--- /srv/reproducible-results/rbuild-debian/r-b-build.dOROL2Vk/b1/libtorrent-rasterbar_2.0.10-1.1_i386.changes +++ /srv/reproducible-results/rbuild-debian/r-b-build.dOROL2Vk/b2/libtorrent-rasterbar_2.0.10-1.1_i386.changes ├── Files │ @@ -1,7 +1,7 @@ │ │ 529fbea61c4f70f812104bf5fb26346f 365476 libdevel optional libtorrent-rasterbar-dev_2.0.10-1.1_i386.deb │ - 33c7e28608d48d52d6e77025957ce880 1669544 doc optional libtorrent-rasterbar-doc_2.0.10-1.1_all.deb │ + a792b5568437163f64c90b29ae206a15 1668988 doc optional libtorrent-rasterbar-doc_2.0.10-1.1_all.deb │ 7e727d1aa4c18a3469f8d9360e073f7a 50322608 debug optional libtorrent-rasterbar2.0t64-dbgsym_2.0.10-1.1_i386.deb │ 9ebf68a28121f2be4b650d1e8fe10040 1823728 libs optional libtorrent-rasterbar2.0t64_2.0.10-1.1_i386.deb │ 419d95e8bbac2dff6c9046302bc7ca4e 13042016 debug optional python3-libtorrent-dbgsym_2.0.10-1.1_i386.deb │ 75bcf4da2366aac4ef0f3391d1787537 732896 python optional python3-libtorrent_2.0.10-1.1_i386.deb ├── libtorrent-rasterbar-doc_2.0.10-1.1_all.deb │ ├── file list │ │ @@ -1,3 +1,3 @@ │ │ -rw-r--r-- 0 0 0 4 2024-02-28 20:35:15.000000 debian-binary │ │ --rw-r--r-- 0 0 0 3632 2024-02-28 20:35:15.000000 control.tar.xz │ │ --rw-r--r-- 0 0 0 1665720 2024-02-28 20:35:15.000000 data.tar.xz │ │ +-rw-r--r-- 0 0 0 3636 2024-02-28 20:35:15.000000 control.tar.xz │ │ +-rw-r--r-- 0 0 0 1665160 2024-02-28 20:35:15.000000 data.tar.xz │ ├── control.tar.xz │ │ ├── control.tar │ │ │ ├── ./md5sums │ │ │ │ ├── ./md5sums │ │ │ │ │┄ Files differ │ ├── data.tar.xz │ │ ├── data.tar │ │ │ ├── file list │ │ │ │ @@ -73,43 +73,43 @@ │ │ │ │ -rw-r--r-- 0 root (0) root (0) 428300 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/img/troubleshooting.png │ │ │ │ -rw-r--r-- 0 root (0) root (0) 46281 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/img/troubleshooting_thumb.png │ │ │ │ -rw-r--r-- 0 root (0) root (0) 243 2024-02-19 12:14:14.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/img/utp_stack.diagram │ │ │ │ -rw-r--r-- 0 root (0) root (0) 2007 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/img/utp_stack.png │ │ │ │ -rw-r--r-- 0 root (0) root (0) 1156 2024-02-19 12:14:14.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/img/write_disk_buffers.diagram │ │ │ │ -rw-r--r-- 0 root (0) root (0) 9631 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/img/write_disk_buffers.png │ │ │ │ -rw-r--r-- 0 root (0) root (0) 9768 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/index.html │ │ │ │ --rw-r--r-- 0 root (0) root (0) 144603 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/manual-ref.html │ │ │ │ +-rw-r--r-- 0 root (0) root (0) 144610 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/manual-ref.html │ │ │ │ -rw-r--r-- 0 root (0) root (0) 9650 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/projects.html │ │ │ │ -rw-r--r-- 0 root (0) root (0) 22814 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/python_binding.html │ │ │ │ -rw-r--r-- 0 root (0) root (0) 33687 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-Add_Torrent.html │ │ │ │ -rw-r--r-- 0 root (0) root (0) 256774 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-Alerts.html │ │ │ │ --rw-r--r-- 0 root (0) root (0) 27441 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-Bdecoding.html │ │ │ │ +-rw-r--r-- 0 root (0) root (0) 27434 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-Bdecoding.html │ │ │ │ -rw-r--r-- 0 root (0) root (0) 25856 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-Bencoding.html │ │ │ │ --rw-r--r-- 0 root (0) root (0) 88949 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-Core.html │ │ │ │ +-rw-r--r-- 0 root (0) root (0) 88956 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-Core.html │ │ │ │ -rw-r--r-- 0 root (0) root (0) 43739 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-Create_Torrents.html │ │ │ │ -rw-r--r-- 0 root (0) root (0) 50884 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-Custom_Storage.html │ │ │ │ -rw-r--r-- 0 root (0) root (0) 24960 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-DHT.html │ │ │ │ -rw-r--r-- 0 root (0) root (0) 48568 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-Error_Codes.html │ │ │ │ -rw-r--r-- 0 root (0) root (0) 13261 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-Filter.html │ │ │ │ -rw-r--r-- 0 root (0) root (0) 12804 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-PeerClass.html │ │ │ │ -rw-r--r-- 0 root (0) root (0) 68487 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-Plugins.html │ │ │ │ -rw-r--r-- 0 root (0) root (0) 9618 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-Resume_Data.html │ │ │ │ --rw-r--r-- 0 root (0) root (0) 101835 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-Session.html │ │ │ │ +-rw-r--r-- 0 root (0) root (0) 101842 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-Session.html │ │ │ │ -rw-r--r-- 0 root (0) root (0) 167853 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-Settings.html │ │ │ │ -rw-r--r-- 0 root (0) root (0) 9742 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-Stats.html │ │ │ │ -rw-r--r-- 0 root (0) root (0) 56856 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-Storage.html │ │ │ │ --rw-r--r-- 0 root (0) root (0) 129801 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-Torrent_Handle.html │ │ │ │ --rw-r--r-- 0 root (0) root (0) 55643 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-Torrent_Info.html │ │ │ │ --rw-r--r-- 0 root (0) root (0) 48266 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-Torrent_Status.html │ │ │ │ --rw-r--r-- 0 root (0) root (0) 16462 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-Trackers.html │ │ │ │ +-rw-r--r-- 0 root (0) root (0) 129829 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-Torrent_Handle.html │ │ │ │ +-rw-r--r-- 0 root (0) root (0) 55640 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-Torrent_Info.html │ │ │ │ +-rw-r--r-- 0 root (0) root (0) 48273 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-Torrent_Status.html │ │ │ │ +-rw-r--r-- 0 root (0) root (0) 16461 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-Trackers.html │ │ │ │ -rw-r--r-- 0 root (0) root (0) 25530 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-Utility.html │ │ │ │ -rw-r--r-- 0 root (0) root (0) 9129 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-ed25519.html │ │ │ │ -rw-r--r-- 0 root (0) root (0) 34353 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/reference.html │ │ │ │ -rw-r--r-- 0 root (0) root (0) 29242 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/security-audit.html │ │ │ │ --rw-r--r-- 0 root (0) root (0) 1272265 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/single-page-ref.html │ │ │ │ +-rw-r--r-- 0 root (0) root (0) 1272303 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/single-page-ref.html │ │ │ │ -rw-r--r-- 0 root (0) root (0) 10121 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/streaming.html │ │ │ │ -rw-r--r-- 0 root (0) root (0) 8807 2024-02-19 12:14:14.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/style.css │ │ │ │ -rw-r--r-- 0 root (0) root (0) 522811 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/todo.html │ │ │ │ -rw-r--r-- 0 root (0) root (0) 3023 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/troubleshooting.html │ │ │ │ -rw-r--r-- 0 root (0) root (0) 25162 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/tuning-ref.html │ │ │ │ -rw-r--r-- 0 root (0) root (0) 132630 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/tutorial-ref.html │ │ │ │ -rw-r--r-- 0 root (0) root (0) 16383 2024-02-28 20:35:15.000000 ./usr/share/doc/libtorrent-rasterbar-doc/html/udp_tracker_protocol.html │ │ │ ├── ./usr/share/doc/libtorrent-rasterbar-doc/html/manual-ref.html │ │ │ │ @@ -100,15 +100,15 @@ │ │ │ │ the session, it contains the main loop that serves all torrents.

│ │ │ │

The basic usage is as follows:

│ │ │ │ │ │ │ │ │ │ │ │
  • torrent_removed_alert
  • │ │ │ │
  • read_piece_alert
  • │ │ │ │
  • file_completed_alert
  • │ │ │ │
  • file_renamed_alert │ │ │ │
  • │ │ │ │
  • file_rename_failed_alert
  • │ │ │ │
  • performance_alert │ │ │ │
  • │ │ │ │ @@ -191,15 +191,15 @@ │ │ │ │ │ │ │ │ │ │ │ │
  • dht_get_peers_reply_alert
  • │ │ │ │
  • dht_direct_response_alert
  • │ │ │ │
  • picker_log_alert
  • │ │ │ │
  • session_error_alert
  • │ │ │ │
  • dht_live_nodes_alert │ │ │ │
  • │ │ │ │
  • session_stats_header_alert
  • │ │ │ │
  • dht_sample_infohashes_alert │ │ │ │ @@ -57,50 +57,50 @@ │ │ │ │ │ │ │ │ [report issue]
    │ │ │ │

    bdecode_node

    │ │ │ │

    Declared in "libtorrent/bdecode.hpp"

    │ │ │ │

    Sometimes it's important to get a non-owning reference to the root node ( │ │ │ │ to be able to copy it as a reference for instance). For that, use the │ │ │ │ non_owning() member function.

    │ │ │ │ -

    There are 5 different types of nodes, see type_t.

    │ │ │ │ +

    There are 5 different types of nodes, see type_t.

    │ │ │ │
    │ │ │ │  struct bdecode_node
    │ │ │ │  {
    │ │ │ │     bdecode_node () = default;
    │ │ │ │ -   bdecode_node (bdecode_node const&);
    │ │ │ │ +   bdecode_node (bdecode_node&&) noexcept;
    │ │ │ │     bdecode_node& operator= (bdecode_node const&) &;
    │ │ │ │     bdecode_node& operator= (bdecode_node&&) & = default;
    │ │ │ │ -   bdecode_node (bdecode_node&&) noexcept;
    │ │ │ │ +   bdecode_node (bdecode_node const&);
    │ │ │ │     type_t type () const noexcept;
    │ │ │ │     explicit operator bool () const noexcept;
    │ │ │ │     bdecode_node non_owning () const;
    │ │ │ │     span<char const> data_section () const noexcept;
    │ │ │ │     std::ptrdiff_t data_offset () const noexcept;
    │ │ │ │ +   std::int64_t list_int_value_at (int i
    │ │ │ │ +      , std::int64_t default_val = 0) const;
    │ │ │ │ +   int list_size () const;
    │ │ │ │     string_view list_string_value_at (int i
    │ │ │ │        , string_view default_val = string_view()) const;
    │ │ │ │     bdecode_node list_at (int i) const;
    │ │ │ │ -   std::int64_t list_int_value_at (int i
    │ │ │ │ +   string_view dict_find_string_value (string_view key
    │ │ │ │ +      , string_view default_value = string_view()) const;
    │ │ │ │ +   std::int64_t dict_find_int_value (string_view key
    │ │ │ │        , std::int64_t default_val = 0) const;
    │ │ │ │ -   int list_size () const;
    │ │ │ │ -   bdecode_node dict_find_dict (string_view key) const;
    │ │ │ │ +   bdecode_node dict_find (string_view key) const;
    │ │ │ │ +   bdecode_node dict_find_list (string_view key) const;
    │ │ │ │     std::pair<string_view, bdecode_node> dict_at (int i) const;
    │ │ │ │ -   int dict_size () const;
    │ │ │ │ +   bdecode_node dict_find_dict (string_view key) const;
    │ │ │ │     std::pair<bdecode_node, bdecode_node> dict_at_node (int i) const;
    │ │ │ │ -   std::int64_t dict_find_int_value (string_view key
    │ │ │ │ -      , std::int64_t default_val = 0) const;
    │ │ │ │     bdecode_node dict_find_int (string_view key) const;
    │ │ │ │ -   bdecode_node dict_find_list (string_view key) const;
    │ │ │ │ +   int dict_size () const;
    │ │ │ │     bdecode_node dict_find_string (string_view key) const;
    │ │ │ │ -   string_view dict_find_string_value (string_view key
    │ │ │ │ -      , string_view default_value = string_view()) const;
    │ │ │ │ -   bdecode_node dict_find (string_view key) const;
    │ │ │ │     std::int64_t int_value () const;
    │ │ │ │ +   char const* string_ptr () const;
    │ │ │ │     int string_length () const;
    │ │ │ │     string_view string_value () const;
    │ │ │ │ -   char const* string_ptr () const;
    │ │ │ │     std::ptrdiff_t string_offset () const;
    │ │ │ │     void clear ();
    │ │ │ │     void swap (bdecode_node& n);
    │ │ │ │     void reserve (int tokens);
    │ │ │ │     void switch_underlying_buffer (char const* buf) noexcept;
    │ │ │ │     bool has_soft_error (span<char> error) const;
    │ │ │ │  
    │ │ │ │ @@ -121,35 +121,35 @@
    │ │ │ │  
    │ │ │ │

    creates a default constructed node, it will have the type none_t.

    │ │ │ │ │ │ │ │ [report issue]
    │ │ │ │
    │ │ │ │

    operator=() bdecode_node()

    │ │ │ │
    │ │ │ │ -bdecode_node (bdecode_node const&);
    │ │ │ │ +bdecode_node (bdecode_node&&) noexcept;
    │ │ │ │  bdecode_node& operator= (bdecode_node const&) &;
    │ │ │ │  bdecode_node& operator= (bdecode_node&&) & = default;
    │ │ │ │ -bdecode_node (bdecode_node&&) noexcept;
    │ │ │ │ +bdecode_node (bdecode_node const&);
    │ │ │ │  
    │ │ │ │

    For owning nodes, the copy will create a copy of the tree, but the │ │ │ │ underlying buffer remains the same.

    │ │ │ │ [report issue]
    │ │ │ │
    │ │ │ │

    type()

    │ │ │ │
    │ │ │ │  type_t type () const noexcept;
    │ │ │ │  
    │ │ │ │ -

    the type of this node. See type_t.

    │ │ │ │ +

    the type of this node. See type_t.

    │ │ │ │ [report issue]
    │ │ │ │
    │ │ │ │

    bool()

    │ │ │ │
    │ │ │ │  explicit operator bool () const noexcept;
    │ │ │ │  
    │ │ │ │ -

    returns true if type() != none_t.

    │ │ │ │ +

    returns true if type() != none_t.

    │ │ │ │ [report issue]
    │ │ │ │
    │ │ │ │

    non_owning()

    │ │ │ │
    │ │ │ │  bdecode_node non_owning () const;
    │ │ │ │  
    │ │ │ │

    return a non-owning reference to this node. This is useful to refer to │ │ │ │ @@ -171,50 +171,50 @@ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ [report issue]

    │ │ │ │
    │ │ │ │

    list_int_value_at() list_size() list_at() list_string_value_at()

    │ │ │ │
    │ │ │ │ -string_view list_string_value_at (int i
    │ │ │ │ -      , string_view default_val = string_view()) const;
    │ │ │ │ -bdecode_node list_at (int i) const;
    │ │ │ │  std::int64_t list_int_value_at (int i
    │ │ │ │        , std::int64_t default_val = 0) const;
    │ │ │ │  int list_size () const;
    │ │ │ │ +string_view list_string_value_at (int i
    │ │ │ │ +      , string_view default_val = string_view()) const;
    │ │ │ │ +bdecode_node list_at (int i) const;
    │ │ │ │  
    │ │ │ │

    functions with the list_ prefix operate on lists. These functions are │ │ │ │ only valid if type() == list_t. list_at() returns the item │ │ │ │ in the list at index i. i may not be greater than or equal to the │ │ │ │ size of the list. size() returns the size of the list.

    │ │ │ │ + │ │ │ │ │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ │ │ │ │ - │ │ │ │ │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ + │ │ │ │ │ │ │ │ -[report issue]
    │ │ │ │ -
    │ │ │ │ -

    dict_at() dict_find_int_value() dict_find_string_value() dict_find_list() dict_size() dict_find() dict_find_string() dict_find_dict() dict_at_node() dict_find_int()

    │ │ │ │ +[report issue]
    │ │ │ │ +
    │ │ │ │ +

    dict_find_string() dict_at() dict_find_dict() dict_find_int() dict_find() dict_find_int_value() dict_find_list() dict_find_string_value() dict_at_node() dict_size()

    │ │ │ │
    │ │ │ │ -bdecode_node dict_find_dict (string_view key) const;
    │ │ │ │ -std::pair<string_view, bdecode_node> dict_at (int i) const;
    │ │ │ │ -int dict_size () const;
    │ │ │ │ -std::pair<bdecode_node, bdecode_node> dict_at_node (int i) const;
    │ │ │ │ +string_view dict_find_string_value (string_view key
    │ │ │ │ +      , string_view default_value = string_view()) const;
    │ │ │ │  std::int64_t dict_find_int_value (string_view key
    │ │ │ │        , std::int64_t default_val = 0) const;
    │ │ │ │ -bdecode_node dict_find_int (string_view key) const;
    │ │ │ │ +bdecode_node dict_find (string_view key) const;
    │ │ │ │  bdecode_node dict_find_list (string_view key) const;
    │ │ │ │ +std::pair<string_view, bdecode_node> dict_at (int i) const;
    │ │ │ │ +bdecode_node dict_find_dict (string_view key) const;
    │ │ │ │ +std::pair<bdecode_node, bdecode_node> dict_at_node (int i) const;
    │ │ │ │ +bdecode_node dict_find_int (string_view key) const;
    │ │ │ │ +int dict_size () const;
    │ │ │ │  bdecode_node dict_find_string (string_view key) const;
    │ │ │ │ -string_view dict_find_string_value (string_view key
    │ │ │ │ -      , string_view default_value = string_view()) const;
    │ │ │ │ -bdecode_node dict_find (string_view key) const;
    │ │ │ │  
    │ │ │ │

    Functions with the dict_ prefix operates on dictionaries. They are │ │ │ │ only valid if type() == dict_t. In case a key you're looking up │ │ │ │ contains a 0 byte, you cannot use the 0-terminated string overloads, │ │ │ │ but have to use string_view instead. dict_find_list will return a │ │ │ │ valid bdecode_node if the key is found _and_ it is a list. Otherwise │ │ │ │ it will return a default-constructed bdecode_node.

    │ │ │ │ @@ -230,23 +230,23 @@ │ │ │ │

    int_value()

    │ │ │ │
    │ │ │ │  std::int64_t int_value () const;
    │ │ │ │  
    │ │ │ │

    this function is only valid if type() == int_t. It returns the │ │ │ │ value of the integer.

    │ │ │ │ │ │ │ │ + │ │ │ │ │ │ │ │ - │ │ │ │ -[report issue]
    │ │ │ │ -
    │ │ │ │ -

    string_ptr() string_length() string_offset() string_value()

    │ │ │ │ +[report issue]
    │ │ │ │ +
    │ │ │ │ +

    string_ptr() string_value() string_length() string_offset()

    │ │ │ │
    │ │ │ │ +char const* string_ptr () const;
    │ │ │ │  int string_length () const;
    │ │ │ │  string_view string_value () const;
    │ │ │ │ -char const* string_ptr () const;
    │ │ │ │  std::ptrdiff_t string_offset () const;
    │ │ │ │  
    │ │ │ │

    these functions are only valid if type() == string_t. They return │ │ │ │ the string values. Note that string_ptr() is not 0-terminated. │ │ │ │ string_length() returns the number of bytes in the string. │ │ │ │ string_offset() returns the byte offset from the start of the parsed │ │ │ │ bencoded buffer this string can be found.

    │ │ │ │ ├── html2text {} │ │ │ │ │ @@ -7,19 +7,19 @@ │ │ │ │ │ o _b_d_e_c_o_d_e___n_o_d_e_(_) │ │ │ │ │ o _o_p_e_r_a_t_o_r_=_(_)_ _b_d_e_c_o_d_e___n_o_d_e_(_) │ │ │ │ │ o _t_y_p_e_(_) │ │ │ │ │ o _b_o_o_l_(_) │ │ │ │ │ o _n_o_n___o_w_n_i_n_g_(_) │ │ │ │ │ o _d_a_t_a___s_e_c_t_i_o_n_(_)_ _d_a_t_a___o_f_f_s_e_t_(_) │ │ │ │ │ o _l_i_s_t___i_n_t___v_a_l_u_e___a_t_(_)_ _l_i_s_t___s_i_z_e_(_)_ _l_i_s_t___a_t_(_)_ _l_i_s_t___s_t_r_i_n_g___v_a_l_u_e___a_t_(_) │ │ │ │ │ - o _d_i_c_t___a_t_(_)_ _d_i_c_t___f_i_n_d___i_n_t___v_a_l_u_e_(_)_ _d_i_c_t___f_i_n_d___s_t_r_i_n_g___v_a_l_u_e_(_) │ │ │ │ │ - _d_i_c_t___f_i_n_d___l_i_s_t_(_)_ _d_i_c_t___s_i_z_e_(_)_ _d_i_c_t___f_i_n_d_(_)_ _d_i_c_t___f_i_n_d___s_t_r_i_n_g_(_) │ │ │ │ │ - _d_i_c_t___f_i_n_d___d_i_c_t_(_)_ _d_i_c_t___a_t___n_o_d_e_(_)_ _d_i_c_t___f_i_n_d___i_n_t_(_) │ │ │ │ │ + o _d_i_c_t___f_i_n_d___s_t_r_i_n_g_(_)_ _d_i_c_t___a_t_(_)_ _d_i_c_t___f_i_n_d___d_i_c_t_(_)_ _d_i_c_t___f_i_n_d___i_n_t_(_) │ │ │ │ │ + _d_i_c_t___f_i_n_d_(_)_ _d_i_c_t___f_i_n_d___i_n_t___v_a_l_u_e_(_)_ _d_i_c_t___f_i_n_d___l_i_s_t_(_) │ │ │ │ │ + _d_i_c_t___f_i_n_d___s_t_r_i_n_g___v_a_l_u_e_(_)_ _d_i_c_t___a_t___n_o_d_e_(_)_ _d_i_c_t___s_i_z_e_(_) │ │ │ │ │ o _i_n_t___v_a_l_u_e_(_) │ │ │ │ │ - o _s_t_r_i_n_g___p_t_r_(_)_ _s_t_r_i_n_g___l_e_n_g_t_h_(_)_ _s_t_r_i_n_g___o_f_f_s_e_t_(_)_ _s_t_r_i_n_g___v_a_l_u_e_(_) │ │ │ │ │ + o _s_t_r_i_n_g___p_t_r_(_)_ _s_t_r_i_n_g___v_a_l_u_e_(_)_ _s_t_r_i_n_g___l_e_n_g_t_h_(_)_ _s_t_r_i_n_g___o_f_f_s_e_t_(_) │ │ │ │ │ o _c_l_e_a_r_(_) │ │ │ │ │ o _s_w_a_p_(_) │ │ │ │ │ o _r_e_s_e_r_v_e_(_) │ │ │ │ │ o _s_w_i_t_c_h___u_n_d_e_r_l_y_i_n_g___b_u_f_f_e_r_(_) │ │ │ │ │ o _h_a_s___s_o_f_t___e_r_r_o_r_(_) │ │ │ │ │ o _e_n_u_m_ _t_y_p_e___t │ │ │ │ │ * _p_r_i_n_t___e_n_t_r_y_(_) │ │ │ │ │ @@ -30,45 +30,45 @@ │ │ │ │ │ Sometimes it's important to get a non-owning reference to the root node ( to be │ │ │ │ │ able to copy it as a reference for instance). For that, use the _n_o_n___o_w_n_i_n_g_(_) │ │ │ │ │ member function. │ │ │ │ │ There are 5 different types of nodes, see _t_y_p_e___t. │ │ │ │ │ struct bdecode_node │ │ │ │ │ { │ │ │ │ │ bbddeeccooddee__nnooddee () = default; │ │ │ │ │ - bbddeeccooddee__nnooddee (bdecode_node const&); │ │ │ │ │ + bbddeeccooddee__nnooddee (bdecode_node&&) noexcept; │ │ │ │ │ bdecode_node& ooppeerraattoorr== (bdecode_node const&) &; │ │ │ │ │ bdecode_node& ooppeerraattoorr== (bdecode_node&&) & = default; │ │ │ │ │ - bbddeeccooddee__nnooddee (bdecode_node&&) noexcept; │ │ │ │ │ + bbddeeccooddee__nnooddee (bdecode_node const&); │ │ │ │ │ type_t ttyyppee () const noexcept; │ │ │ │ │ explicit operator bbooooll () const noexcept; │ │ │ │ │ bdecode_node nnoonn__oowwnniinngg () const; │ │ │ │ │ span ddaattaa__sseeccttiioonn () const noexcept; │ │ │ │ │ std::ptrdiff_t ddaattaa__ooffffsseett () const noexcept; │ │ │ │ │ + std::int64_t lliisstt__iinntt__vvaalluuee__aatt (int i │ │ │ │ │ + , std::int64_t default_val = 0) const; │ │ │ │ │ + int lliisstt__ssiizzee () const; │ │ │ │ │ string_view lliisstt__ssttrriinngg__vvaalluuee__aatt (int i │ │ │ │ │ , string_view default_val = string_view()) const; │ │ │ │ │ bdecode_node lliisstt__aatt (int i) const; │ │ │ │ │ - std::int64_t lliisstt__iinntt__vvaalluuee__aatt (int i │ │ │ │ │ + string_view ddiicctt__ffiinndd__ssttrriinngg__vvaalluuee (string_view key │ │ │ │ │ + , string_view default_value = string_view()) const; │ │ │ │ │ + std::int64_t ddiicctt__ffiinndd__iinntt__vvaalluuee (string_view key │ │ │ │ │ , std::int64_t default_val = 0) const; │ │ │ │ │ - int lliisstt__ssiizzee () const; │ │ │ │ │ - bdecode_node ddiicctt__ffiinndd__ddiicctt (string_view key) const; │ │ │ │ │ + bdecode_node ddiicctt__ffiinndd (string_view key) const; │ │ │ │ │ + bdecode_node ddiicctt__ffiinndd__lliisstt (string_view key) const; │ │ │ │ │ std::pair ddiicctt__aatt (int i) const; │ │ │ │ │ - int ddiicctt__ssiizzee () const; │ │ │ │ │ + bdecode_node ddiicctt__ffiinndd__ddiicctt (string_view key) const; │ │ │ │ │ std::pair ddiicctt__aatt__nnooddee (int i) const; │ │ │ │ │ - std::int64_t ddiicctt__ffiinndd__iinntt__vvaalluuee (string_view key │ │ │ │ │ - , std::int64_t default_val = 0) const; │ │ │ │ │ bdecode_node ddiicctt__ffiinndd__iinntt (string_view key) const; │ │ │ │ │ - bdecode_node ddiicctt__ffiinndd__lliisstt (string_view key) const; │ │ │ │ │ + int ddiicctt__ssiizzee () const; │ │ │ │ │ bdecode_node ddiicctt__ffiinndd__ssttrriinngg (string_view key) const; │ │ │ │ │ - string_view ddiicctt__ffiinndd__ssttrriinngg__vvaalluuee (string_view key │ │ │ │ │ - , string_view default_value = string_view()) const; │ │ │ │ │ - bdecode_node ddiicctt__ffiinndd (string_view key) const; │ │ │ │ │ std::int64_t iinntt__vvaalluuee () const; │ │ │ │ │ + char const* ssttrriinngg__ppttrr () const; │ │ │ │ │ int ssttrriinngg__lleennggtthh () const; │ │ │ │ │ string_view ssttrriinngg__vvaalluuee () const; │ │ │ │ │ - char const* ssttrriinngg__ppttrr () const; │ │ │ │ │ std::ptrdiff_t ssttrriinngg__ooffffsseett () const; │ │ │ │ │ void cclleeaarr (); │ │ │ │ │ void sswwaapp (bdecode_node& n); │ │ │ │ │ void rreesseerrvvee (int tokens); │ │ │ │ │ void sswwiittcchh__uunnddeerrllyyiinngg__bbuuffffeerr (char const* buf) noexcept; │ │ │ │ │ bool hhaass__ssoofftt__eerrrroorr (span error) const; │ │ │ │ │ │ │ │ │ │ @@ -83,18 +83,18 @@ │ │ │ │ │ }; │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ********** bbddeeccooddee__nnooddee(()) ********** │ │ │ │ │ bbddeeccooddee__nnooddee () = default; │ │ │ │ │ creates a default constructed node, it will have the type none_t. │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ********** ooppeerraattoorr==(()) bbddeeccooddee__nnooddee(()) ********** │ │ │ │ │ -bbddeeccooddee__nnooddee (bdecode_node const&); │ │ │ │ │ +bbddeeccooddee__nnooddee (bdecode_node&&) noexcept; │ │ │ │ │ bdecode_node& ooppeerraattoorr== (bdecode_node const&) &; │ │ │ │ │ bdecode_node& ooppeerraattoorr== (bdecode_node&&) & = default; │ │ │ │ │ -bbddeeccooddee__nnooddee (bdecode_node&&) noexcept; │ │ │ │ │ +bbddeeccooddee__nnooddee (bdecode_node const&); │ │ │ │ │ For owning nodes, the copy will create a copy of the tree, but the underlying │ │ │ │ │ buffer remains the same. │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ********** ttyyppee(()) ********** │ │ │ │ │ type_t ttyyppee () const noexcept; │ │ │ │ │ the type of this node. See _t_y_p_e___t. │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ @@ -113,40 +113,40 @@ │ │ │ │ │ returns the buffer and length of the section in the original bencoded buffer │ │ │ │ │ where this node is defined. For a dictionary for instance, this starts with d │ │ │ │ │ and ends with e, and has all the content of the dictionary in between. the │ │ │ │ │ data_offset() function returns the byte-offset to this node in, starting from │ │ │ │ │ the beginning of the buffer that was parsed. │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ********** lliisstt__iinntt__vvaalluuee__aatt(()) lliisstt__ssiizzee(()) lliisstt__aatt(()) lliisstt__ssttrriinngg__vvaalluuee__aatt(()) ********** │ │ │ │ │ -string_view lliisstt__ssttrriinngg__vvaalluuee__aatt (int i │ │ │ │ │ - , string_view default_val = string_view()) const; │ │ │ │ │ -bdecode_node lliisstt__aatt (int i) const; │ │ │ │ │ std::int64_t lliisstt__iinntt__vvaalluuee__aatt (int i │ │ │ │ │ , std::int64_t default_val = 0) const; │ │ │ │ │ int lliisstt__ssiizzee () const; │ │ │ │ │ +string_view lliisstt__ssttrriinngg__vvaalluuee__aatt (int i │ │ │ │ │ + , string_view default_val = string_view()) const; │ │ │ │ │ +bdecode_node lliisstt__aatt (int i) const; │ │ │ │ │ functions with the list_ prefix operate on lists. These functions are only │ │ │ │ │ valid if type() == list_t. list_at() returns the item in the list at index i. i │ │ │ │ │ may not be greater than or equal to the size of the list. size() returns the │ │ │ │ │ size of the list. │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ -********** ddiicctt__aatt(()) ddiicctt__ffiinndd__iinntt__vvaalluuee(()) ddiicctt__ffiinndd__ssttrriinngg__vvaalluuee(()) ddiicctt__ffiinndd__lliisstt(()) │ │ │ │ │ -ddiicctt__ssiizzee(()) ddiicctt__ffiinndd(()) ddiicctt__ffiinndd__ssttrriinngg(()) ddiicctt__ffiinndd__ddiicctt(()) ddiicctt__aatt__nnooddee(()) │ │ │ │ │ -ddiicctt__ffiinndd__iinntt(()) ********** │ │ │ │ │ -bdecode_node ddiicctt__ffiinndd__ddiicctt (string_view key) const; │ │ │ │ │ -std::pair ddiicctt__aatt (int i) const; │ │ │ │ │ -int ddiicctt__ssiizzee () const; │ │ │ │ │ -std::pair ddiicctt__aatt__nnooddee (int i) const; │ │ │ │ │ +********** ddiicctt__ffiinndd__ssttrriinngg(()) ddiicctt__aatt(()) ddiicctt__ffiinndd__ddiicctt(()) ddiicctt__ffiinndd__iinntt(()) ddiicctt__ffiinndd(()) │ │ │ │ │ +ddiicctt__ffiinndd__iinntt__vvaalluuee(()) ddiicctt__ffiinndd__lliisstt(()) ddiicctt__ffiinndd__ssttrriinngg__vvaalluuee(()) ddiicctt__aatt__nnooddee(()) │ │ │ │ │ +ddiicctt__ssiizzee(()) ********** │ │ │ │ │ +string_view ddiicctt__ffiinndd__ssttrriinngg__vvaalluuee (string_view key │ │ │ │ │ + , string_view default_value = string_view()) const; │ │ │ │ │ std::int64_t ddiicctt__ffiinndd__iinntt__vvaalluuee (string_view key │ │ │ │ │ , std::int64_t default_val = 0) const; │ │ │ │ │ -bdecode_node ddiicctt__ffiinndd__iinntt (string_view key) const; │ │ │ │ │ +bdecode_node ddiicctt__ffiinndd (string_view key) const; │ │ │ │ │ bdecode_node ddiicctt__ffiinndd__lliisstt (string_view key) const; │ │ │ │ │ +std::pair ddiicctt__aatt (int i) const; │ │ │ │ │ +bdecode_node ddiicctt__ffiinndd__ddiicctt (string_view key) const; │ │ │ │ │ +std::pair ddiicctt__aatt__nnooddee (int i) const; │ │ │ │ │ +bdecode_node ddiicctt__ffiinndd__iinntt (string_view key) const; │ │ │ │ │ +int ddiicctt__ssiizzee () const; │ │ │ │ │ bdecode_node ddiicctt__ffiinndd__ssttrriinngg (string_view key) const; │ │ │ │ │ -string_view ddiicctt__ffiinndd__ssttrriinngg__vvaalluuee (string_view key │ │ │ │ │ - , string_view default_value = string_view()) const; │ │ │ │ │ -bdecode_node ddiicctt__ffiinndd (string_view key) const; │ │ │ │ │ Functions with the dict_ prefix operates on dictionaries. They are only valid │ │ │ │ │ if type() == dict_t. In case a key you're looking up contains a 0 byte, you │ │ │ │ │ cannot use the 0-terminated string overloads, but have to use string_view │ │ │ │ │ instead. dict_find_list will return a valid bdecode_node if the key is found │ │ │ │ │ _and_ it is a list. Otherwise it will return a default-constructed │ │ │ │ │ _b_d_e_c_o_d_e___n_o_d_e. │ │ │ │ │ Functions with the _value suffix return the value of the node directly, rather │ │ │ │ │ @@ -158,18 +158,18 @@ │ │ │ │ │ string). │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ********** iinntt__vvaalluuee(()) ********** │ │ │ │ │ std::int64_t iinntt__vvaalluuee () const; │ │ │ │ │ this function is only valid if type() == int_t. It returns the value of the │ │ │ │ │ integer. │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ -********** ssttrriinngg__ppttrr(()) ssttrriinngg__lleennggtthh(()) ssttrriinngg__ooffffsseett(()) ssttrriinngg__vvaalluuee(()) ********** │ │ │ │ │ +********** ssttrriinngg__ppttrr(()) ssttrriinngg__vvaalluuee(()) ssttrriinngg__lleennggtthh(()) ssttrriinngg__ooffffsseett(()) ********** │ │ │ │ │ +char const* ssttrriinngg__ppttrr () const; │ │ │ │ │ int ssttrriinngg__lleennggtthh () const; │ │ │ │ │ string_view ssttrriinngg__vvaalluuee () const; │ │ │ │ │ -char const* ssttrriinngg__ppttrr () const; │ │ │ │ │ std::ptrdiff_t ssttrriinngg__ooffffsseett () const; │ │ │ │ │ these functions are only valid if type() == string_t. They return the string │ │ │ │ │ values. Note that string_ptr() is nnoott 0-terminated. string_length() returns the │ │ │ │ │ number of bytes in the string. string_offset() returns the byte offset from the │ │ │ │ │ start of the parsed bencoded buffer this string can be found. │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ********** cclleeaarr(()) ********** │ │ │ ├── ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-Bencoding.html │ │ │ │ @@ -34,15 +34,15 @@ │ │ │ │
      │ │ │ │
    • entry │ │ │ │
    • │ │ │ │ @@ -69,44 +69,44 @@ │ │ │ │

      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.

      │ │ │ │
      │ │ │ │  class entry
      │ │ │ │  {
      │ │ │ │     data_type type () const;
      │ │ │ │ -   entry (list_type);
      │ │ │ │ -   entry (integer_type);
      │ │ │ │     entry (span<char const>);
      │ │ │ │ -   entry (preformatted_type);
      │ │ │ │     entry (dictionary_type);
      │ │ │ │ +   entry (preformatted_type);
      │ │ │ │ +   entry (list_type);
      │ │ │ │ +   entry (integer_type);
      │ │ │ │     entry (U v);
      │ │ │ │     entry (data_type t);
      │ │ │ │     entry (bdecode_node const& n);
      │ │ │ │ -   entry& operator= (preformatted_type) &;
      │ │ │ │ -   entry& operator= (list_type) &;
      │ │ │ │     entry& operator= (bdecode_node const&) &;
      │ │ │ │ -   entry& operator= (entry&&) & noexcept;
      │ │ │ │     entry& operator= (dictionary_type) &;
      │ │ │ │ -   entry& operator= (span<char const>) &;
      │ │ │ │ -   entry& operator= (integer_type) &;
      │ │ │ │ +   entry& operator= (entry&&) & noexcept;
      │ │ │ │ +   entry& operator= (preformatted_type) &;
      │ │ │ │     entry& operator= (entry const&) &;
      │ │ │ │ +   entry& operator= (list_type) &;
      │ │ │ │ +   entry& operator= (integer_type) &;
      │ │ │ │ +   entry& operator= (span<char const>) &;
      │ │ │ │     entry& operator= (U v) &;
      │ │ │ │ -   string_type const& string () const;
      │ │ │ │ -   preformatted_type& preformatted ();
      │ │ │ │ -   integer_type& integer ();
      │ │ │ │     integer_type const& integer () const;
      │ │ │ │     dictionary_type& dict ();
      │ │ │ │ -   list_type const& list () const;
      │ │ │ │     preformatted_type const& preformatted () const;
      │ │ │ │ +   integer_type& integer ();
      │ │ │ │ +   string_type const& string () const;
      │ │ │ │ +   list_type const& list () const;
      │ │ │ │ +   string_type& string ();
      │ │ │ │     dictionary_type const& dict () const;
      │ │ │ │     list_type& list ();
      │ │ │ │ -   string_type& string ();
      │ │ │ │ +   preformatted_type& preformatted ();
      │ │ │ │     void swap (entry& e);
      │ │ │ │ -   entry const& operator[] (string_view key) const;
      │ │ │ │     entry& operator[] (string_view key);
      │ │ │ │ +   entry const& operator[] (string_view key) const;
      │ │ │ │     entry const* find_key (string_view key) const;
      │ │ │ │     entry* find_key (string_view key);
      │ │ │ │     std::string to_string (bool single_line = false) const;
      │ │ │ │  
      │ │ │ │     enum data_type
      │ │ │ │     {
      │ │ │ │        int_t,
      │ │ │ │ @@ -124,19 +124,19 @@
      │ │ │ │  data_type type () const;
      │ │ │ │  
      │ │ │ │

      returns the concrete type of the entry

      │ │ │ │ [report issue]
    │ │ │ │
    │ │ │ │

    entry()

    │ │ │ │
    │ │ │ │ -entry (list_type);
    │ │ │ │ -entry (integer_type);
    │ │ │ │  entry (span<char const>);
    │ │ │ │ -entry (preformatted_type);
    │ │ │ │  entry (dictionary_type);
    │ │ │ │ +entry (preformatted_type);
    │ │ │ │ +entry (list_type);
    │ │ │ │ +entry (integer_type);
    │ │ │ │  
    │ │ │ │

    constructors directly from a specific type. │ │ │ │ The content of the argument is copied into the │ │ │ │ newly constructed entry

    │ │ │ │ [report issue]
    │ │ │ │
    │ │ │ │

    entry()

    │ │ │ │ @@ -152,43 +152,43 @@ │ │ │ │ entry (bdecode_node const& n); │ │ │ │ │ │ │ │

    construct from bdecode_node parsed form (see bdecode())

    │ │ │ │ [report issue]
    │ │ │ │
    │ │ │ │

    operator=()

    │ │ │ │
    │ │ │ │ -entry& operator= (preformatted_type) &;
    │ │ │ │ -entry& operator= (list_type) &;
    │ │ │ │  entry& operator= (bdecode_node const&) &;
    │ │ │ │ -entry& operator= (entry&&) & noexcept;
    │ │ │ │  entry& operator= (dictionary_type) &;
    │ │ │ │ -entry& operator= (span<char const>) &;
    │ │ │ │ -entry& operator= (integer_type) &;
    │ │ │ │ +entry& operator= (entry&&) & noexcept;
    │ │ │ │ +entry& operator= (preformatted_type) &;
    │ │ │ │  entry& operator= (entry const&) &;
    │ │ │ │ +entry& operator= (list_type) &;
    │ │ │ │ +entry& operator= (integer_type) &;
    │ │ │ │ +entry& operator= (span<char const>) &;
    │ │ │ │  
    │ │ │ │

    copies the structure of the right hand side into this │ │ │ │ entry.

    │ │ │ │ + │ │ │ │ + │ │ │ │ │ │ │ │ │ │ │ │ - │ │ │ │ - │ │ │ │ -[report issue]
    │ │ │ │ -
    │ │ │ │ -

    list() integer() preformatted() string() dict()

    │ │ │ │ +[report issue]
    │ │ │ │ +
    │ │ │ │ +

    string() dict() list() integer() preformatted()

    │ │ │ │
    │ │ │ │ -string_type const& string () const;
    │ │ │ │ -preformatted_type& preformatted ();
    │ │ │ │ -integer_type& integer ();
    │ │ │ │  integer_type const& integer () const;
    │ │ │ │  dictionary_type& dict ();
    │ │ │ │ -list_type const& list () const;
    │ │ │ │  preformatted_type const& preformatted () const;
    │ │ │ │ +integer_type& integer ();
    │ │ │ │ +string_type const& string () const;
    │ │ │ │ +list_type const& list () const;
    │ │ │ │ +string_type& string ();
    │ │ │ │  dictionary_type const& dict () const;
    │ │ │ │  list_type& list ();
    │ │ │ │ -string_type& string ();
    │ │ │ │ +preformatted_type& preformatted ();
    │ │ │ │  
    │ │ │ │

    The integer(), string(), list() and dict() functions │ │ │ │ are accessors that return the respective type. If the entry object │ │ │ │ isn't of the type you request, the accessor will throw │ │ │ │ system_error. You can ask an entry for its type through the │ │ │ │ type() function.

    │ │ │ │

    If you want to create an entry you give it the type you want it to │ │ │ │ @@ -232,16 +232,16 @@ │ │ │ │ void swap (entry& e); │ │ │ │ │ │ │ │

    swaps the content of this with e.

    │ │ │ │ [report issue]
    │ │ │ │
    │ │ │ │

    operator[]()

    │ │ │ │
    │ │ │ │ -entry const& operator[] (string_view key) const;
    │ │ │ │  entry& operator[] (string_view key);
    │ │ │ │ +entry const& operator[] (string_view key) const;
    │ │ │ │  
    │ │ │ │

    All of these functions requires the entry to be a dictionary, if it │ │ │ │ isn't they will throw system_error.

    │ │ │ │

    The non-const versions of the operator[] will return a reference │ │ │ │ to either the existing element at the given key or, if there is no │ │ │ │ element with the given key, a reference to a newly inserted element at │ │ │ │ that key.

    │ │ │ │ ├── html2text {} │ │ │ │ │ @@ -5,15 +5,15 @@ │ │ │ │ │ Table of contents │ │ │ │ │ * _e_n_t_r_y │ │ │ │ │ o _t_y_p_e_(_) │ │ │ │ │ o _e_n_t_r_y_(_) │ │ │ │ │ o _e_n_t_r_y_(_) │ │ │ │ │ o _e_n_t_r_y_(_) │ │ │ │ │ o _o_p_e_r_a_t_o_r_=_(_) │ │ │ │ │ - o _l_i_s_t_(_)_ _i_n_t_e_g_e_r_(_)_ _p_r_e_f_o_r_m_a_t_t_e_d_(_)_ _s_t_r_i_n_g_(_)_ _d_i_c_t_(_) │ │ │ │ │ + o _s_t_r_i_n_g_(_)_ _d_i_c_t_(_)_ _l_i_s_t_(_)_ _i_n_t_e_g_e_r_(_)_ _p_r_e_f_o_r_m_a_t_t_e_d_(_) │ │ │ │ │ o _s_w_a_p_(_) │ │ │ │ │ o _o_p_e_r_a_t_o_r_[_]_(_) │ │ │ │ │ o _f_i_n_d___k_e_y_(_) │ │ │ │ │ o _t_o___s_t_r_i_n_g_(_) │ │ │ │ │ o _e_n_u_m_ _d_a_t_a___t_y_p_e │ │ │ │ │ * _o_p_e_r_a_t_o_r_<_<_(_) │ │ │ │ │ * _b_e_n_c_o_d_e_(_) │ │ │ │ │ @@ -35,44 +35,44 @@ │ │ │ │ │ Declared in "_l_i_b_t_o_r_r_e_n_t_/_e_n_t_r_y_._h_p_p" │ │ │ │ │ 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. │ │ │ │ │ class entry │ │ │ │ │ { │ │ │ │ │ data_type ttyyppee () const; │ │ │ │ │ - eennttrryy (list_type); │ │ │ │ │ - eennttrryy (integer_type); │ │ │ │ │ eennttrryy (span); │ │ │ │ │ - eennttrryy (preformatted_type); │ │ │ │ │ eennttrryy (dictionary_type); │ │ │ │ │ + eennttrryy (preformatted_type); │ │ │ │ │ + eennttrryy (list_type); │ │ │ │ │ + eennttrryy (integer_type); │ │ │ │ │ eennttrryy (U v); │ │ │ │ │ eennttrryy (data_type t); │ │ │ │ │ eennttrryy (bdecode_node const& n); │ │ │ │ │ - entry& ooppeerraattoorr== (preformatted_type) &; │ │ │ │ │ - entry& ooppeerraattoorr== (list_type) &; │ │ │ │ │ entry& ooppeerraattoorr== (bdecode_node const&) &; │ │ │ │ │ - entry& ooppeerraattoorr== (entry&&) & noexcept; │ │ │ │ │ entry& ooppeerraattoorr== (dictionary_type) &; │ │ │ │ │ - entry& ooppeerraattoorr== (span) &; │ │ │ │ │ - entry& ooppeerraattoorr== (integer_type) &; │ │ │ │ │ + entry& ooppeerraattoorr== (entry&&) & noexcept; │ │ │ │ │ + entry& ooppeerraattoorr== (preformatted_type) &; │ │ │ │ │ entry& ooppeerraattoorr== (entry const&) &; │ │ │ │ │ + entry& ooppeerraattoorr== (list_type) &; │ │ │ │ │ + entry& ooppeerraattoorr== (integer_type) &; │ │ │ │ │ + entry& ooppeerraattoorr== (span) &; │ │ │ │ │ entry& ooppeerraattoorr== (U v) &; │ │ │ │ │ - string_type const& ssttrriinngg () const; │ │ │ │ │ - preformatted_type& pprreeffoorrmmaatttteedd (); │ │ │ │ │ - integer_type& iinntteeggeerr (); │ │ │ │ │ integer_type const& iinntteeggeerr () const; │ │ │ │ │ dictionary_type& ddiicctt (); │ │ │ │ │ - list_type const& lliisstt () const; │ │ │ │ │ preformatted_type const& pprreeffoorrmmaatttteedd () const; │ │ │ │ │ + integer_type& iinntteeggeerr (); │ │ │ │ │ + string_type const& ssttrriinngg () const; │ │ │ │ │ + list_type const& lliisstt () const; │ │ │ │ │ + string_type& ssttrriinngg (); │ │ │ │ │ dictionary_type const& ddiicctt () const; │ │ │ │ │ list_type& lliisstt (); │ │ │ │ │ - string_type& ssttrriinngg (); │ │ │ │ │ + preformatted_type& pprreeffoorrmmaatttteedd (); │ │ │ │ │ void sswwaapp (entry& e); │ │ │ │ │ - entry const& ooppeerraattoorr[[]] (string_view key) const; │ │ │ │ │ entry& ooppeerraattoorr[[]] (string_view key); │ │ │ │ │ + entry const& ooppeerraattoorr[[]] (string_view key) const; │ │ │ │ │ entry const* ffiinndd__kkeeyy (string_view key) const; │ │ │ │ │ entry* ffiinndd__kkeeyy (string_view key); │ │ │ │ │ std::string ttoo__ssttrriinngg (bool single_line = false) const; │ │ │ │ │ │ │ │ │ │ enum data_type │ │ │ │ │ { │ │ │ │ │ int_t, │ │ │ │ │ @@ -85,52 +85,52 @@ │ │ │ │ │ }; │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ********** ttyyppee(()) ********** │ │ │ │ │ data_type ttyyppee () const; │ │ │ │ │ returns the concrete type of the _e_n_t_r_y │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ********** eennttrryy(()) ********** │ │ │ │ │ -eennttrryy (list_type); │ │ │ │ │ -eennttrryy (integer_type); │ │ │ │ │ eennttrryy (span); │ │ │ │ │ -eennttrryy (preformatted_type); │ │ │ │ │ eennttrryy (dictionary_type); │ │ │ │ │ +eennttrryy (preformatted_type); │ │ │ │ │ +eennttrryy (list_type); │ │ │ │ │ +eennttrryy (integer_type); │ │ │ │ │ constructors directly from a specific type. The content of the argument is │ │ │ │ │ copied into the newly constructed _e_n_t_r_y │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ********** eennttrryy(()) ********** │ │ │ │ │ eennttrryy (data_type t); │ │ │ │ │ construct an empty _e_n_t_r_y of the specified type. see _d_a_t_a___t_y_p_e enum. │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ********** eennttrryy(()) ********** │ │ │ │ │ eennttrryy (bdecode_node const& n); │ │ │ │ │ construct from _b_d_e_c_o_d_e___n_o_d_e parsed form (see _b_d_e_c_o_d_e_(_)) │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ********** ooppeerraattoorr==(()) ********** │ │ │ │ │ -entry& ooppeerraattoorr== (preformatted_type) &; │ │ │ │ │ -entry& ooppeerraattoorr== (list_type) &; │ │ │ │ │ entry& ooppeerraattoorr== (bdecode_node const&) &; │ │ │ │ │ -entry& ooppeerraattoorr== (entry&&) & noexcept; │ │ │ │ │ entry& ooppeerraattoorr== (dictionary_type) &; │ │ │ │ │ -entry& ooppeerraattoorr== (span) &; │ │ │ │ │ -entry& ooppeerraattoorr== (integer_type) &; │ │ │ │ │ +entry& ooppeerraattoorr== (entry&&) & noexcept; │ │ │ │ │ +entry& ooppeerraattoorr== (preformatted_type) &; │ │ │ │ │ entry& ooppeerraattoorr== (entry const&) &; │ │ │ │ │ +entry& ooppeerraattoorr== (list_type) &; │ │ │ │ │ +entry& ooppeerraattoorr== (integer_type) &; │ │ │ │ │ +entry& ooppeerraattoorr== (span) &; │ │ │ │ │ copies the structure of the right hand side into this _e_n_t_r_y. │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ -********** lliisstt(()) iinntteeggeerr(()) pprreeffoorrmmaatttteedd(()) ssttrriinngg(()) ddiicctt(()) ********** │ │ │ │ │ -string_type const& ssttrriinngg () const; │ │ │ │ │ -preformatted_type& pprreeffoorrmmaatttteedd (); │ │ │ │ │ -integer_type& iinntteeggeerr (); │ │ │ │ │ +********** ssttrriinngg(()) ddiicctt(()) lliisstt(()) iinntteeggeerr(()) pprreeffoorrmmaatttteedd(()) ********** │ │ │ │ │ integer_type const& iinntteeggeerr () const; │ │ │ │ │ dictionary_type& ddiicctt (); │ │ │ │ │ -list_type const& lliisstt () const; │ │ │ │ │ preformatted_type const& pprreeffoorrmmaatttteedd () const; │ │ │ │ │ +integer_type& iinntteeggeerr (); │ │ │ │ │ +string_type const& ssttrriinngg () const; │ │ │ │ │ +list_type const& lliisstt () const; │ │ │ │ │ +string_type& ssttrriinngg (); │ │ │ │ │ dictionary_type const& ddiicctt () const; │ │ │ │ │ list_type& lliisstt (); │ │ │ │ │ -string_type& ssttrriinngg (); │ │ │ │ │ +preformatted_type& pprreeffoorrmmaatttteedd (); │ │ │ │ │ The integer(), string(), list() and dict() functions are accessors that return │ │ │ │ │ the respective type. If the entry object isn't of the type you request, the │ │ │ │ │ accessor will throw system_error. You can ask an entry for its type through the │ │ │ │ │ type() function. │ │ │ │ │ If you want to create an entry you give it the type you want it to have in its │ │ │ │ │ constructor, and then use one of the non-const accessors to get a reference │ │ │ │ │ which you then can assign the value you want it to have. │ │ │ │ │ @@ -161,16 +161,16 @@ │ │ │ │ │ _t_o_r_r_e_n_t___i_n_f_o exists. │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ********** sswwaapp(()) ********** │ │ │ │ │ void sswwaapp (entry& e); │ │ │ │ │ swaps the content of tthhiiss with e. │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ********** ooppeerraattoorr[[]](()) ********** │ │ │ │ │ -entry const& ooppeerraattoorr[[]] (string_view key) const; │ │ │ │ │ entry& ooppeerraattoorr[[]] (string_view key); │ │ │ │ │ +entry const& ooppeerraattoorr[[]] (string_view key) const; │ │ │ │ │ All of these functions requires the _e_n_t_r_y to be a dictionary, if it isn't they │ │ │ │ │ will throw system_error. │ │ │ │ │ The non-const versions of the operator[] will return a reference to either the │ │ │ │ │ existing element at the given key or, if there is no element with the given │ │ │ │ │ key, a reference to a newly inserted element at that key. │ │ │ │ │ The const version of operator[] will only return a reference to an existing │ │ │ │ │ element at the given key. If the key is not found, it will throw system_error. │ │ │ ├── ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-Core.html │ │ │ │ @@ -30,45 +30,45 @@ │ │ │ │ │ │ │ │

    home

    │ │ │ │
    │ │ │ │

    Table of contents

    │ │ │ │
    │ │ │ │ [report issue]
    │ │ │ │

    info_hash_t

    │ │ │ │

    Declared in "libtorrent/info_hash.hpp"

    │ │ │ │ @@ -78,21 +78,21 @@ │ │ │ │

    Note

    │ │ │ │

    If has_v2() is false then the v1 hash might actually be a truncated │ │ │ │ v2 hash

    │ │ │ │
    │ │ │ │
    │ │ │ │  struct info_hash_t
    │ │ │ │  {
    │ │ │ │ -   info_hash_t () noexcept = default;
    │ │ │ │ -   info_hash_t (sha1_hash h1, sha256_hash h2) noexcept;
    │ │ │ │     explicit info_hash_t (sha256_hash h2) noexcept;
    │ │ │ │ +   info_hash_t (sha1_hash h1, sha256_hash h2) noexcept;
    │ │ │ │     explicit info_hash_t (sha1_hash h1) noexcept;
    │ │ │ │ +   info_hash_t () noexcept = default;
    │ │ │ │     bool has_v2 () const;
    │ │ │ │ -   bool has_v1 () const;
    │ │ │ │     bool has (protocol_version v) const;
    │ │ │ │ +   bool has_v1 () const;
    │ │ │ │     sha1_hash get (protocol_version v) const;
    │ │ │ │     sha1_hash get_best () const;
    │ │ │ │     friend bool operator!= (info_hash_t const& lhs, info_hash_t const& rhs);
    │ │ │ │     friend bool operator== (info_hash_t const& lhs, info_hash_t const& rhs) noexcept;
    │ │ │ │     template <typename F> void for_each (F f) const;
    │ │ │ │     bool operator< (info_hash_t const& o) const;
    │ │ │ │     friend std::ostream& operator<< (std::ostream& os, info_hash_t const& ih);
    │ │ │ │ @@ -100,33 +100,33 @@
    │ │ │ │     sha1_hash v1;
    │ │ │ │     sha256_hash v2;
    │ │ │ │  };
    │ │ │ │  
    │ │ │ │ [report issue]
    │ │ │ │

    info_hash_t()

    │ │ │ │
    │ │ │ │ -info_hash_t () noexcept = default;
    │ │ │ │ -info_hash_t (sha1_hash h1, sha256_hash h2) noexcept;
    │ │ │ │  explicit info_hash_t (sha256_hash h2) noexcept;
    │ │ │ │ +info_hash_t (sha1_hash h1, sha256_hash h2) noexcept;
    │ │ │ │  explicit info_hash_t (sha1_hash h1) noexcept;
    │ │ │ │ +info_hash_t () noexcept = default;
    │ │ │ │  
    │ │ │ │

    The default constructor creates an object that has neither a v1 or v2 │ │ │ │ hash.

    │ │ │ │

    For backwards compatibility, make it possible to construct directly │ │ │ │ from a v1 hash. This constructor allows implicit conversion from a │ │ │ │ v1 hash, but the implicitness is deprecated.

    │ │ │ │ │ │ │ │ - │ │ │ │ -[report issue]
    │ │ │ │ -
    │ │ │ │ -

    has() has_v1() has_v2()

    │ │ │ │ + │ │ │ │ +[report issue]
    │ │ │ │ +
    │ │ │ │ +

    has() has_v2() has_v1()

    │ │ │ │
    │ │ │ │  bool has_v2 () const;
    │ │ │ │ -bool has_v1 () const;
    │ │ │ │  bool has (protocol_version v) const;
    │ │ │ │ +bool has_v1 () const;
    │ │ │ │  
    │ │ │ │

    returns true if the corresponding info hash is present in this │ │ │ │ object.

    │ │ │ │ [report issue]
    │ │ │ │
    │ │ │ │

    get()

    │ │ │ │
    │ │ │ │ @@ -148,50 +148,14 @@
    │ │ │ │  template <typename F> void for_each (F f) const;
    │ │ │ │  
    │ │ │ │

    calls the function object f for each hash that is available. │ │ │ │ starting with v1. The signature of F is:

    │ │ │ │
    │ │ │ │  void(sha1_hash const&, protocol_version);
    │ │ │ │  
    │ │ │ │ -[report issue]
    │ │ │ │ -
    │ │ │ │ -
    │ │ │ │ -

    peer_request

    │ │ │ │ -

    Declared in "libtorrent/peer_request.hpp"

    │ │ │ │ -

    represents a byte range within a piece. Internally this is is used for │ │ │ │ -incoming piece requests.

    │ │ │ │ -
    │ │ │ │ -struct peer_request
    │ │ │ │ -{
    │ │ │ │ -   bool operator== (peer_request const& r) const;
    │ │ │ │ -
    │ │ │ │ -   piece_index_t piece;
    │ │ │ │ -   int start;
    │ │ │ │ -   int length;
    │ │ │ │ -};
    │ │ │ │ -
    │ │ │ │ -[report issue]
    │ │ │ │ -

    operator==()

    │ │ │ │ -
    │ │ │ │ -bool operator== (peer_request const& r) const;
    │ │ │ │ -
    │ │ │ │ -

    returns true if the right hand side peer_request refers to the same │ │ │ │ -range as this does.

    │ │ │ │ -[report issue]
    │ │ │ │ -
    piece
    │ │ │ │ -
    The index of the piece in which the range starts.
    │ │ │ │ -
    │ │ │ │ -[report issue]
    │ │ │ │ -
    start
    │ │ │ │ -
    The byte offset within that piece where the range starts.
    │ │ │ │ -
    │ │ │ │ -[report issue]
    │ │ │ │ -
    length
    │ │ │ │ -
    The size of the range, in bytes.
    │ │ │ │ -
    │ │ │ │ [report issue]
    │ │ │ │
    │ │ │ │
    │ │ │ │

    peer_info

    │ │ │ │

    Declared in "libtorrent/peer_info.hpp"

    │ │ │ │

    holds information and statistics about one peer │ │ │ │ that libtorrent is connected to

    │ │ │ │ @@ -679,33 +643,111 @@ │ │ │ │
    │ │ │ │
    │ │ │ │

    piece_block

    │ │ │ │

    Declared in "libtorrent/piece_block.hpp"

    │ │ │ │
    │ │ │ │  struct piece_block
    │ │ │ │  {
    │ │ │ │ -   piece_block () = default;
    │ │ │ │     piece_block (piece_index_t p_index, int b_index);
    │ │ │ │ +   piece_block () = default;
    │ │ │ │     bool operator< (piece_block const& b) const;
    │ │ │ │     bool operator== (piece_block const& b) const;
    │ │ │ │     bool operator!= (piece_block const& b) const;
    │ │ │ │  
    │ │ │ │     static const piece_block invalid;
    │ │ │ │     piece_index_t piece_index {0};
    │ │ │ │     int block_index  = 0;
    │ │ │ │  };
    │ │ │ │  
    │ │ │ │ +[report issue]
    │ │ │ │ +
    │ │ │ │ +

    peer_request

    │ │ │ │ +

    Declared in "libtorrent/peer_request.hpp"

    │ │ │ │ +

    represents a byte range within a piece. Internally this is is used for │ │ │ │ +incoming piece requests.

    │ │ │ │ +
    │ │ │ │ +struct peer_request
    │ │ │ │ +{
    │ │ │ │ +   bool operator== (peer_request const& r) const;
    │ │ │ │ +
    │ │ │ │ +   piece_index_t piece;
    │ │ │ │ +   int start;
    │ │ │ │ +   int length;
    │ │ │ │ +};
    │ │ │ │ +
    │ │ │ │ +[report issue]
    │ │ │ │ +

    operator==()

    │ │ │ │ +
    │ │ │ │ +bool operator== (peer_request const& r) const;
    │ │ │ │ +
    │ │ │ │ +

    returns true if the right hand side peer_request refers to the same │ │ │ │ +range as this does.

    │ │ │ │ +[report issue]
    │ │ │ │ +
    piece
    │ │ │ │ +
    The index of the piece in which the range starts.
    │ │ │ │ +
    │ │ │ │ +[report issue]
    │ │ │ │ +
    start
    │ │ │ │ +
    The byte offset within that piece where the range starts.
    │ │ │ │ +
    │ │ │ │ +[report issue]
    │ │ │ │ +
    length
    │ │ │ │ +
    The size of the range, in bytes.
    │ │ │ │ +
    │ │ │ │ + │ │ │ │ + │ │ │ │ +[report issue]
    │ │ │ │ +
    │ │ │ │ +
    │ │ │ │ +

    load_torrent_buffer() load_torrent_parsed() load_torrent_file()

    │ │ │ │ +

    Declared in "libtorrent/load_torrent.hpp"

    │ │ │ │ +
    │ │ │ │ +add_torrent_params load_torrent_file (
    │ │ │ │ +   std::string const& filename, load_torrent_limits const& cfg);
    │ │ │ │ +add_torrent_params load_torrent_parsed (
    │ │ │ │ +   bdecode_node const& torrent_file);
    │ │ │ │ +add_torrent_params load_torrent_file (
    │ │ │ │ +   std::string const& filename);
    │ │ │ │ +add_torrent_params load_torrent_parsed (
    │ │ │ │ +   bdecode_node const& torrent_file, load_torrent_limits const& cfg);
    │ │ │ │ +add_torrent_params load_torrent_buffer (
    │ │ │ │ +   span<char const> buffer);
    │ │ │ │ +add_torrent_params load_torrent_buffer (
    │ │ │ │ +   span<char const> buffer, load_torrent_limits const& cfg);
    │ │ │ │ +
    │ │ │ │ +

    These functions load the content of a .torrent file into an │ │ │ │ +add_torrent_params object. │ │ │ │ +The immutable part of a torrent file (the info-dictionary) is stored in │ │ │ │ +the ti field in the add_torrent_params object (as a torrent_info │ │ │ │ +object). │ │ │ │ +The returned object is suitable to be:

    │ │ │ │ +
    │ │ │ │ + │ │ │ │ +
    │ │ │ │ +[report issue]
    │ │ │ │ +
    │ │ │ │ +

    truncate_files()

    │ │ │ │ +

    Declared in "libtorrent/truncate.hpp"

    │ │ │ │ +
    │ │ │ │ +void truncate_files (file_storage const& fs, std::string const& save_path, storage_error& ec);
    │ │ │ │ +
    │ │ │ │ +

    Truncates files larger than specified in the file_storage, saved under │ │ │ │ +the specified save_path.

    │ │ │ │ [report issue]
    │ │ │ │
    │ │ │ │

    make_magnet_uri()

    │ │ │ │

    Declared in "libtorrent/magnet_uri.hpp"

    │ │ │ │
    │ │ │ │ -std::string make_magnet_uri (add_torrent_params const& atp);
    │ │ │ │  std::string make_magnet_uri (torrent_info const& info);
    │ │ │ │  std::string make_magnet_uri (torrent_handle const& handle);
    │ │ │ │ +std::string make_magnet_uri (add_torrent_params const& atp);
    │ │ │ │  
    │ │ │ │

    Generates a magnet URI from the specified torrent.

    │ │ │ │

    Several fields from the add_torrent_params objects are recorded in the │ │ │ │ magnet link. In order to not include them, they have to be cleared before │ │ │ │ calling make_magnet_uri(). These fields are used:

    │ │ │ │
    │ │ │ │ ti, info_hashes, url_seeds, dht_nodes, │ │ │ │ @@ -725,134 +767,68 @@ │ │ │ │ an empty string is returned.

    │ │ │ │

    For more information about magnet links, see magnet links.

    │ │ │ │ [report issue]
    │ │ │ │
    │ │ │ │

    parse_magnet_uri()

    │ │ │ │

    Declared in "libtorrent/magnet_uri.hpp"

    │ │ │ │
    │ │ │ │ -void parse_magnet_uri (string_view uri, add_torrent_params& p, error_code& ec);
    │ │ │ │  add_torrent_params parse_magnet_uri (string_view uri, error_code& ec);
    │ │ │ │  add_torrent_params parse_magnet_uri (string_view uri);
    │ │ │ │ +void parse_magnet_uri (string_view uri, add_torrent_params& p, error_code& ec);
    │ │ │ │  
    │ │ │ │

    This function parses out information from the magnet link and populates the │ │ │ │ add_torrent_params object. The overload that does not take an │ │ │ │ error_code reference will throw a system_error on error │ │ │ │ The overload taking an add_torrent_params reference will fill in the │ │ │ │ fields specified in the magnet URI.

    │ │ │ │ -[report issue]
    │ │ │ │ -
    │ │ │ │ -

    torrent_peer_equal()

    │ │ │ │ -

    Declared in "libtorrent/torrent_peer.hpp"

    │ │ │ │ -
    │ │ │ │ -inline bool torrent_peer_equal (torrent_peer const* lhs, torrent_peer const* rhs);
    │ │ │ │ -
    │ │ │ │ - │ │ │ │ - │ │ │ │ -[report issue]
    │ │ │ │ -
    │ │ │ │ -

    load_torrent_parsed() load_torrent_file() load_torrent_buffer()

    │ │ │ │ -

    Declared in "libtorrent/load_torrent.hpp"

    │ │ │ │ -
    │ │ │ │ -add_torrent_params load_torrent_parsed (
    │ │ │ │ -   bdecode_node const& torrent_file, load_torrent_limits const& cfg);
    │ │ │ │ -add_torrent_params load_torrent_buffer (
    │ │ │ │ -   span<char const> buffer);
    │ │ │ │ -add_torrent_params load_torrent_file (
    │ │ │ │ -   std::string const& filename);
    │ │ │ │ -add_torrent_params load_torrent_file (
    │ │ │ │ -   std::string const& filename, load_torrent_limits const& cfg);
    │ │ │ │ -add_torrent_params load_torrent_parsed (
    │ │ │ │ -   bdecode_node const& torrent_file);
    │ │ │ │ -add_torrent_params load_torrent_buffer (
    │ │ │ │ -   span<char const> buffer, load_torrent_limits const& cfg);
    │ │ │ │ -
    │ │ │ │ -

    These functions load the content of a .torrent file into an │ │ │ │ -add_torrent_params object. │ │ │ │ -The immutable part of a torrent file (the info-dictionary) is stored in │ │ │ │ -the ti field in the add_torrent_params object (as a torrent_info │ │ │ │ -object). │ │ │ │ -The returned object is suitable to be:

    │ │ │ │ -
    │ │ │ │ - │ │ │ │ -
    │ │ │ │ -[report issue]
    │ │ │ │ -
    │ │ │ │ -

    truncate_files()

    │ │ │ │ -

    Declared in "libtorrent/truncate.hpp"

    │ │ │ │ -
    │ │ │ │ -void truncate_files (file_storage const& fs, std::string const& save_path, storage_error& ec);
    │ │ │ │ -
    │ │ │ │ -

    Truncates files larger than specified in the file_storage, saved under │ │ │ │ -the specified save_path.

    │ │ │ │ [report issue]
    │ │ │ │
    │ │ │ │

    version()

    │ │ │ │

    Declared in "libtorrent/version.hpp"

    │ │ │ │
    │ │ │ │  char const* version ();
    │ │ │ │  
    │ │ │ │

    returns the libtorrent version as string form in this format: │ │ │ │ "<major>.<minor>.<tiny>.<tag>"

    │ │ │ │ -[report issue]
    │ │ │ │ -
    │ │ │ │ -

    enum socket_type_t

    │ │ │ │ -

    Declared in "libtorrent/socket_type.hpp"

    │ │ │ │ +[report issue]
    │ │ │ │ +
    │ │ │ │ +

    torrent_peer_equal()

    │ │ │ │ +

    Declared in "libtorrent/torrent_peer.hpp"

    │ │ │ │ +
    │ │ │ │ +inline bool torrent_peer_equal (torrent_peer const* lhs, torrent_peer const* rhs);
    │ │ │ │ +
    │ │ │ │ +[report issue]
    │ │ │ │ +
    │ │ │ │ +

    enum protocol_version

    │ │ │ │ +

    Declared in "libtorrent/info_hash.hpp"

    │ │ │ │ │ │ │ │ │ │ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ - │ │ │ │ + │ │ │ │ │ │ │ │ - │ │ │ │ + │ │ │ │ │ │ │ │ - │ │ │ │ + │ │ │ │ │ │ │ │ - │ │ │ │ + │ │ │ │ │ │ │ │ - │ │ │ │ + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ │ │ │ │
    namevaluedescription
    tcp
    V10 The original BitTorrent version, using SHA-1 hashes
    socks5
    V21 Version 2 of the BitTorrent protocol, using SHA-256 hashes
    http
    NUM2 
    utp3 
    i2p4 
    tcp_ssl5 
    socks5_ssl6 
    http_ssl7 
    utp_ssl8 
    │ │ │ │ [report issue]
    │ │ │ │
    │ │ │ │

    enum event_t

    │ │ │ │

    Declared in "libtorrent/tracker_manager.hpp"

    │ │ │ │ │ │ │ │ @@ -886,129 +862,153 @@ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
    paused4 
    │ │ │ │ -[report issue]
    │ │ │ │ -
    │ │ │ │ -

    enum portmap_transport

    │ │ │ │ -

    Declared in "libtorrent/portmap.hpp"

    │ │ │ │ +[report issue]
    │ │ │ │ +
    │ │ │ │ +

    enum connection_type

    │ │ │ │ +

    Declared in "libtorrent/peer_connection.hpp"

    │ │ │ │ │ │ │ │ │ │ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ - │ │ │ │ + │ │ │ │ │ │ │ │ - │ │ │ │ + │ │ │ │ │ │ │ │ - │ │ │ │ + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ │ │ │ │
    namevaluedescription
    natpmp
    bittorrent0natpmp can be NAT-PMP or PCP 
    upnp
    url_seed1 
    http_seed2 
    │ │ │ │ -[report issue]
    │ │ │ │ -
    │ │ │ │ -

    enum portmap_protocol

    │ │ │ │ -

    Declared in "libtorrent/portmap.hpp"

    │ │ │ │ +[report issue]
    │ │ │ │ +
    │ │ │ │ +

    enum socket_type_t

    │ │ │ │ +

    Declared in "libtorrent/socket_type.hpp"

    │ │ │ │ │ │ │ │ │ │ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ - │ │ │ │ + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ - │ │ │ │ + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ - │ │ │ │ + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ │ │ │ │
    namevaluedescription
    none
    tcp0 
    tcp
    socks51 
    udp
    http2 
    utp3 
    i2p4 
    tcp_ssl5 
    socks5_ssl6 
    http_ssl7 
    utp_ssl8 
    │ │ │ │ -[report issue]
    │ │ │ │ -
    │ │ │ │ -

    enum protocol_version

    │ │ │ │ -

    Declared in "libtorrent/info_hash.hpp"

    │ │ │ │ +[report issue]
    │ │ │ │ +
    │ │ │ │ +

    enum portmap_transport

    │ │ │ │ +

    Declared in "libtorrent/portmap.hpp"

    │ │ │ │ │ │ │ │ │ │ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ - │ │ │ │ + │ │ │ │ │ │ │ │ - │ │ │ │ + │ │ │ │ │ │ │ │ - │ │ │ │ + │ │ │ │ │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
    namevaluedescription
    V1
    natpmp0The original BitTorrent version, using SHA-1 hashesnatpmp can be NAT-PMP or PCP
    V2
    upnp1Version 2 of the BitTorrent protocol, using SHA-256 hashes
    NUM2 
    │ │ │ │ -[report issue]
    │ │ │ │ -
    │ │ │ │ -

    enum connection_type

    │ │ │ │ -

    Declared in "libtorrent/peer_connection.hpp"

    │ │ │ │ +[report issue]
    │ │ │ │ +
    │ │ │ │ +

    enum portmap_protocol

    │ │ │ │ +

    Declared in "libtorrent/portmap.hpp"

    │ │ │ │ │ │ │ │ │ │ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ - │ │ │ │ + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ - │ │ │ │ + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ - │ │ │ │ + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
    namevaluedescription
    bittorrent
    none0 
    url_seed
    tcp1 
    http_seed
    udp2 
    │ │ │ │ [report issue]
    │ │ │ │
    │ │ │ │ @@ -1027,14 +1027,41 @@ │ │ │ │
    low_priority
    │ │ │ │
    The lowest priority for files and pieces.
    │ │ │ │ │ │ │ │
    │ │ │ │
    top_priority
    │ │ │ │
    The highest priority for files and pieces.
    │ │ │ │
    │ │ │ │ +[report issue]
    │ │ │ │ +
    │ │ │ │ +

    pex_flags_t

    │ │ │ │ +

    Declared in "libtorrent/pex_flags.hpp"

    │ │ │ │ +
    │ │ │ │ +
    pex_encryption
    │ │ │ │ +
    the peer supports protocol encryption
    │ │ │ │ +
    │ │ │ │ +
    │ │ │ │ +
    pex_seed
    │ │ │ │ +
    the peer is a seed
    │ │ │ │ +
    │ │ │ │ +
    │ │ │ │ +
    pex_utp
    │ │ │ │ +
    the peer supports the uTP, transport protocol over UDP.
    │ │ │ │ +
    │ │ │ │ +
    │ │ │ │ +
    pex_holepunch
    │ │ │ │ +
    the peer supports the holepunch extension If this flag is received from a │ │ │ │ +peer, it can be used as a rendezvous point in case direct connections to │ │ │ │ +the peer fail
    │ │ │ │ +
    │ │ │ │ +
    │ │ │ │ +
    pex_lt_v2
    │ │ │ │ +
    protocol v2 │ │ │ │ +this is not a standard flag, it is only used internally
    │ │ │ │ +
    │ │ │ │ [report issue]
    │ │ │ │
    │ │ │ │

    int

    │ │ │ │

    Declared in "libtorrent/version.hpp"

    │ │ │ │
    │ │ │ │
    version_major
    │ │ │ │
    the major, minor and tiny versions of libtorrent
    │ │ │ │ @@ -1179,15 +1206,15 @@ │ │ │ │ stop-when-ready immediately.

    │ │ │ │

    When the stop-when-ready logic fires, the flag is cleared. Any │ │ │ │ subsequent transitions between downloading and non-downloading states │ │ │ │ will not be affected, until this flag is set again.

    │ │ │ │

    The behavior is more robust when setting this flag as part of adding │ │ │ │ the torrent. See add_torrent_params.

    │ │ │ │

    The stop-when-ready flag fixes the inherent race condition of waiting │ │ │ │ -for the state_changed_alert and then call pause(). The download/seeding │ │ │ │ +for the state_changed_alert and then call pause(). The download/seeding │ │ │ │ will most likely start in between posting the alert and receiving the │ │ │ │ call to pause.

    │ │ │ │

    A downloading state is one where peers are being connected. Which means │ │ │ │ just downloading the metadata via the ut_metadata extension counts │ │ │ │ as a downloading state. In order to stop a torrent once the metadata │ │ │ │ has been downloaded, instead set all file priorities to dont_download

    │ │ │ │ │ │ │ │ @@ -1277,41 +1304,14 @@ │ │ │ │ URL. │ │ │ │
    │ │ │ │
    │ │ │ │
    all
    │ │ │ │
    all torrent flags combined. Can conveniently be used when creating masks │ │ │ │ for flags
    │ │ │ │
    │ │ │ │ -[report issue]
    │ │ │ │ -
    │ │ │ │ -

    pex_flags_t

    │ │ │ │ -

    Declared in "libtorrent/pex_flags.hpp"

    │ │ │ │ -
    │ │ │ │ -
    pex_encryption
    │ │ │ │ -
    the peer supports protocol encryption
    │ │ │ │ -
    │ │ │ │ -
    │ │ │ │ -
    pex_seed
    │ │ │ │ -
    the peer is a seed
    │ │ │ │ -
    │ │ │ │ -
    │ │ │ │ -
    pex_utp
    │ │ │ │ -
    the peer supports the uTP, transport protocol over UDP.
    │ │ │ │ -
    │ │ │ │ -
    │ │ │ │ -
    pex_holepunch
    │ │ │ │ -
    the peer supports the holepunch extension If this flag is received from a │ │ │ │ -peer, it can be used as a rendezvous point in case direct connections to │ │ │ │ -the peer fail
    │ │ │ │ -
    │ │ │ │ -
    │ │ │ │ -
    pex_lt_v2
    │ │ │ │ -
    protocol v2 │ │ │ │ -this is not a standard flag, it is only used internally
    │ │ │ │ -
    │ │ │ │ [report issue]
    │ │ │ │
    │ │ │ │

    char const*

    │ │ │ │

    Declared in "libtorrent/version.hpp"

    │ │ │ │
    │ │ │ │
    version_str
    │ │ │ │
    the libtorrent version in string form
    │ │ │ │ ├── html2text {} │ │ │ │ │ @@ -1,84 +1,84 @@ │ │ │ │ │ > │ │ │ │ │ _[_l_i_b_t_o_r_r_e_n_t_ _l_o_g_o_] │ │ │ │ │ VVeerrssiioonn:: 2.0.10 │ │ │ │ │ _h_o_m_e │ │ │ │ │ Table of contents │ │ │ │ │ * _i_n_f_o___h_a_s_h___t │ │ │ │ │ o _i_n_f_o___h_a_s_h___t_(_) │ │ │ │ │ - o _h_a_s_(_)_ _h_a_s___v_1_(_)_ _h_a_s___v_2_(_) │ │ │ │ │ + o _h_a_s_(_)_ _h_a_s___v_2_(_)_ _h_a_s___v_1_(_) │ │ │ │ │ o _g_e_t_(_) │ │ │ │ │ o _g_e_t___b_e_s_t_(_) │ │ │ │ │ o _f_o_r___e_a_c_h_(_) │ │ │ │ │ - * _p_e_e_r___r_e_q_u_e_s_t │ │ │ │ │ - o _o_p_e_r_a_t_o_r_=_=_(_) │ │ │ │ │ * _p_e_e_r___i_n_f_o │ │ │ │ │ o _i_2_p___d_e_s_t_i_n_a_t_i_o_n_(_) │ │ │ │ │ * _p_i_e_c_e___b_l_o_c_k │ │ │ │ │ + * _p_e_e_r___r_e_q_u_e_s_t │ │ │ │ │ + o _o_p_e_r_a_t_o_r_=_=_(_) │ │ │ │ │ + * _l_o_a_d___t_o_r_r_e_n_t___b_u_f_f_e_r_(_)_ _l_o_a_d___t_o_r_r_e_n_t___p_a_r_s_e_d_(_)_ _l_o_a_d___t_o_r_r_e_n_t___f_i_l_e_(_) │ │ │ │ │ + * _t_r_u_n_c_a_t_e___f_i_l_e_s_(_) │ │ │ │ │ * _m_a_k_e___m_a_g_n_e_t___u_r_i_(_) │ │ │ │ │ * _p_a_r_s_e___m_a_g_n_e_t___u_r_i_(_) │ │ │ │ │ - * _t_o_r_r_e_n_t___p_e_e_r___e_q_u_a_l_(_) │ │ │ │ │ - * _l_o_a_d___t_o_r_r_e_n_t___p_a_r_s_e_d_(_)_ _l_o_a_d___t_o_r_r_e_n_t___f_i_l_e_(_)_ _l_o_a_d___t_o_r_r_e_n_t___b_u_f_f_e_r_(_) │ │ │ │ │ - * _t_r_u_n_c_a_t_e___f_i_l_e_s_(_) │ │ │ │ │ * _v_e_r_s_i_o_n_(_) │ │ │ │ │ - * _e_n_u_m_ _s_o_c_k_e_t___t_y_p_e___t │ │ │ │ │ + * _t_o_r_r_e_n_t___p_e_e_r___e_q_u_a_l_(_) │ │ │ │ │ + * _e_n_u_m_ _p_r_o_t_o_c_o_l___v_e_r_s_i_o_n │ │ │ │ │ * _e_n_u_m_ _e_v_e_n_t___t │ │ │ │ │ + * _e_n_u_m_ _c_o_n_n_e_c_t_i_o_n___t_y_p_e │ │ │ │ │ + * _e_n_u_m_ _s_o_c_k_e_t___t_y_p_e___t │ │ │ │ │ * _e_n_u_m_ _p_o_r_t_m_a_p___t_r_a_n_s_p_o_r_t │ │ │ │ │ * _e_n_u_m_ _p_o_r_t_m_a_p___p_r_o_t_o_c_o_l │ │ │ │ │ - * _e_n_u_m_ _p_r_o_t_o_c_o_l___v_e_r_s_i_o_n │ │ │ │ │ - * _e_n_u_m_ _c_o_n_n_e_c_t_i_o_n___t_y_p_e │ │ │ │ │ * _d_o_w_n_l_o_a_d___p_r_i_o_r_i_t_y___t │ │ │ │ │ + * _p_e_x___f_l_a_g_s___t │ │ │ │ │ * _i_n_t │ │ │ │ │ * _t_o_r_r_e_n_t___f_l_a_g_s___t │ │ │ │ │ - * _p_e_x___f_l_a_g_s___t │ │ │ │ │ * _c_h_a_r_ _c_o_n_s_t_* │ │ │ │ │ * _s_t_d_:_:_u_i_n_t_6_4___t │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ************ iinnffoo__hhaasshh__tt ************ │ │ │ │ │ Declared in "_l_i_b_t_o_r_r_e_n_t_/_i_n_f_o___h_a_s_h_._h_p_p" │ │ │ │ │ class holding the info-hash of a torrent. It can hold a v1 info-hash (SHA-1) or │ │ │ │ │ a v2 info-hash (SHA-256) or both. │ │ │ │ │ Note │ │ │ │ │ If has_v2() is false then the v1 hash might actually be a truncated v2 hash │ │ │ │ │ struct info_hash_t │ │ │ │ │ { │ │ │ │ │ - iinnffoo__hhaasshh__tt () noexcept = default; │ │ │ │ │ - iinnffoo__hhaasshh__tt (sha1_hash h1, sha256_hash h2) noexcept; │ │ │ │ │ explicit iinnffoo__hhaasshh__tt (sha256_hash h2) noexcept; │ │ │ │ │ + iinnffoo__hhaasshh__tt (sha1_hash h1, sha256_hash h2) noexcept; │ │ │ │ │ explicit iinnffoo__hhaasshh__tt (sha1_hash h1) noexcept; │ │ │ │ │ + iinnffoo__hhaasshh__tt () noexcept = default; │ │ │ │ │ bool hhaass__vv22 () const; │ │ │ │ │ - bool hhaass__vv11 () const; │ │ │ │ │ bool hhaass (protocol_version v) const; │ │ │ │ │ + bool hhaass__vv11 () const; │ │ │ │ │ sha1_hash ggeett (protocol_version v) const; │ │ │ │ │ sha1_hash ggeett__bbeesstt () const; │ │ │ │ │ friend bool ooppeerraattoorr!!== (info_hash_t const& lhs, info_hash_t const& rhs); │ │ │ │ │ friend bool ooppeerraattoorr==== (info_hash_t const& lhs, info_hash_t const& rhs) │ │ │ │ │ noexcept; │ │ │ │ │ template void ffoorr__eeaacchh (F f) const; │ │ │ │ │ bool ooppeerraattoorr<< (info_hash_t const& o) const; │ │ │ │ │ friend std::ostream& ooppeerraattoorr<<<< (std::ostream& os, info_hash_t const& ih); │ │ │ │ │ │ │ │ │ │ sha1_hash v1; │ │ │ │ │ sha256_hash v2; │ │ │ │ │ }; │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ********** iinnffoo__hhaasshh__tt(()) ********** │ │ │ │ │ -iinnffoo__hhaasshh__tt () noexcept = default; │ │ │ │ │ -iinnffoo__hhaasshh__tt (sha1_hash h1, sha256_hash h2) noexcept; │ │ │ │ │ explicit iinnffoo__hhaasshh__tt (sha256_hash h2) noexcept; │ │ │ │ │ +iinnffoo__hhaasshh__tt (sha1_hash h1, sha256_hash h2) noexcept; │ │ │ │ │ explicit iinnffoo__hhaasshh__tt (sha1_hash h1) noexcept; │ │ │ │ │ +iinnffoo__hhaasshh__tt () noexcept = default; │ │ │ │ │ The default constructor creates an object that has neither a v1 or v2 hash. │ │ │ │ │ For backwards compatibility, make it possible to construct directly from a v1 │ │ │ │ │ hash. This constructor allows iimmpplliicciitt conversion from a v1 hash, but the │ │ │ │ │ implicitness is deprecated. │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ -********** hhaass(()) hhaass__vv11(()) hhaass__vv22(()) ********** │ │ │ │ │ +********** hhaass(()) hhaass__vv22(()) hhaass__vv11(()) ********** │ │ │ │ │ bool hhaass__vv22 () const; │ │ │ │ │ -bool hhaass__vv11 () const; │ │ │ │ │ bool hhaass (protocol_version v) const; │ │ │ │ │ +bool hhaass__vv11 () const; │ │ │ │ │ returns true if the corresponding info hash is present in this object. │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ********** ggeett(()) ********** │ │ │ │ │ sha1_hash ggeett (protocol_version v) const; │ │ │ │ │ returns the has for the specified protocol version │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ********** ggeett__bbeesstt(()) ********** │ │ │ │ │ @@ -88,41 +88,14 @@ │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ********** ffoorr__eeaacchh(()) ********** │ │ │ │ │ template void ffoorr__eeaacchh (F f) const; │ │ │ │ │ calls the function object f for each hash that is available. starting with v1. │ │ │ │ │ The signature of F is: │ │ │ │ │ void(sha1_hash const&, protocol_version); │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ -************ ppeeeerr__rreeqquueesstt ************ │ │ │ │ │ -Declared in "_l_i_b_t_o_r_r_e_n_t_/_p_e_e_r___r_e_q_u_e_s_t_._h_p_p" │ │ │ │ │ -represents a byte range within a piece. Internally this is is used for incoming │ │ │ │ │ -piece requests. │ │ │ │ │ -struct peer_request │ │ │ │ │ -{ │ │ │ │ │ - bool ooppeerraattoorr==== (peer_request const& r) const; │ │ │ │ │ - │ │ │ │ │ - piece_index_t piece; │ │ │ │ │ - int start; │ │ │ │ │ - int length; │ │ │ │ │ -}; │ │ │ │ │ -[_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ -********** ooppeerraattoorr====(()) ********** │ │ │ │ │ -bool ooppeerraattoorr==== (peer_request const& r) const; │ │ │ │ │ -returns true if the right hand side _p_e_e_r___r_e_q_u_e_s_t refers to the same range as │ │ │ │ │ -this does. │ │ │ │ │ -[_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ - piece │ │ │ │ │ - The index of the piece in which the range starts. │ │ │ │ │ -[_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ - start │ │ │ │ │ - The byte offset within that piece where the range starts. │ │ │ │ │ -[_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ - length │ │ │ │ │ - The size of the range, in bytes. │ │ │ │ │ -[_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ************ ppeeeerr__iinnffoo ************ │ │ │ │ │ Declared in "_l_i_b_t_o_r_r_e_n_t_/_p_e_e_r___i_n_f_o_._h_p_p" │ │ │ │ │ holds information and statistics about one peer that libtorrent is connected to │ │ │ │ │ struct peer_info │ │ │ │ │ { │ │ │ │ │ sha256_hash ii22pp__ddeessttiinnaattiioonn () const; │ │ │ │ │ │ │ │ │ │ @@ -495,30 +468,86 @@ │ │ │ │ │ and receiving data. The states are defined as independent flags of type │ │ │ │ │ bandwidth_state_flags_t, in this class. │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ************ ppiieeccee__bblloocckk ************ │ │ │ │ │ Declared in "_l_i_b_t_o_r_r_e_n_t_/_p_i_e_c_e___b_l_o_c_k_._h_p_p" │ │ │ │ │ struct piece_block │ │ │ │ │ { │ │ │ │ │ - ppiieeccee__bblloocckk () = default; │ │ │ │ │ ppiieeccee__bblloocckk (piece_index_t p_index, int b_index); │ │ │ │ │ + ppiieeccee__bblloocckk () = default; │ │ │ │ │ bool ooppeerraattoorr<< (piece_block const& b) const; │ │ │ │ │ bool ooppeerraattoorr==== (piece_block const& b) const; │ │ │ │ │ bool ooppeerraattoorr!!== (piece_block const& b) const; │ │ │ │ │ │ │ │ │ │ static const piece_block invalid; │ │ │ │ │ piece_index_t piece_index {0}; │ │ │ │ │ int bblloocckk__iinnddeexx = 0; │ │ │ │ │ }; │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ +************ ppeeeerr__rreeqquueesstt ************ │ │ │ │ │ +Declared in "_l_i_b_t_o_r_r_e_n_t_/_p_e_e_r___r_e_q_u_e_s_t_._h_p_p" │ │ │ │ │ +represents a byte range within a piece. Internally this is is used for incoming │ │ │ │ │ +piece requests. │ │ │ │ │ +struct peer_request │ │ │ │ │ +{ │ │ │ │ │ + bool ooppeerraattoorr==== (peer_request const& r) const; │ │ │ │ │ + │ │ │ │ │ + piece_index_t piece; │ │ │ │ │ + int start; │ │ │ │ │ + int length; │ │ │ │ │ +}; │ │ │ │ │ +[_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ +********** ooppeerraattoorr====(()) ********** │ │ │ │ │ +bool ooppeerraattoorr==== (peer_request const& r) const; │ │ │ │ │ +returns true if the right hand side _p_e_e_r___r_e_q_u_e_s_t refers to the same range as │ │ │ │ │ +this does. │ │ │ │ │ +[_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ + piece │ │ │ │ │ + The index of the piece in which the range starts. │ │ │ │ │ +[_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ + start │ │ │ │ │ + The byte offset within that piece where the range starts. │ │ │ │ │ +[_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ + length │ │ │ │ │ + The size of the range, in bytes. │ │ │ │ │ +[_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ +************ llooaadd__ttoorrrreenntt__bbuuffffeerr(()) llooaadd__ttoorrrreenntt__ppaarrsseedd(()) llooaadd__ttoorrrreenntt__ffiillee(()) ************ │ │ │ │ │ +Declared in "_l_i_b_t_o_r_r_e_n_t_/_l_o_a_d___t_o_r_r_e_n_t_._h_p_p" │ │ │ │ │ +add_torrent_params llooaadd__ttoorrrreenntt__ffiillee ( │ │ │ │ │ + std::string const& filename, load_torrent_limits const& cfg); │ │ │ │ │ +add_torrent_params llooaadd__ttoorrrreenntt__ppaarrsseedd ( │ │ │ │ │ + bdecode_node const& torrent_file); │ │ │ │ │ +add_torrent_params llooaadd__ttoorrrreenntt__ffiillee ( │ │ │ │ │ + std::string const& filename); │ │ │ │ │ +add_torrent_params llooaadd__ttoorrrreenntt__ppaarrsseedd ( │ │ │ │ │ + bdecode_node const& torrent_file, load_torrent_limits const& cfg); │ │ │ │ │ +add_torrent_params llooaadd__ttoorrrreenntt__bbuuffffeerr ( │ │ │ │ │ + span buffer); │ │ │ │ │ +add_torrent_params llooaadd__ttoorrrreenntt__bbuuffffeerr ( │ │ │ │ │ + span buffer, load_torrent_limits const& cfg); │ │ │ │ │ +These functions load the content of a .torrent file into an _a_d_d___t_o_r_r_e_n_t___p_a_r_a_m_s │ │ │ │ │ +object. The immutable part of a torrent file (the info-dictionary) is stored in │ │ │ │ │ +the ti field in the _a_d_d___t_o_r_r_e_n_t___p_a_r_a_m_s object (as a _t_o_r_r_e_n_t___i_n_f_o object). The │ │ │ │ │ +returned object is suitable to be: │ │ │ │ │ + * added to a _s_e_s_s_i_o_n via _a_d_d___t_o_r_r_e_n_t_(_) or _a_s_y_n_c___a_d_d___t_o_r_r_e_n_t_(_) │ │ │ │ │ + * saved as a .torrent_file via _w_r_i_t_e___t_o_r_r_e_n_t___f_i_l_e_(_) │ │ │ │ │ + * turned into a magnet link via _m_a_k_e___m_a_g_n_e_t___u_r_i_(_) │ │ │ │ │ +[_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ +************ ttrruunnccaattee__ffiilleess(()) ************ │ │ │ │ │ +Declared in "_l_i_b_t_o_r_r_e_n_t_/_t_r_u_n_c_a_t_e_._h_p_p" │ │ │ │ │ +void ttrruunnccaattee__ffiilleess (file_storage const& fs, std::string const& save_path, │ │ │ │ │ +storage_error& ec); │ │ │ │ │ +Truncates files larger than specified in the _f_i_l_e___s_t_o_r_a_g_e, saved under the │ │ │ │ │ +specified save_path. │ │ │ │ │ +[_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ************ mmaakkee__mmaaggnneett__uurrii(()) ************ │ │ │ │ │ Declared in "_l_i_b_t_o_r_r_e_n_t_/_m_a_g_n_e_t___u_r_i_._h_p_p" │ │ │ │ │ -std::string mmaakkee__mmaaggnneett__uurrii (add_torrent_params const& atp); │ │ │ │ │ std::string mmaakkee__mmaaggnneett__uurrii (torrent_info const& info); │ │ │ │ │ std::string mmaakkee__mmaaggnneett__uurrii (torrent_handle const& handle); │ │ │ │ │ +std::string mmaakkee__mmaaggnneett__uurrii (add_torrent_params const& atp); │ │ │ │ │ Generates a magnet URI from the specified torrent. │ │ │ │ │ Several fields from the _a_d_d___t_o_r_r_e_n_t___p_a_r_a_m_s objects are recorded in the magnet │ │ │ │ │ link. In order to not include them, they have to be cleared before calling │ │ │ │ │ _m_a_k_e___m_a_g_n_e_t___u_r_i_(_). These fields are used: │ │ │ │ │ ti, info_hashes, url_seeds, dht_nodes, file_priorities, trackers, │ │ │ │ │ name, peers. │ │ │ │ │ Depending on what the use case for the resulting magnet link is, clearing peers │ │ │ │ │ @@ -533,62 +562,59 @@ │ │ │ │ │ The overload that takes a _t_o_r_r_e_n_t___h_a_n_d_l_e will make blocking calls to query │ │ │ │ │ information about the torrent. If the torrent handle is invalid, an empty │ │ │ │ │ string is returned. │ │ │ │ │ For more information about magnet links, see _m_a_g_n_e_t_ _l_i_n_k_s. │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ************ ppaarrssee__mmaaggnneett__uurrii(()) ************ │ │ │ │ │ Declared in "_l_i_b_t_o_r_r_e_n_t_/_m_a_g_n_e_t___u_r_i_._h_p_p" │ │ │ │ │ -void ppaarrssee__mmaaggnneett__uurrii (string_view uri, add_torrent_params& p, error_code& ec); │ │ │ │ │ add_torrent_params ppaarrssee__mmaaggnneett__uurrii (string_view uri, error_code& ec); │ │ │ │ │ add_torrent_params ppaarrssee__mmaaggnneett__uurrii (string_view uri); │ │ │ │ │ +void ppaarrssee__mmaaggnneett__uurrii (string_view uri, add_torrent_params& p, error_code& ec); │ │ │ │ │ This function parses out information from the magnet link and populates the │ │ │ │ │ _a_d_d___t_o_r_r_e_n_t___p_a_r_a_m_s object. The overload that does not take an error_code │ │ │ │ │ reference will throw a system_error on error The overload taking an │ │ │ │ │ add_torrent_params reference will fill in the fields specified in the magnet │ │ │ │ │ URI. │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ +************ vveerrssiioonn(()) ************ │ │ │ │ │ +Declared in "_l_i_b_t_o_r_r_e_n_t_/_v_e_r_s_i_o_n_._h_p_p" │ │ │ │ │ +char const* vveerrssiioonn (); │ │ │ │ │ +returns the libtorrent version as string form in this format: │ │ │ │ │ +"..." │ │ │ │ │ +[_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ************ ttoorrrreenntt__ppeeeerr__eeqquuaall(()) ************ │ │ │ │ │ Declared in "_l_i_b_t_o_r_r_e_n_t_/_t_o_r_r_e_n_t___p_e_e_r_._h_p_p" │ │ │ │ │ inline bool ttoorrrreenntt__ppeeeerr__eeqquuaall (torrent_peer const* lhs, torrent_peer const* │ │ │ │ │ rhs); │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ -************ llooaadd__ttoorrrreenntt__ppaarrsseedd(()) llooaadd__ttoorrrreenntt__ffiillee(()) llooaadd__ttoorrrreenntt__bbuuffffeerr(()) ************ │ │ │ │ │ -Declared in "_l_i_b_t_o_r_r_e_n_t_/_l_o_a_d___t_o_r_r_e_n_t_._h_p_p" │ │ │ │ │ -add_torrent_params llooaadd__ttoorrrreenntt__ppaarrsseedd ( │ │ │ │ │ - bdecode_node const& torrent_file, load_torrent_limits const& cfg); │ │ │ │ │ -add_torrent_params llooaadd__ttoorrrreenntt__bbuuffffeerr ( │ │ │ │ │ - span buffer); │ │ │ │ │ -add_torrent_params llooaadd__ttoorrrreenntt__ffiillee ( │ │ │ │ │ - std::string const& filename); │ │ │ │ │ -add_torrent_params llooaadd__ttoorrrreenntt__ffiillee ( │ │ │ │ │ - std::string const& filename, load_torrent_limits const& cfg); │ │ │ │ │ -add_torrent_params llooaadd__ttoorrrreenntt__ppaarrsseedd ( │ │ │ │ │ - bdecode_node const& torrent_file); │ │ │ │ │ -add_torrent_params llooaadd__ttoorrrreenntt__bbuuffffeerr ( │ │ │ │ │ - span buffer, load_torrent_limits const& cfg); │ │ │ │ │ -These functions load the content of a .torrent file into an _a_d_d___t_o_r_r_e_n_t___p_a_r_a_m_s │ │ │ │ │ -object. The immutable part of a torrent file (the info-dictionary) is stored in │ │ │ │ │ -the ti field in the _a_d_d___t_o_r_r_e_n_t___p_a_r_a_m_s object (as a _t_o_r_r_e_n_t___i_n_f_o object). The │ │ │ │ │ -returned object is suitable to be: │ │ │ │ │ - * added to a _s_e_s_s_i_o_n via _a_d_d___t_o_r_r_e_n_t_(_) or _a_s_y_n_c___a_d_d___t_o_r_r_e_n_t_(_) │ │ │ │ │ - * saved as a .torrent_file via _w_r_i_t_e___t_o_r_r_e_n_t___f_i_l_e_(_) │ │ │ │ │ - * turned into a magnet link via _m_a_k_e___m_a_g_n_e_t___u_r_i_(_) │ │ │ │ │ +************ eennuumm pprroottooccooll__vveerrssiioonn ************ │ │ │ │ │ +Declared in "_l_i_b_t_o_r_r_e_n_t_/_i_n_f_o___h_a_s_h_._h_p_p" │ │ │ │ │ + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ │ │ │ │ │ +|_nn_aa_mm_ee_|_vv_aa_ll_uu_ee_|_dd_ee_ss_cc_rr_ii_pp_tt_ii_oo_nn_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_V_1_ _ _|_0_ _ _ _ _|_T_h_e_ _o_r_i_g_i_n_a_l_ _B_i_t_T_o_r_r_e_n_t_ _v_e_r_s_i_o_n_,_ _u_s_i_n_g_ _S_H_A_-_1_ _h_a_s_h_e_s_ _ _ _ _ _ _ | │ │ │ │ │ +|_V_2_ _ _|_1_ _ _ _ _|_V_e_r_s_i_o_n_ _2_ _o_f_ _t_h_e_ _B_i_t_T_o_r_r_e_n_t_ _p_r_o_t_o_c_o_l_,_ _u_s_i_n_g_ _S_H_A_-_2_5_6_ _h_a_s_h_e_s| │ │ │ │ │ +|_N_U_M_ _|_2_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ -************ ttrruunnccaattee__ffiilleess(()) ************ │ │ │ │ │ -Declared in "_l_i_b_t_o_r_r_e_n_t_/_t_r_u_n_c_a_t_e_._h_p_p" │ │ │ │ │ -void ttrruunnccaattee__ffiilleess (file_storage const& fs, std::string const& save_path, │ │ │ │ │ -storage_error& ec); │ │ │ │ │ -Truncates files larger than specified in the _f_i_l_e___s_t_o_r_a_g_e, saved under the │ │ │ │ │ -specified save_path. │ │ │ │ │ +************ eennuumm eevveenntt__tt ************ │ │ │ │ │ +Declared in "_l_i_b_t_o_r_r_e_n_t_/_t_r_a_c_k_e_r___m_a_n_a_g_e_r_._h_p_p" │ │ │ │ │ + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ │ │ │ │ │ +|_nn_aa_mm_ee_ _ _ _ _ _|_vv_aa_ll_uu_ee_|_dd_ee_ss_cc_rr_ii_pp_tt_ii_oo_nn| │ │ │ │ │ +|_n_o_n_e_ _ _ _ _ _|_0_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_c_o_m_p_l_e_t_e_d_|_1_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_s_t_a_r_t_e_d_ _ _|_2_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_s_t_o_p_p_e_d_ _ _|_3_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_p_a_u_s_e_d_ _ _ _|_4_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ -************ vveerrssiioonn(()) ************ │ │ │ │ │ -Declared in "_l_i_b_t_o_r_r_e_n_t_/_v_e_r_s_i_o_n_._h_p_p" │ │ │ │ │ -char const* vveerrssiioonn (); │ │ │ │ │ -returns the libtorrent version as string form in this format: │ │ │ │ │ -"..." │ │ │ │ │ +************ eennuumm ccoonnnneeccttiioonn__ttyyppee ************ │ │ │ │ │ +Declared in "_l_i_b_t_o_r_r_e_n_t_/_p_e_e_r___c_o_n_n_e_c_t_i_o_n_._h_p_p" │ │ │ │ │ + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ │ │ │ │ │ +|_nn_aa_mm_ee_ _ _ _ _ _ _|_vv_aa_ll_uu_ee_|_dd_ee_ss_cc_rr_ii_pp_tt_ii_oo_nn| │ │ │ │ │ +|_b_i_t_t_o_r_r_e_n_t_|_0_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_u_r_l___s_e_e_d_ _ _|_1_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_h_t_t_p___s_e_e_d_ _|_2_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ************ eennuumm ssoocckkeett__ttyyppee__tt ************ │ │ │ │ │ Declared in "_l_i_b_t_o_r_r_e_n_t_/_s_o_c_k_e_t___t_y_p_e_._h_p_p" │ │ │ │ │ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ │ │ │ │ │ |_nn_aa_mm_ee_ _ _ _ _ _ _|_vv_aa_ll_uu_ee_|_dd_ee_ss_cc_rr_ii_pp_tt_ii_oo_nn| │ │ │ │ │ |_t_c_p_ _ _ _ _ _ _ _|_0_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |_s_o_c_k_s_5_ _ _ _ _|_1_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ @@ -596,24 +622,14 @@ │ │ │ │ │ |_u_t_p_ _ _ _ _ _ _ _|_3_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |_i_2_p_ _ _ _ _ _ _ _|_4_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |_t_c_p___s_s_l_ _ _ _|_5_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |_s_o_c_k_s_5___s_s_l_|_6_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |_h_t_t_p___s_s_l_ _ _|_7_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |_u_t_p___s_s_l_ _ _ _|_8_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ -************ eennuumm eevveenntt__tt ************ │ │ │ │ │ -Declared in "_l_i_b_t_o_r_r_e_n_t_/_t_r_a_c_k_e_r___m_a_n_a_g_e_r_._h_p_p" │ │ │ │ │ - _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ │ │ │ │ │ -|_nn_aa_mm_ee_ _ _ _ _ _|_vv_aa_ll_uu_ee_|_dd_ee_ss_cc_rr_ii_pp_tt_ii_oo_nn| │ │ │ │ │ -|_n_o_n_e_ _ _ _ _ _|_0_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_c_o_m_p_l_e_t_e_d_|_1_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_s_t_a_r_t_e_d_ _ _|_2_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_s_t_o_p_p_e_d_ _ _|_3_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_p_a_u_s_e_d_ _ _ _|_4_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -[_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ************ eennuumm ppoorrttmmaapp__ttrraannssppoorrtt ************ │ │ │ │ │ Declared in "_l_i_b_t_o_r_r_e_n_t_/_p_o_r_t_m_a_p_._h_p_p" │ │ │ │ │ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ │ │ │ │ │ |_nn_aa_mm_ee_ _ _|_vv_aa_ll_uu_ee_|_dd_ee_ss_cc_rr_ii_pp_tt_ii_oo_nn_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |_n_a_t_p_m_p_|_0_ _ _ _ _|_n_a_t_p_m_p_ _c_a_n_ _b_e_ _N_A_T_-_P_M_P_ _o_r_ _P_C_P| │ │ │ │ │ |_u_p_n_p_ _ _|_1_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ @@ -621,42 +637,41 @@ │ │ │ │ │ Declared in "_l_i_b_t_o_r_r_e_n_t_/_p_o_r_t_m_a_p_._h_p_p" │ │ │ │ │ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ │ │ │ │ │ |_nn_aa_mm_ee_|_vv_aa_ll_uu_ee_|_dd_ee_ss_cc_rr_ii_pp_tt_ii_oo_nn| │ │ │ │ │ |_n_o_n_e_|_0_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |_t_c_p_ _|_1_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |_u_d_p_ _|_2_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ -************ eennuumm pprroottooccooll__vveerrssiioonn ************ │ │ │ │ │ -Declared in "_l_i_b_t_o_r_r_e_n_t_/_i_n_f_o___h_a_s_h_._h_p_p" │ │ │ │ │ - _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ │ │ │ │ │ -|_nn_aa_mm_ee_|_vv_aa_ll_uu_ee_|_dd_ee_ss_cc_rr_ii_pp_tt_ii_oo_nn_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_V_1_ _ _|_0_ _ _ _ _|_T_h_e_ _o_r_i_g_i_n_a_l_ _B_i_t_T_o_r_r_e_n_t_ _v_e_r_s_i_o_n_,_ _u_s_i_n_g_ _S_H_A_-_1_ _h_a_s_h_e_s_ _ _ _ _ _ _ | │ │ │ │ │ -|_V_2_ _ _|_1_ _ _ _ _|_V_e_r_s_i_o_n_ _2_ _o_f_ _t_h_e_ _B_i_t_T_o_r_r_e_n_t_ _p_r_o_t_o_c_o_l_,_ _u_s_i_n_g_ _S_H_A_-_2_5_6_ _h_a_s_h_e_s| │ │ │ │ │ -|_N_U_M_ _|_2_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -[_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ -************ eennuumm ccoonnnneeccttiioonn__ttyyppee ************ │ │ │ │ │ -Declared in "_l_i_b_t_o_r_r_e_n_t_/_p_e_e_r___c_o_n_n_e_c_t_i_o_n_._h_p_p" │ │ │ │ │ - _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ │ │ │ │ │ -|_nn_aa_mm_ee_ _ _ _ _ _ _|_vv_aa_ll_uu_ee_|_dd_ee_ss_cc_rr_ii_pp_tt_ii_oo_nn| │ │ │ │ │ -|_b_i_t_t_o_r_r_e_n_t_|_0_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_u_r_l___s_e_e_d_ _ _|_1_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_h_t_t_p___s_e_e_d_ _|_2_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -[_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ************ ddoowwnnllooaadd__pprriioorriittyy__tt ************ │ │ │ │ │ Declared in "_l_i_b_t_o_r_r_e_n_t_/_d_o_w_n_l_o_a_d___p_r_i_o_r_i_t_y_._h_p_p" │ │ │ │ │ dont_download │ │ │ │ │ Don't download the file or piece. Partial pieces may still be downloaded │ │ │ │ │ when setting file priorities. │ │ │ │ │ default_priority │ │ │ │ │ The default priority for files and pieces. │ │ │ │ │ low_priority │ │ │ │ │ The lowest priority for files and pieces. │ │ │ │ │ top_priority │ │ │ │ │ The highest priority for files and pieces. │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ +************ ppeexx__ffllaaggss__tt ************ │ │ │ │ │ +Declared in "_l_i_b_t_o_r_r_e_n_t_/_p_e_x___f_l_a_g_s_._h_p_p" │ │ │ │ │ + pex_encryption │ │ │ │ │ + the peer supports protocol encryption │ │ │ │ │ + pex_seed │ │ │ │ │ + the peer is a seed │ │ │ │ │ + pex_utp │ │ │ │ │ + the peer supports the uTP, transport protocol over UDP. │ │ │ │ │ + pex_holepunch │ │ │ │ │ + the peer supports the holepunch extension If this flag is received from a │ │ │ │ │ + peer, it can be used as a rendezvous point in case direct connections to │ │ │ │ │ + the peer fail │ │ │ │ │ + pex_lt_v2 │ │ │ │ │ + protocol v2 this is not a standard flag, it is only used internally │ │ │ │ │ +[_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ************ iinntt ************ │ │ │ │ │ Declared in "_l_i_b_t_o_r_r_e_n_t_/_v_e_r_s_i_o_n_._h_p_p" │ │ │ │ │ version_major │ │ │ │ │ the major, minor and tiny versions of libtorrent │ │ │ │ │ version_minor │ │ │ │ │ the major, minor and tiny versions of libtorrent │ │ │ │ │ version_tiny │ │ │ │ │ @@ -834,29 +849,14 @@ │ │ │ │ │ This flag is set automatically when adding a torrent that has at least │ │ │ │ │ one tracker whose hostname ends with .i2p. It's also set by │ │ │ │ │ _p_a_r_s_e___m_a_g_n_e_t___u_r_i_(_) if the tracker list contains such URL. │ │ │ │ │ all │ │ │ │ │ all torrent flags combined. Can conveniently be used when creating masks │ │ │ │ │ for flags │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ -************ ppeexx__ffllaaggss__tt ************ │ │ │ │ │ -Declared in "_l_i_b_t_o_r_r_e_n_t_/_p_e_x___f_l_a_g_s_._h_p_p" │ │ │ │ │ - pex_encryption │ │ │ │ │ - the peer supports protocol encryption │ │ │ │ │ - pex_seed │ │ │ │ │ - the peer is a seed │ │ │ │ │ - pex_utp │ │ │ │ │ - the peer supports the uTP, transport protocol over UDP. │ │ │ │ │ - pex_holepunch │ │ │ │ │ - the peer supports the holepunch extension If this flag is received from a │ │ │ │ │ - peer, it can be used as a rendezvous point in case direct connections to │ │ │ │ │ - the peer fail │ │ │ │ │ - pex_lt_v2 │ │ │ │ │ - protocol v2 this is not a standard flag, it is only used internally │ │ │ │ │ -[_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ************ cchhaarr ccoonnsstt** ************ │ │ │ │ │ Declared in "_l_i_b_t_o_r_r_e_n_t_/_v_e_r_s_i_o_n_._h_p_p" │ │ │ │ │ version_str │ │ │ │ │ the libtorrent version in string form │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ************ ssttdd::::uuiinntt6644__tt ************ │ │ │ │ │ Declared in "_l_i_b_t_o_r_r_e_n_t_/_v_e_r_s_i_o_n_._h_p_p" │ │ │ ├── ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-Create_Torrents.html │ │ │ │ @@ -37,26 +37,26 @@ │ │ │ │
  • generate() generate_buf()
  • │ │ │ │
  • files()
  • │ │ │ │
  • set_comment()
  • │ │ │ │
  • set_creator()
  • │ │ │ │
  • set_creation_date()
  • │ │ │ │
  • set_hash()
  • │ │ │ │
  • set_hash2()
  • │ │ │ │ -
  • add_url_seed() add_http_seed()
  • │ │ │ │ +
  • add_http_seed() add_url_seed()
  • │ │ │ │
  • add_node()
  • │ │ │ │
  • add_tracker()
  • │ │ │ │
  • set_root_cert()
  • │ │ │ │ -
  • priv() set_priv()
  • │ │ │ │ +
  • set_priv() priv()
  • │ │ │ │
  • num_pieces()
  • │ │ │ │
  • piece_range()
  • │ │ │ │
  • file_range()
  • │ │ │ │
  • file_piece_range()
  • │ │ │ │
  • total_size()
  • │ │ │ │
  • piece_size() piece_length()
  • │ │ │ │ -
  • add_collection() add_similar_torrent()
  • │ │ │ │ +
  • add_similar_torrent() add_collection()
  • │ │ │ │ │ │ │ │
  • │ │ │ │
  • add_files()
  • │ │ │ │
  • set_piece_hashes()
  • │ │ │ │ │ │ │ │ │ │ │ │

    This section describes the functions and classes that are used │ │ │ │ @@ -105,43 +105,43 @@ │ │ │ │

    This class holds state for creating a torrent. After having added │ │ │ │ all information to it, call create_torrent::generate() to generate │ │ │ │ the torrent. The entry that's returned can then be bencoded into a │ │ │ │ .torrent file using bencode().

    │ │ │ │
    │ │ │ │  struct create_torrent
    │ │ │ │  {
    │ │ │ │ +   explicit create_torrent (torrent_info const& ti);
    │ │ │ │     explicit create_torrent (file_storage& fs, int piece_size = 0
    │ │ │ │        , create_flags_t flags = {});
    │ │ │ │ -   explicit create_torrent (torrent_info const& ti);
    │ │ │ │ -   std::vector<char> generate_buf () const;
    │ │ │ │     entry generate () const;
    │ │ │ │ +   std::vector<char> generate_buf () const;
    │ │ │ │     file_storage const& files () const;
    │ │ │ │     void set_comment (char const* str);
    │ │ │ │     void set_creator (char const* str);
    │ │ │ │     void set_creation_date (std::time_t timestamp);
    │ │ │ │     void set_hash (piece_index_t index, sha1_hash const& h);
    │ │ │ │     void set_hash2 (file_index_t file, piece_index_t::diff_type piece, sha256_hash const& h);
    │ │ │ │ -   void add_url_seed (string_view url);
    │ │ │ │     void add_http_seed (string_view url);
    │ │ │ │ +   void add_url_seed (string_view url);
    │ │ │ │     void add_node (std::pair<std::string, int> node);
    │ │ │ │     void add_tracker (string_view url, int tier = 0);
    │ │ │ │     void set_root_cert (string_view cert);
    │ │ │ │     void set_priv (bool p);
    │ │ │ │     bool priv () const;
    │ │ │ │ -   bool is_v1_only () const;
    │ │ │ │     bool is_v2_only () const;
    │ │ │ │ +   bool is_v1_only () const;
    │ │ │ │     int num_pieces () const;
    │ │ │ │     piece_index_t end_piece () const;
    │ │ │ │     index_range<piece_index_t> piece_range () const noexcept;
    │ │ │ │     file_index_t end_file () const;
    │ │ │ │     index_range<file_index_t> file_range () const noexcept;
    │ │ │ │     index_range<piece_index_t::diff_type> file_piece_range (file_index_t f);
    │ │ │ │     std::int64_t total_size () const;
    │ │ │ │ -   int piece_length () const;
    │ │ │ │     int piece_size (piece_index_t i) const;
    │ │ │ │ +   int piece_length () const;
    │ │ │ │     void add_collection (string_view c);
    │ │ │ │     void add_similar_torrent (sha1_hash ih);
    │ │ │ │  
    │ │ │ │     static constexpr create_flags_t modification_time  = 2_bit;
    │ │ │ │     static constexpr create_flags_t symlinks  = 3_bit;
    │ │ │ │     static constexpr create_flags_t v2_only  = 5_bit;
    │ │ │ │     static constexpr create_flags_t v1_only  = 6_bit;
    │ │ │ │ @@ -149,17 +149,17 @@
    │ │ │ │     static constexpr create_flags_t no_attributes  = 8_bit;
    │ │ │ │     static constexpr create_flags_t canonical_files_no_tail_padding  = 9_bit;
    │ │ │ │  };
    │ │ │ │  
    │ │ │ │ [report issue]
    │ │ │ │

    create_torrent()

    │ │ │ │
    │ │ │ │ +explicit create_torrent (torrent_info const& ti);
    │ │ │ │  explicit create_torrent (file_storage& fs, int piece_size = 0
    │ │ │ │        , create_flags_t flags = {});
    │ │ │ │ -explicit create_torrent (torrent_info const& ti);
    │ │ │ │  
    │ │ │ │

    The piece_size is the size of each piece in bytes. It must be a │ │ │ │ power of 2 and a minimum of 16 kiB. If a piece size of 0 is │ │ │ │ specified, a piece_size will be set automatically.

    │ │ │ │

    The flags arguments specifies options for the torrent creation. It can │ │ │ │ be any combination of the flags defined by create_flags_t.

    │ │ │ │

    The file_storage (fs) parameter defines the files, sizes and │ │ │ │ @@ -178,16 +178,16 @@ │ │ │ │ entire duration of the create_torrent object.

    │ │ │ │
    │ │ │ │ │ │ │ │ [report issue] │ │ │ │
    │ │ │ │

    generate() generate_buf()

    │ │ │ │
    │ │ │ │ -std::vector<char> generate_buf () const;
    │ │ │ │  entry generate () const;
    │ │ │ │ +std::vector<char> generate_buf () const;
    │ │ │ │  
    │ │ │ │

    This function will generate the .torrent file as a bencode tree, or a │ │ │ │ bencoded into a buffer. │ │ │ │ In order to encode the entry into a flat file, use the bencode() function.

    │ │ │ │

    The function returning an entry may be useful to add custom entries │ │ │ │ to the torrent file before bencoding it and saving it to disk.

    │ │ │ │

    Whether the resulting torrent object is v1, v2 or hybrid depends on │ │ │ │ @@ -270,21 +270,21 @@ │ │ │ │ 16 kiB blocks. Note that piece sizes must be powers-of-2, so all │ │ │ │ per-piece merkle trees are complete. │ │ │ │ A SHA-256 hash of all zeros is internally used to indicate a hash │ │ │ │ that has not been set. Setting such hash will not be considered set │ │ │ │ when calling generate(). │ │ │ │ This function will throw std::system_error if it is called on an │ │ │ │ object constructed with the v1_only flag.

    │ │ │ │ - │ │ │ │ -[report issue]
    │ │ │ │ -
    │ │ │ │ -

    add_url_seed() add_http_seed()

    │ │ │ │ + │ │ │ │ +[report issue]
    │ │ │ │ +
    │ │ │ │ +

    add_http_seed() add_url_seed()

    │ │ │ │
    │ │ │ │ -void add_url_seed (string_view url);
    │ │ │ │  void add_http_seed (string_view url);
    │ │ │ │ +void add_url_seed (string_view url);
    │ │ │ │  
    │ │ │ │

    This adds a url seed to the torrent. You can have any number of url seeds. For a │ │ │ │ single file torrent, this should be an HTTP url, pointing to a file with identical │ │ │ │ content as the file of the torrent. For a multi-file torrent, it should point to │ │ │ │ a directory containing a directory with the same name as this torrent, and all the │ │ │ │ files of the torrent in it.

    │ │ │ │

    The second function, add_http_seed() adds an HTTP seed instead.

    │ │ │ │ @@ -318,18 +318,18 @@ │ │ │ │ │ │ │ │

    This function sets an X.509 certificate in PEM format to the torrent. This makes the │ │ │ │ torrent an SSL torrent. An SSL torrent requires that each peer has a valid certificate │ │ │ │ signed by this root certificate. For SSL torrents, all peers are connecting over SSL │ │ │ │ connections. For more information, see the section on ssl torrents.

    │ │ │ │

    The string is not the path to the cert, it's the actual content of the │ │ │ │ certificate.

    │ │ │ │ - │ │ │ │ -[report issue]
    │ │ │ │ -
    │ │ │ │ -

    priv() set_priv()

    │ │ │ │ + │ │ │ │ +[report issue]
    │ │ │ │ +
    │ │ │ │ +

    set_priv() priv()

    │ │ │ │
    │ │ │ │  void set_priv (bool p);
    │ │ │ │  bool priv () const;
    │ │ │ │  
    │ │ │ │

    Sets and queries the private flag of the torrent. │ │ │ │ Torrents with the private flag set ask the client to not use any other │ │ │ │ sources than the tracker for peers, and to not use DHT to advertise itself publicly, │ │ │ │ @@ -372,24 +372,24 @@ │ │ │ │ │ │ │ │

    the total number of bytes of all files and pad files

    │ │ │ │ │ │ │ │ [report issue]
    │ │ │ │
    │ │ │ │

    piece_size() piece_length()

    │ │ │ │
    │ │ │ │ -int piece_length () const;
    │ │ │ │  int piece_size (piece_index_t i) const;
    │ │ │ │ +int piece_length () const;
    │ │ │ │  
    │ │ │ │

    piece_length() returns the piece size of all pieces but the │ │ │ │ last one. piece_size() returns the size of the specified piece. │ │ │ │ these functions are just forwarding to the associated file_storage.

    │ │ │ │ - │ │ │ │ -[report issue]
    │ │ │ │ -
    │ │ │ │ -

    add_collection() add_similar_torrent()

    │ │ │ │ + │ │ │ │ +[report issue]
    │ │ │ │ +
    │ │ │ │ +

    add_similar_torrent() add_collection()

    │ │ │ │
    │ │ │ │  void add_collection (string_view c);
    │ │ │ │  void add_similar_torrent (sha1_hash ih);
    │ │ │ │  
    │ │ │ │

    Add similar torrents (by info-hash) or collections of similar torrents. │ │ │ │ Similar torrents are expected to share some files with this torrent. │ │ │ │ Torrents sharing a collection name with this torrent are also expected │ │ │ │ @@ -485,22 +485,22 @@ │ │ │ │

    Declared in "libtorrent/create_torrent.hpp"

    │ │ │ │
    │ │ │ │  void set_piece_hashes (create_torrent& t, std::string const& p
    │ │ │ │     , settings_interface const& settings, disk_io_constructor_type disk_io
    │ │ │ │     , std::function<void(piece_index_t)> const& f, error_code& ec);
    │ │ │ │  inline void set_piece_hashes (create_torrent& t, std::string const& p
    │ │ │ │     , std::function<void(piece_index_t)> const& f);
    │ │ │ │ -inline void set_piece_hashes (create_torrent& t, std::string const& p);
    │ │ │ │ -void set_piece_hashes (create_torrent& t, std::string const& p
    │ │ │ │ -   , std::function<void(piece_index_t)> const& f, error_code& ec);
    │ │ │ │ -inline void set_piece_hashes (create_torrent& t, std::string const& p, error_code& ec);
    │ │ │ │  inline void set_piece_hashes (create_torrent& t, std::string const& p
    │ │ │ │     , settings_interface const& settings
    │ │ │ │     , std::function<void(piece_index_t)> const& f);
    │ │ │ │  void set_piece_hashes (create_torrent& t, std::string const& p
    │ │ │ │ +   , std::function<void(piece_index_t)> const& f, error_code& ec);
    │ │ │ │ +inline void set_piece_hashes (create_torrent& t, std::string const& p);
    │ │ │ │ +inline void set_piece_hashes (create_torrent& t, std::string const& p, error_code& ec);
    │ │ │ │ +void set_piece_hashes (create_torrent& t, std::string const& p
    │ │ │ │     , settings_interface const& settings
    │ │ │ │     , std::function<void(piece_index_t)> const& f, error_code& ec);
    │ │ │ │  
    │ │ │ │

    This function will assume that the files added to the torrent file exists at path │ │ │ │ p, read those files and hash the content and set the hashes in the create_torrent │ │ │ │ object. The optional function f is called in between every hash that is set. f │ │ │ │ must have the following signature:

    │ │ │ │ ├── html2text {} │ │ │ │ │ @@ -8,26 +8,26 @@ │ │ │ │ │ o _g_e_n_e_r_a_t_e_(_)_ _g_e_n_e_r_a_t_e___b_u_f_(_) │ │ │ │ │ o _f_i_l_e_s_(_) │ │ │ │ │ o _s_e_t___c_o_m_m_e_n_t_(_) │ │ │ │ │ o _s_e_t___c_r_e_a_t_o_r_(_) │ │ │ │ │ o _s_e_t___c_r_e_a_t_i_o_n___d_a_t_e_(_) │ │ │ │ │ o _s_e_t___h_a_s_h_(_) │ │ │ │ │ o _s_e_t___h_a_s_h_2_(_) │ │ │ │ │ - o _a_d_d___u_r_l___s_e_e_d_(_)_ _a_d_d___h_t_t_p___s_e_e_d_(_) │ │ │ │ │ + o _a_d_d___h_t_t_p___s_e_e_d_(_)_ _a_d_d___u_r_l___s_e_e_d_(_) │ │ │ │ │ o _a_d_d___n_o_d_e_(_) │ │ │ │ │ o _a_d_d___t_r_a_c_k_e_r_(_) │ │ │ │ │ o _s_e_t___r_o_o_t___c_e_r_t_(_) │ │ │ │ │ - o _p_r_i_v_(_)_ _s_e_t___p_r_i_v_(_) │ │ │ │ │ + o _s_e_t___p_r_i_v_(_)_ _p_r_i_v_(_) │ │ │ │ │ o _n_u_m___p_i_e_c_e_s_(_) │ │ │ │ │ o _p_i_e_c_e___r_a_n_g_e_(_) │ │ │ │ │ o _f_i_l_e___r_a_n_g_e_(_) │ │ │ │ │ o _f_i_l_e___p_i_e_c_e___r_a_n_g_e_(_) │ │ │ │ │ o _t_o_t_a_l___s_i_z_e_(_) │ │ │ │ │ o _p_i_e_c_e___s_i_z_e_(_)_ _p_i_e_c_e___l_e_n_g_t_h_(_) │ │ │ │ │ - o _a_d_d___c_o_l_l_e_c_t_i_o_n_(_)_ _a_d_d___s_i_m_i_l_a_r___t_o_r_r_e_n_t_(_) │ │ │ │ │ + o _a_d_d___s_i_m_i_l_a_r___t_o_r_r_e_n_t_(_)_ _a_d_d___c_o_l_l_e_c_t_i_o_n_(_) │ │ │ │ │ * _a_d_d___f_i_l_e_s_(_) │ │ │ │ │ * _s_e_t___p_i_e_c_e___h_a_s_h_e_s_(_) │ │ │ │ │ This section describes the functions and classes that are used to create │ │ │ │ │ torrent files. It is a layered API with low level classes and higher level │ │ │ │ │ convenience functions. A torrent is created in 4 steps: │ │ │ │ │ 1. first the files that will be part of the torrent are determined. │ │ │ │ │ 2. the torrent properties are set, such as tracker url, web seeds, DHT nodes │ │ │ │ │ @@ -66,60 +66,60 @@ │ │ │ │ │ Declared in "_l_i_b_t_o_r_r_e_n_t_/_c_r_e_a_t_e___t_o_r_r_e_n_t_._h_p_p" │ │ │ │ │ This class holds state for creating a torrent. After having added all │ │ │ │ │ information to it, call _c_r_e_a_t_e___t_o_r_r_e_n_t_:_:_g_e_n_e_r_a_t_e_(_) to generate the torrent. The │ │ │ │ │ _e_n_t_r_y that's returned can then be bencoded into a .torrent file using _b_e_n_c_o_d_e │ │ │ │ │ _(_). │ │ │ │ │ struct create_torrent │ │ │ │ │ { │ │ │ │ │ + explicit ccrreeaattee__ttoorrrreenntt (torrent_info const& ti); │ │ │ │ │ explicit ccrreeaattee__ttoorrrreenntt (file_storage& fs, int piece_size = 0 │ │ │ │ │ , create_flags_t flags = {}); │ │ │ │ │ - explicit ccrreeaattee__ttoorrrreenntt (torrent_info const& ti); │ │ │ │ │ - std::vector ggeenneerraattee__bbuuff () const; │ │ │ │ │ entry ggeenneerraattee () const; │ │ │ │ │ + std::vector ggeenneerraattee__bbuuff () const; │ │ │ │ │ file_storage const& ffiilleess () const; │ │ │ │ │ void sseett__ccoommmmeenntt (char const* str); │ │ │ │ │ void sseett__ccrreeaattoorr (char const* str); │ │ │ │ │ void sseett__ccrreeaattiioonn__ddaattee (std::time_t timestamp); │ │ │ │ │ void sseett__hhaasshh (piece_index_t index, sha1_hash const& h); │ │ │ │ │ void sseett__hhaasshh22 (file_index_t file, piece_index_t::diff_type piece, │ │ │ │ │ sha256_hash const& h); │ │ │ │ │ - void aadddd__uurrll__sseeeedd (string_view url); │ │ │ │ │ void aadddd__hhttttpp__sseeeedd (string_view url); │ │ │ │ │ + void aadddd__uurrll__sseeeedd (string_view url); │ │ │ │ │ void aadddd__nnooddee (std::pair node); │ │ │ │ │ void aadddd__ttrraacckkeerr (string_view url, int tier = 0); │ │ │ │ │ void sseett__rroooott__cceerrtt (string_view cert); │ │ │ │ │ void sseett__pprriivv (bool p); │ │ │ │ │ bool pprriivv () const; │ │ │ │ │ - bool iiss__vv11__oonnllyy () const; │ │ │ │ │ bool iiss__vv22__oonnllyy () const; │ │ │ │ │ + bool iiss__vv11__oonnllyy () const; │ │ │ │ │ int nnuumm__ppiieecceess () const; │ │ │ │ │ piece_index_t eenndd__ppiieeccee () const; │ │ │ │ │ index_range ppiieeccee__rraannggee () const noexcept; │ │ │ │ │ file_index_t eenndd__ffiillee () const; │ │ │ │ │ index_range ffiillee__rraannggee () const noexcept; │ │ │ │ │ index_range ffiillee__ppiieeccee__rraannggee (file_index_t f); │ │ │ │ │ std::int64_t ttoottaall__ssiizzee () const; │ │ │ │ │ - int ppiieeccee__lleennggtthh () const; │ │ │ │ │ int ppiieeccee__ssiizzee (piece_index_t i) const; │ │ │ │ │ + int ppiieeccee__lleennggtthh () const; │ │ │ │ │ void aadddd__ccoolllleeccttiioonn (string_view c); │ │ │ │ │ void aadddd__ssiimmiillaarr__ttoorrrreenntt (sha1_hash ih); │ │ │ │ │ │ │ │ │ │ static constexpr create_flags_t mmooddiiffiiccaattiioonn__ttiimmee = 2_bit; │ │ │ │ │ static constexpr create_flags_t ssyymmlliinnkkss = 3_bit; │ │ │ │ │ static constexpr create_flags_t vv22__oonnllyy = 5_bit; │ │ │ │ │ static constexpr create_flags_t vv11__oonnllyy = 6_bit; │ │ │ │ │ static constexpr create_flags_t ccaannoonniiccaall__ffiilleess = 7_bit; │ │ │ │ │ static constexpr create_flags_t nnoo__aattttrriibbuutteess = 8_bit; │ │ │ │ │ static constexpr create_flags_t ccaannoonniiccaall__ffiilleess__nnoo__ttaaiill__ppaaddddiinngg = 9_bit; │ │ │ │ │ }; │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ********** ccrreeaattee__ttoorrrreenntt(()) ********** │ │ │ │ │ +explicit ccrreeaattee__ttoorrrreenntt (torrent_info const& ti); │ │ │ │ │ explicit ccrreeaattee__ttoorrrreenntt (file_storage& fs, int piece_size = 0 │ │ │ │ │ , create_flags_t flags = {}); │ │ │ │ │ -explicit ccrreeaattee__ttoorrrreenntt (torrent_info const& ti); │ │ │ │ │ The piece_size is the size of each piece in bytes. It must be a power of 2 and │ │ │ │ │ a minimum of 16 kiB. If a piece size of 0 is specified, a piece_size will be │ │ │ │ │ set automatically. │ │ │ │ │ The flags arguments specifies options for the torrent creation. It can be any │ │ │ │ │ combination of the flags defined by create_flags_t. │ │ │ │ │ The _f_i_l_e___s_t_o_r_a_g_e (fs) parameter defines the files, sizes and their properties │ │ │ │ │ for the torrent to be created. Set this up first, before passing it to the │ │ │ │ │ @@ -131,16 +131,16 @@ │ │ │ │ │ (such as _s_e_t___h_a_s_h_(_)), will have any affect. Instead of using this overload, │ │ │ │ │ consider using _w_r_i_t_e___t_o_r_r_e_n_t___f_i_l_e_(_) instead. │ │ │ │ │ Warning │ │ │ │ │ The _f_i_l_e___s_t_o_r_a_g_e and _t_o_r_r_e_n_t___i_n_f_o objects must stay alive for the entire │ │ │ │ │ duration of the _c_r_e_a_t_e___t_o_r_r_e_n_t object. │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ********** ggeenneerraattee(()) ggeenneerraattee__bbuuff(()) ********** │ │ │ │ │ -std::vector ggeenneerraattee__bbuuff () const; │ │ │ │ │ entry ggeenneerraattee () const; │ │ │ │ │ +std::vector ggeenneerraattee__bbuuff () const; │ │ │ │ │ This function will generate the .torrent file as a bencode tree, or a bencoded │ │ │ │ │ into a buffer. In order to encode the _e_n_t_r_y into a flat file, use the _b_e_n_c_o_d_e_(_) │ │ │ │ │ function. │ │ │ │ │ The function returning an _e_n_t_r_y may be useful to add custom entries to the │ │ │ │ │ torrent file before bencoding it and saving it to disk. │ │ │ │ │ Whether the resulting torrent object is v1, v2 or hybrid depends on whether any │ │ │ │ │ of the v1_only or v2_only flags were set on the constructor. If neither were │ │ │ │ │ @@ -197,17 +197,17 @@ │ │ │ │ │ the merkle tree formed by the piece's 16 kiB blocks. Note that piece sizes must │ │ │ │ │ be powers-of-2, so all per-piece merkle trees are complete. A SHA-256 hash of │ │ │ │ │ all zeros is internally used to indicate a hash that has not been set. Setting │ │ │ │ │ such hash will not be considered set when calling _g_e_n_e_r_a_t_e_(_). This function │ │ │ │ │ will throw std::system_error if it is called on an object constructed with the │ │ │ │ │ v1_only flag. │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ -********** aadddd__uurrll__sseeeedd(()) aadddd__hhttttpp__sseeeedd(()) ********** │ │ │ │ │ -void aadddd__uurrll__sseeeedd (string_view url); │ │ │ │ │ +********** aadddd__hhttttpp__sseeeedd(()) aadddd__uurrll__sseeeedd(()) ********** │ │ │ │ │ void aadddd__hhttttpp__sseeeedd (string_view url); │ │ │ │ │ +void aadddd__uurrll__sseeeedd (string_view url); │ │ │ │ │ This adds a url seed to the torrent. You can have any number of url seeds. For │ │ │ │ │ a single file torrent, this should be an HTTP url, pointing to a file with │ │ │ │ │ identical content as the file of the torrent. For a multi-file torrent, it │ │ │ │ │ should point to a directory containing a directory with the same name as this │ │ │ │ │ torrent, and all the files of the torrent in it. │ │ │ │ │ The second function, add_http_seed() adds an HTTP seed instead. │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ @@ -234,15 +234,15 @@ │ │ │ │ │ makes the torrent an SSSSLL ttoorrrreenntt. An SSL torrent requires that each peer has a │ │ │ │ │ valid certificate signed by this root certificate. For SSL torrents, all peers │ │ │ │ │ are connecting over SSL connections. For more information, see the section on │ │ │ │ │ _s_s_l_ _t_o_r_r_e_n_t_s. │ │ │ │ │ The string is not the path to the cert, it's the actual content of the │ │ │ │ │ certificate. │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ -********** pprriivv(()) sseett__pprriivv(()) ********** │ │ │ │ │ +********** sseett__pprriivv(()) pprriivv(()) ********** │ │ │ │ │ void sseett__pprriivv (bool p); │ │ │ │ │ bool pprriivv () const; │ │ │ │ │ Sets and queries the private flag of the torrent. Torrents with the private │ │ │ │ │ flag set ask the client to not use any other sources than the tracker for │ │ │ │ │ peers, and to not use DHT to advertise itself publicly, only the tracker. │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ********** nnuumm__ppiieecceess(()) ********** │ │ │ │ │ @@ -263,21 +263,21 @@ │ │ │ │ │ delta from the first piece in the file. i.e. the first index is 0. │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ********** ttoottaall__ssiizzee(()) ********** │ │ │ │ │ std::int64_t ttoottaall__ssiizzee () const; │ │ │ │ │ the total number of bytes of all files and pad files │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ********** ppiieeccee__ssiizzee(()) ppiieeccee__lleennggtthh(()) ********** │ │ │ │ │ -int ppiieeccee__lleennggtthh () const; │ │ │ │ │ int ppiieeccee__ssiizzee (piece_index_t i) const; │ │ │ │ │ +int ppiieeccee__lleennggtthh () const; │ │ │ │ │ piece_length() returns the piece size of all pieces but the last one. │ │ │ │ │ piece_size() returns the size of the specified piece. these functions are just │ │ │ │ │ forwarding to the associated _f_i_l_e___s_t_o_r_a_g_e. │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ -********** aadddd__ccoolllleeccttiioonn(()) aadddd__ssiimmiillaarr__ttoorrrreenntt(()) ********** │ │ │ │ │ +********** aadddd__ssiimmiillaarr__ttoorrrreenntt(()) aadddd__ccoolllleeccttiioonn(()) ********** │ │ │ │ │ void aadddd__ccoolllleeccttiioonn (string_view c); │ │ │ │ │ void aadddd__ssiimmiillaarr__ttoorrrreenntt (sha1_hash ih); │ │ │ │ │ Add similar torrents (by info-hash) or collections of similar torrents. Similar │ │ │ │ │ torrents are expected to share some files with this torrent. Torrents sharing a │ │ │ │ │ collection name with this torrent are also expected to share files with this │ │ │ │ │ torrent. A torrent may have more than one collection and more than one similar │ │ │ │ │ torrents. For more information, see _B_E_P_ _3_8. │ │ │ │ │ @@ -352,22 +352,22 @@ │ │ │ │ │ ************ sseett__ppiieeccee__hhaasshheess(()) ************ │ │ │ │ │ Declared in "_l_i_b_t_o_r_r_e_n_t_/_c_r_e_a_t_e___t_o_r_r_e_n_t_._h_p_p" │ │ │ │ │ void sseett__ppiieeccee__hhaasshheess (create_torrent& t, std::string const& p │ │ │ │ │ , settings_interface const& settings, disk_io_constructor_type disk_io │ │ │ │ │ , std::function const& f, error_code& ec); │ │ │ │ │ inline void sseett__ppiieeccee__hhaasshheess (create_torrent& t, std::string const& p │ │ │ │ │ , std::function const& f); │ │ │ │ │ -inline void sseett__ppiieeccee__hhaasshheess (create_torrent& t, std::string const& p); │ │ │ │ │ +inline void sseett__ppiieeccee__hhaasshheess (create_torrent& t, std::string const& p │ │ │ │ │ + , settings_interface const& settings │ │ │ │ │ + , std::function const& f); │ │ │ │ │ void sseett__ppiieeccee__hhaasshheess (create_torrent& t, std::string const& p │ │ │ │ │ , std::function const& f, error_code& ec); │ │ │ │ │ +inline void sseett__ppiieeccee__hhaasshheess (create_torrent& t, std::string const& p); │ │ │ │ │ inline void sseett__ppiieeccee__hhaasshheess (create_torrent& t, std::string const& p, │ │ │ │ │ error_code& ec); │ │ │ │ │ -inline void sseett__ppiieeccee__hhaasshheess (create_torrent& t, std::string const& p │ │ │ │ │ - , settings_interface const& settings │ │ │ │ │ - , std::function const& f); │ │ │ │ │ void sseett__ppiieeccee__hhaasshheess (create_torrent& t, std::string const& p │ │ │ │ │ , settings_interface const& settings │ │ │ │ │ , std::function const& f, error_code& ec); │ │ │ │ │ This function will assume that the files added to the torrent file exists at │ │ │ │ │ path p, read those files and hash the content and set the hashes in the │ │ │ │ │ create_torrent object. The optional function f is called in between every hash │ │ │ │ │ that is set. f must have the following signature: │ │ │ ├── ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-Custom_Storage.html │ │ │ │ @@ -51,31 +51,31 @@ │ │ │ │
  • get_status()
  • │ │ │ │
  • abort()
  • │ │ │ │
  • submit_jobs()
  • │ │ │ │
  • settings_updated()
  • │ │ │ │ │ │ │ │ │ │ │ │
  • storage_holder
  • │ │ │ │ -
  • buffer_allocator_interface
  • │ │ │ │ -
  • disk_buffer_holder
  • │ │ │ │

    You have some control over session configuration through the session::apply_settings() │ │ │ │ member function. To change one or more configuration options, create a settings_pack │ │ │ │ object and fill it with the settings to be set and pass it in to session::apply_settings().

    │ │ │ │

    The settings_pack object is a collection of settings updates that are applied │ │ │ │ @@ -133,21 +133,21 @@ │ │ │ │ the constructor. The callbacks will be run in the network thread.

    │ │ │ │
    │ │ │ │  struct disk_interface
    │ │ │ │  {
    │ │ │ │     virtual storage_holder new_torrent (storage_params const& p
    │ │ │ │        , std::shared_ptr<void> const& torrent) = 0;
    │ │ │ │     virtual void remove_torrent (storage_index_t) = 0;
    │ │ │ │ +   virtual void async_read (storage_index_t storage, peer_request const& r
    │ │ │ │ +      , std::function<void(disk_buffer_holder, storage_error const&)> handler
    │ │ │ │ +      , disk_job_flags_t flags = {}) = 0;
    │ │ │ │     virtual bool async_write (storage_index_t storage, peer_request const& r
    │ │ │ │        , char const* buf, std::shared_ptr<disk_observer> o
    │ │ │ │        , std::function<void(storage_error const&)> handler
    │ │ │ │        , disk_job_flags_t flags = {}) = 0;
    │ │ │ │ -   virtual void async_read (storage_index_t storage, peer_request const& r
    │ │ │ │ -      , std::function<void(disk_buffer_holder, storage_error const&)> handler
    │ │ │ │ -      , disk_job_flags_t flags = {}) = 0;
    │ │ │ │     virtual void async_hash (storage_index_t storage, piece_index_t piece, span<sha256_hash> v2
    │ │ │ │        , disk_job_flags_t flags
    │ │ │ │        , std::function<void(piece_index_t, sha1_hash const&, storage_error const&)> handler) = 0;
    │ │ │ │     virtual void async_hash2 (storage_index_t storage, piece_index_t piece, int offset, disk_job_flags_t flags
    │ │ │ │        , std::function<void(piece_index_t, sha256_hash const&, storage_error const&)> handler) = 0;
    │ │ │ │     virtual void async_move_storage (storage_index_t storage, std::string p, move_flags_t flags
    │ │ │ │        , std::function<void(status_t, std::string const&, storage_error const&)> handler) = 0;
    │ │ │ │ @@ -204,21 +204,21 @@
    │ │ │ │  delete any files from disk, just to clean up any resources associated
    │ │ │ │  with the specified storage.

    │ │ │ │ │ │ │ │ [report issue] │ │ │ │
    │ │ │ │

    async_read() async_write()

    │ │ │ │
    │ │ │ │ +virtual void async_read (storage_index_t storage, peer_request const& r
    │ │ │ │ +      , std::function<void(disk_buffer_holder, storage_error const&)> handler
    │ │ │ │ +      , disk_job_flags_t flags = {}) = 0;
    │ │ │ │  virtual bool async_write (storage_index_t storage, peer_request const& r
    │ │ │ │        , char const* buf, std::shared_ptr<disk_observer> o
    │ │ │ │        , std::function<void(storage_error const&)> handler
    │ │ │ │        , disk_job_flags_t flags = {}) = 0;
    │ │ │ │ -virtual void async_read (storage_index_t storage, peer_request const& r
    │ │ │ │ -      , std::function<void(disk_buffer_holder, storage_error const&)> handler
    │ │ │ │ -      , disk_job_flags_t flags = {}) = 0;
    │ │ │ │  
    │ │ │ │

    perform a read or write operation from/to the specified storage │ │ │ │ index and the specified request. When the operation completes, call │ │ │ │ handler possibly with a disk_buffer_holder, holding the buffer with │ │ │ │ the result. Flags may be set to affect the read operation. See │ │ │ │ disk_job_flags_t.

    │ │ │ │

    The disk_observer is a callback to indicate that │ │ │ │ @@ -469,27 +469,64 @@ │ │ │ │ internal libtorrent torrent object to tie the storage object allocated │ │ │ │ for a torrent to the lifetime of the internal torrent object. When a │ │ │ │ torrent is removed from the session, this holder is destructed and will │ │ │ │ inform the disk object.

    │ │ │ │
    │ │ │ │  struct storage_holder
    │ │ │ │  {
    │ │ │ │ -   ~storage_holder ();
    │ │ │ │     storage_holder () = default;
    │ │ │ │     storage_holder (storage_index_t idx, disk_interface& disk_io);
    │ │ │ │ +   ~storage_holder ();
    │ │ │ │     explicit operator bool () const;
    │ │ │ │     operator storage_index_t () const;
    │ │ │ │     void reset ();
    │ │ │ │     storage_holder& operator= (storage_holder const&) = delete;
    │ │ │ │     storage_holder (storage_holder const&) = delete;
    │ │ │ │     storage_holder (storage_holder&& rhs) noexcept;
    │ │ │ │     storage_holder& operator= (storage_holder&& rhs) noexcept;
    │ │ │ │  };
    │ │ │ │  
    │ │ │ │ +[report issue]
    │ │ │ │ +
    │ │ │ │ +

    settings_interface

    │ │ │ │ +

    Declared in "libtorrent/settings_pack.hpp"

    │ │ │ │ +

    the common interface to settings_pack and the internal representation of │ │ │ │ +settings.

    │ │ │ │ +
    │ │ │ │ +struct settings_interface
    │ │ │ │ +{
    │ │ │ │ +   virtual bool has_val (int name) const = 0;
    │ │ │ │ +   virtual void set_str (int name, std::string val) = 0;
    │ │ │ │ +   virtual void set_bool (int name, bool val) = 0;
    │ │ │ │ +   virtual void set_int (int name, int val) = 0;
    │ │ │ │ +   virtual bool get_bool (int name) const = 0;
    │ │ │ │ +   virtual std::string const& get_str (int name) const = 0;
    │ │ │ │ +   virtual int get_int (int name) const = 0;
    │ │ │ │ +};
    │ │ │ │ +
    │ │ │ │ +[report issue]
    │ │ │ │ +
    │ │ │ │ +

    disk_observer

    │ │ │ │ +

    Declared in "libtorrent/disk_observer.hpp"

    │ │ │ │ +
    │ │ │ │ +struct disk_observer
    │ │ │ │ +{
    │ │ │ │ +   virtual void on_disk () = 0;
    │ │ │ │ +};
    │ │ │ │ +
    │ │ │ │ +[report issue]
    │ │ │ │ +

    on_disk()

    │ │ │ │ +
    │ │ │ │ +virtual void on_disk () = 0;
    │ │ │ │ +
    │ │ │ │ +

    called when the disk cache size has dropped │ │ │ │ +below the low watermark again and we can │ │ │ │ +resume downloading from peers

    │ │ │ │ [report issue]
    │ │ │ │ +
    │ │ │ │
    │ │ │ │

    buffer_allocator_interface

    │ │ │ │

    Declared in "libtorrent/disk_buffer_holder.hpp"

    │ │ │ │

    the interface for freeing disk buffers, used by the disk_buffer_holder. │ │ │ │ when implementing disk_interface, this must also be implemented in order │ │ │ │ to return disk buffers back to libtorrent

    │ │ │ │
    │ │ │ │ @@ -507,16 +544,16 @@
    │ │ │ │  

    If this buffer holder is moved-from, default constructed or reset, │ │ │ │ data() will return nullptr.

    │ │ │ │
    │ │ │ │  struct disk_buffer_holder
    │ │ │ │  {
    │ │ │ │     disk_buffer_holder& operator= (disk_buffer_holder&&) & noexcept;
    │ │ │ │     disk_buffer_holder (disk_buffer_holder&&) noexcept;
    │ │ │ │ -   disk_buffer_holder& operator= (disk_buffer_holder const&) = delete;
    │ │ │ │     disk_buffer_holder (disk_buffer_holder const&) = delete;
    │ │ │ │ +   disk_buffer_holder& operator= (disk_buffer_holder const&) = delete;
    │ │ │ │     disk_buffer_holder (buffer_allocator_interface& alloc
    │ │ │ │        , char* buf, int sz) noexcept;
    │ │ │ │     disk_buffer_holder () noexcept = default;
    │ │ │ │     ~disk_buffer_holder ();
    │ │ │ │     char* data () const noexcept;
    │ │ │ │     void reset ();
    │ │ │ │     void swap (disk_buffer_holder& h) noexcept;
    │ │ │ │ @@ -581,53 +618,16 @@
    │ │ │ │  
    │ │ │ │

    bool()

    │ │ │ │
    │ │ │ │  explicit operator bool () const noexcept;
    │ │ │ │  
    │ │ │ │

    implicitly convertible to true if the object is currently holding a │ │ │ │ buffer

    │ │ │ │ -[report issue]
    │ │ │ │ -
    │ │ │ │ -
    │ │ │ │ -

    disk_observer

    │ │ │ │ -

    Declared in "libtorrent/disk_observer.hpp"

    │ │ │ │ -
    │ │ │ │ -struct disk_observer
    │ │ │ │ -{
    │ │ │ │ -   virtual void on_disk () = 0;
    │ │ │ │ -};
    │ │ │ │ -
    │ │ │ │ -[report issue]
    │ │ │ │ -

    on_disk()

    │ │ │ │ -
    │ │ │ │ -virtual void on_disk () = 0;
    │ │ │ │ -
    │ │ │ │ -

    called when the disk cache size has dropped │ │ │ │ -below the low watermark again and we can │ │ │ │ -resume downloading from peers

    │ │ │ │ -[report issue]
    │ │ │ │ -
    │ │ │ │ -
    │ │ │ │ -

    settings_interface

    │ │ │ │ -

    Declared in "libtorrent/settings_pack.hpp"

    │ │ │ │ -

    the common interface to settings_pack and the internal representation of │ │ │ │ -settings.

    │ │ │ │ -
    │ │ │ │ -struct settings_interface
    │ │ │ │ -{
    │ │ │ │ -   virtual void set_str (int name, std::string val) = 0;
    │ │ │ │ -   virtual void set_int (int name, int val) = 0;
    │ │ │ │ -   virtual void set_bool (int name, bool val) = 0;
    │ │ │ │ -   virtual bool has_val (int name) const = 0;
    │ │ │ │ -   virtual std::string const& get_str (int name) const = 0;
    │ │ │ │ -   virtual bool get_bool (int name) const = 0;
    │ │ │ │ -   virtual int get_int (int name) const = 0;
    │ │ │ │ -};
    │ │ │ │ -
    │ │ │ │ [report issue]
    │ │ │ │ + │ │ │ │
    │ │ │ │

    file_open_mode_t

    │ │ │ │

    Declared in "libtorrent/disk_interface.hpp"

    │ │ │ │
    │ │ │ │
    read_only
    │ │ │ │
    open the file for reading only
    │ │ │ │
    │ │ │ │ ├── html2text {} │ │ │ │ │ @@ -20,27 +20,27 @@ │ │ │ │ │ o _a_s_y_n_c___c_l_e_a_r___p_i_e_c_e_(_) │ │ │ │ │ o _u_p_d_a_t_e___s_t_a_t_s___c_o_u_n_t_e_r_s_(_) │ │ │ │ │ o _g_e_t___s_t_a_t_u_s_(_) │ │ │ │ │ o _a_b_o_r_t_(_) │ │ │ │ │ o _s_u_b_m_i_t___j_o_b_s_(_) │ │ │ │ │ o _s_e_t_t_i_n_g_s___u_p_d_a_t_e_d_(_) │ │ │ │ │ * _s_t_o_r_a_g_e___h_o_l_d_e_r │ │ │ │ │ + * _s_e_t_t_i_n_g_s___i_n_t_e_r_f_a_c_e │ │ │ │ │ + * _d_i_s_k___o_b_s_e_r_v_e_r │ │ │ │ │ + o _o_n___d_i_s_k_(_) │ │ │ │ │ * _b_u_f_f_e_r___a_l_l_o_c_a_t_o_r___i_n_t_e_r_f_a_c_e │ │ │ │ │ * _d_i_s_k___b_u_f_f_e_r___h_o_l_d_e_r │ │ │ │ │ o _d_i_s_k___b_u_f_f_e_r___h_o_l_d_e_r_(_) │ │ │ │ │ o _d_i_s_k___b_u_f_f_e_r___h_o_l_d_e_r_(_) │ │ │ │ │ o _~_d_i_s_k___b_u_f_f_e_r___h_o_l_d_e_r_(_) │ │ │ │ │ o _d_a_t_a_(_) │ │ │ │ │ o _r_e_s_e_t_(_) │ │ │ │ │ o _s_w_a_p_(_) │ │ │ │ │ o _i_s___m_u_t_a_b_l_e_(_) │ │ │ │ │ o _b_o_o_l_(_) │ │ │ │ │ - * _d_i_s_k___o_b_s_e_r_v_e_r │ │ │ │ │ - o _o_n___d_i_s_k_(_) │ │ │ │ │ - * _s_e_t_t_i_n_g_s___i_n_t_e_r_f_a_c_e │ │ │ │ │ * _f_i_l_e___o_p_e_n___m_o_d_e___t │ │ │ │ │ You have some control over _s_e_s_s_i_o_n configuration through the session:: │ │ │ │ │ apply_settings() member function. To change one or more configuration options, │ │ │ │ │ create a _s_e_t_t_i_n_g_s___p_a_c_k object and fill it with the settings to be set and pass │ │ │ │ │ it in to session::apply_settings(). │ │ │ │ │ The _s_e_t_t_i_n_g_s___p_a_c_k object is a collection of settings updates that are applied │ │ │ │ │ to the _s_e_s_s_i_o_n when passed to session::apply_settings(). It's empty when │ │ │ │ │ @@ -90,21 +90,21 @@ │ │ │ │ │ thread via the io_context object passed into the constructor. The callbacks │ │ │ │ │ will be run in the network thread. │ │ │ │ │ struct disk_interface │ │ │ │ │ { │ │ │ │ │ virtual storage_holder nneeww__ttoorrrreenntt (storage_params const& p │ │ │ │ │ , std::shared_ptr const& torrent) = 0; │ │ │ │ │ virtual void rreemmoovvee__ttoorrrreenntt (storage_index_t) = 0; │ │ │ │ │ + virtual void aassyynncc__rreeaadd (storage_index_t storage, peer_request const& r │ │ │ │ │ + , std::function handler │ │ │ │ │ + , disk_job_flags_t flags = {}) = 0; │ │ │ │ │ virtual bool aassyynncc__wwrriittee (storage_index_t storage, peer_request const& r │ │ │ │ │ , char const* buf, std::shared_ptr o │ │ │ │ │ , std::function handler │ │ │ │ │ , disk_job_flags_t flags = {}) = 0; │ │ │ │ │ - virtual void aassyynncc__rreeaadd (storage_index_t storage, peer_request const& r │ │ │ │ │ - , std::function handler │ │ │ │ │ - , disk_job_flags_t flags = {}) = 0; │ │ │ │ │ virtual void aassyynncc__hhaasshh (storage_index_t storage, piece_index_t piece, │ │ │ │ │ span v2 │ │ │ │ │ , disk_job_flags_t flags │ │ │ │ │ , std::function handler) = 0; │ │ │ │ │ virtual void aassyynncc__hhaasshh22 (storage_index_t storage, piece_index_t piece, int │ │ │ │ │ offset, disk_job_flags_t flags │ │ │ │ │ @@ -160,21 +160,21 @@ │ │ │ │ │ ********** rreemmoovvee__ttoorrrreenntt(()) ********** │ │ │ │ │ virtual void rreemmoovvee__ttoorrrreenntt (storage_index_t) = 0; │ │ │ │ │ remove the storage with the specified index. This is not expected to delete any │ │ │ │ │ files from disk, just to clean up any resources associated with the specified │ │ │ │ │ storage. │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ********** aassyynncc__rreeaadd(()) aassyynncc__wwrriittee(()) ********** │ │ │ │ │ +virtual void aassyynncc__rreeaadd (storage_index_t storage, peer_request const& r │ │ │ │ │ + , std::function handler │ │ │ │ │ + , disk_job_flags_t flags = {}) = 0; │ │ │ │ │ virtual bool aassyynncc__wwrriittee (storage_index_t storage, peer_request const& r │ │ │ │ │ , char const* buf, std::shared_ptr o │ │ │ │ │ , std::function handler │ │ │ │ │ , disk_job_flags_t flags = {}) = 0; │ │ │ │ │ -virtual void aassyynncc__rreeaadd (storage_index_t storage, peer_request const& r │ │ │ │ │ - , std::function handler │ │ │ │ │ - , disk_job_flags_t flags = {}) = 0; │ │ │ │ │ perform a read or write operation from/to the specified storage index and the │ │ │ │ │ specified request. When the operation completes, call handler possibly with a │ │ │ │ │ _d_i_s_k___b_u_f_f_e_r___h_o_l_d_e_r, holding the buffer with the result. Flags may be set to │ │ │ │ │ affect the read operation. See disk_job_flags_t. │ │ │ │ │ The _d_i_s_k___o_b_s_e_r_v_e_r is a callback to indicate that the store buffer/disk write │ │ │ │ │ queue is below the watermark to let peers start writing buffers to disk again. │ │ │ │ │ When async_write() returns true, indicating the write queue is full, the peer │ │ │ │ │ @@ -361,26 +361,53 @@ │ │ │ │ │ a unique, owning, reference to the storage of a torrent in a disk io subsystem │ │ │ │ │ (class that implements _d_i_s_k___i_n_t_e_r_f_a_c_e). This is held by the internal libtorrent │ │ │ │ │ torrent object to tie the storage object allocated for a torrent to the │ │ │ │ │ lifetime of the internal torrent object. When a torrent is removed from the │ │ │ │ │ _s_e_s_s_i_o_n, this holder is destructed and will inform the disk object. │ │ │ │ │ struct storage_holder │ │ │ │ │ { │ │ │ │ │ - ~~ssttoorraaggee__hhoollddeerr (); │ │ │ │ │ ssttoorraaggee__hhoollddeerr () = default; │ │ │ │ │ ssttoorraaggee__hhoollddeerr (storage_index_t idx, disk_interface& disk_io); │ │ │ │ │ + ~~ssttoorraaggee__hhoollddeerr (); │ │ │ │ │ explicit operator bbooooll () const; │ │ │ │ │ operator ssttoorraaggee__iinnddeexx__tt () const; │ │ │ │ │ void rreesseett (); │ │ │ │ │ storage_holder& ooppeerraattoorr== (storage_holder const&) = delete; │ │ │ │ │ ssttoorraaggee__hhoollddeerr (storage_holder const&) = delete; │ │ │ │ │ ssttoorraaggee__hhoollddeerr (storage_holder&& rhs) noexcept; │ │ │ │ │ storage_holder& ooppeerraattoorr== (storage_holder&& rhs) noexcept; │ │ │ │ │ }; │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ +************ sseettttiinnggss__iinntteerrffaaccee ************ │ │ │ │ │ +Declared in "_l_i_b_t_o_r_r_e_n_t_/_s_e_t_t_i_n_g_s___p_a_c_k_._h_p_p" │ │ │ │ │ +the common interface to _s_e_t_t_i_n_g_s___p_a_c_k and the internal representation of │ │ │ │ │ +settings. │ │ │ │ │ +struct settings_interface │ │ │ │ │ +{ │ │ │ │ │ + virtual bool hhaass__vvaall (int name) const = 0; │ │ │ │ │ + virtual void sseett__ssttrr (int name, std::string val) = 0; │ │ │ │ │ + virtual void sseett__bbooooll (int name, bool val) = 0; │ │ │ │ │ + virtual void sseett__iinntt (int name, int val) = 0; │ │ │ │ │ + virtual bool ggeett__bbooooll (int name) const = 0; │ │ │ │ │ + virtual std::string const& ggeett__ssttrr (int name) const = 0; │ │ │ │ │ + virtual int ggeett__iinntt (int name) const = 0; │ │ │ │ │ +}; │ │ │ │ │ +[_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ +************ ddiisskk__oobbsseerrvveerr ************ │ │ │ │ │ +Declared in "_l_i_b_t_o_r_r_e_n_t_/_d_i_s_k___o_b_s_e_r_v_e_r_._h_p_p" │ │ │ │ │ +struct disk_observer │ │ │ │ │ +{ │ │ │ │ │ + virtual void oonn__ddiisskk () = 0; │ │ │ │ │ +}; │ │ │ │ │ +[_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ +********** oonn__ddiisskk(()) ********** │ │ │ │ │ +virtual void oonn__ddiisskk () = 0; │ │ │ │ │ +called when the disk cache size has dropped below the low watermark again and │ │ │ │ │ +we can resume downloading from peers │ │ │ │ │ +[_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ************ bbuuffffeerr__aallllooccaattoorr__iinntteerrffaaccee ************ │ │ │ │ │ Declared in "_l_i_b_t_o_r_r_e_n_t_/_d_i_s_k___b_u_f_f_e_r___h_o_l_d_e_r_._h_p_p" │ │ │ │ │ the interface for freeing disk buffers, used by the _d_i_s_k___b_u_f_f_e_r___h_o_l_d_e_r. when │ │ │ │ │ implementing _d_i_s_k___i_n_t_e_r_f_a_c_e, this must also be implemented in order to return │ │ │ │ │ disk buffers back to libtorrent │ │ │ │ │ struct buffer_allocator_interface │ │ │ │ │ { │ │ │ │ │ @@ -393,16 +420,16 @@ │ │ │ │ │ it's destructed │ │ │ │ │ If this buffer holder is moved-from, default constructed or reset, data() will │ │ │ │ │ return nullptr. │ │ │ │ │ struct disk_buffer_holder │ │ │ │ │ { │ │ │ │ │ disk_buffer_holder& ooppeerraattoorr== (disk_buffer_holder&&) & noexcept; │ │ │ │ │ ddiisskk__bbuuffffeerr__hhoollddeerr (disk_buffer_holder&&) noexcept; │ │ │ │ │ - disk_buffer_holder& ooppeerraattoorr== (disk_buffer_holder const&) = delete; │ │ │ │ │ ddiisskk__bbuuffffeerr__hhoollddeerr (disk_buffer_holder const&) = delete; │ │ │ │ │ + disk_buffer_holder& ooppeerraattoorr== (disk_buffer_holder const&) = delete; │ │ │ │ │ ddiisskk__bbuuffffeerr__hhoollddeerr (buffer_allocator_interface& alloc │ │ │ │ │ , char* buf, int sz) noexcept; │ │ │ │ │ ddiisskk__bbuuffffeerr__hhoollddeerr () noexcept = default; │ │ │ │ │ ~~ddiisskk__bbuuffffeerr__hhoollddeerr (); │ │ │ │ │ char* ddaattaa () const noexcept; │ │ │ │ │ void rreesseett (); │ │ │ │ │ void sswwaapp (disk_buffer_holder& h) noexcept; │ │ │ │ │ @@ -442,41 +469,14 @@ │ │ │ │ │ bool iiss__mmuuttaabbllee () const noexcept; │ │ │ │ │ if this returns true, the buffer may not be modified in place │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ********** bbooooll(()) ********** │ │ │ │ │ explicit operator bbooooll () const noexcept; │ │ │ │ │ implicitly convertible to true if the object is currently holding a buffer │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ -************ ddiisskk__oobbsseerrvveerr ************ │ │ │ │ │ -Declared in "_l_i_b_t_o_r_r_e_n_t_/_d_i_s_k___o_b_s_e_r_v_e_r_._h_p_p" │ │ │ │ │ -struct disk_observer │ │ │ │ │ -{ │ │ │ │ │ - virtual void oonn__ddiisskk () = 0; │ │ │ │ │ -}; │ │ │ │ │ -[_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ -********** oonn__ddiisskk(()) ********** │ │ │ │ │ -virtual void oonn__ddiisskk () = 0; │ │ │ │ │ -called when the disk cache size has dropped below the low watermark again and │ │ │ │ │ -we can resume downloading from peers │ │ │ │ │ -[_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ -************ sseettttiinnggss__iinntteerrffaaccee ************ │ │ │ │ │ -Declared in "_l_i_b_t_o_r_r_e_n_t_/_s_e_t_t_i_n_g_s___p_a_c_k_._h_p_p" │ │ │ │ │ -the common interface to _s_e_t_t_i_n_g_s___p_a_c_k and the internal representation of │ │ │ │ │ -settings. │ │ │ │ │ -struct settings_interface │ │ │ │ │ -{ │ │ │ │ │ - virtual void sseett__ssttrr (int name, std::string val) = 0; │ │ │ │ │ - virtual void sseett__iinntt (int name, int val) = 0; │ │ │ │ │ - virtual void sseett__bbooooll (int name, bool val) = 0; │ │ │ │ │ - virtual bool hhaass__vvaall (int name) const = 0; │ │ │ │ │ - virtual std::string const& ggeett__ssttrr (int name) const = 0; │ │ │ │ │ - virtual bool ggeett__bbooooll (int name) const = 0; │ │ │ │ │ - virtual int ggeett__iinntt (int name) const = 0; │ │ │ │ │ -}; │ │ │ │ │ -[_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ************ ffiillee__ooppeenn__mmooddee__tt ************ │ │ │ │ │ Declared in "_l_i_b_t_o_r_r_e_n_t_/_d_i_s_k___i_n_t_e_r_f_a_c_e_._h_p_p" │ │ │ │ │ read_only │ │ │ │ │ open the file for reading only │ │ │ │ │ write_only │ │ │ │ │ open the file for writing only │ │ │ │ │ read_write │ │ │ ├── ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-DHT.html │ │ │ │ @@ -47,16 +47,16 @@ │ │ │ │
  • put_mutable_item()
  • │ │ │ │
  • get_infohashes_sample()
  • │ │ │ │
  • tick()
  • │ │ │ │
  • counters()
  • │ │ │ │ │ │ │ │ │ │ │ │
  • dht_state
  • │ │ │ │ -
  • dht_default_storage_constructor()
  • │ │ │ │ -
  • sign_mutable_item()
  • │ │ │ │ +
  • sign_mutable_item()
  • │ │ │ │ +
  • dht_default_storage_constructor()
  • │ │ │ │
  • announce_flags_t
  • │ │ │ │ │ │ │ │
    │ │ │ │ [report issue]
    │ │ │ │

    dht_storage_counters

    │ │ │ │

    Declared in "libtorrent/kademlia/dht_storage.hpp"

    │ │ │ │

    This structure hold the relevant counters for the storage

    │ │ │ │ @@ -309,25 +309,14 @@ │ │ │ │
    nodes
    │ │ │ │
    the bootstrap nodes saved from the buckets node
    │ │ │ │ │ │ │ │ [report issue]
    │ │ │ │
    nodes6
    │ │ │ │
    the bootstrap nodes saved from the IPv6 buckets node
    │ │ │ │
    │ │ │ │ -[report issue]
    │ │ │ │ -
    │ │ │ │ -

    dht_default_storage_constructor()

    │ │ │ │ -

    Declared in "libtorrent/kademlia/dht_storage.hpp"

    │ │ │ │ -
    │ │ │ │ -std::unique_ptr<dht_storage_interface> dht_default_storage_constructor (
    │ │ │ │ -   settings_interface const& settings);
    │ │ │ │ -
    │ │ │ │ -

    constructor for the default DHT storage. The DHT storage is responsible │ │ │ │ -for maintaining peers and mutable and immutable items announced and │ │ │ │ -stored/put to the DHT node.

    │ │ │ │ [report issue]
    │ │ │ │
    │ │ │ │

    sign_mutable_item()

    │ │ │ │

    Declared in "libtorrent/kademlia/item.hpp"

    │ │ │ │
    │ │ │ │  signature sign_mutable_item (
    │ │ │ │     span<char const> v
    │ │ │ │ @@ -338,14 +327,25 @@
    │ │ │ │  
    │ │ │ │

    given a byte range v and an optional byte range salt, a │ │ │ │ sequence number, public key pk (must be 32 bytes) and a secret key │ │ │ │ sk (must be 64 bytes), this function produces a signature which │ │ │ │ is written into a 64 byte buffer pointed to by sig. The caller │ │ │ │ is responsible for allocating the destination buffer that's passed in │ │ │ │ as the sig argument. Typically it would be allocated on the stack.

    │ │ │ │ +[report issue]
    │ │ │ │ +
    │ │ │ │ +

    dht_default_storage_constructor()

    │ │ │ │ +

    Declared in "libtorrent/kademlia/dht_storage.hpp"

    │ │ │ │ +
    │ │ │ │ +std::unique_ptr<dht_storage_interface> dht_default_storage_constructor (
    │ │ │ │ +   settings_interface const& settings);
    │ │ │ │ +
    │ │ │ │ +

    constructor for the default DHT storage. The DHT storage is responsible │ │ │ │ +for maintaining peers and mutable and immutable items announced and │ │ │ │ +stored/put to the DHT node.

    │ │ │ │ [report issue]
    │ │ │ │
    │ │ │ │

    announce_flags_t

    │ │ │ │

    Declared in "libtorrent/kademlia/announce_flags.hpp"

    │ │ │ │
    │ │ │ │
    seed
    │ │ │ │
    announce to DHT as a seed
    │ │ │ │ ├── html2text {} │ │ │ │ │ @@ -14,16 +14,16 @@ │ │ │ │ │ o _g_e_t___m_u_t_a_b_l_e___i_t_e_m___s_e_q_(_) │ │ │ │ │ o _g_e_t___m_u_t_a_b_l_e___i_t_e_m_(_) │ │ │ │ │ o _p_u_t___m_u_t_a_b_l_e___i_t_e_m_(_) │ │ │ │ │ o _g_e_t___i_n_f_o_h_a_s_h_e_s___s_a_m_p_l_e_(_) │ │ │ │ │ o _t_i_c_k_(_) │ │ │ │ │ o _c_o_u_n_t_e_r_s_(_) │ │ │ │ │ * _d_h_t___s_t_a_t_e │ │ │ │ │ - * _d_h_t___d_e_f_a_u_l_t___s_t_o_r_a_g_e___c_o_n_s_t_r_u_c_t_o_r_(_) │ │ │ │ │ * _s_i_g_n___m_u_t_a_b_l_e___i_t_e_m_(_) │ │ │ │ │ + * _d_h_t___d_e_f_a_u_l_t___s_t_o_r_a_g_e___c_o_n_s_t_r_u_c_t_o_r_(_) │ │ │ │ │ * _a_n_n_o_u_n_c_e___f_l_a_g_s___t │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ************ ddhhtt__ssttoorraaggee__ccoouunntteerrss ************ │ │ │ │ │ Declared in "_l_i_b_t_o_r_r_e_n_t_/_k_a_d_e_m_l_i_a_/_d_h_t___s_t_o_r_a_g_e_._h_p_p" │ │ │ │ │ This structure hold the relevant _c_o_u_n_t_e_r_s for the storage │ │ │ │ │ struct dht_storage_counters │ │ │ │ │ { │ │ │ │ │ @@ -210,36 +210,36 @@ │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ nodes │ │ │ │ │ the bootstrap nodes saved from the buckets node │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ nodes6 │ │ │ │ │ the bootstrap nodes saved from the IPv6 buckets node │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ -************ ddhhtt__ddeeffaauulltt__ssttoorraaggee__ccoonnssttrruuccttoorr(()) ************ │ │ │ │ │ -Declared in "_l_i_b_t_o_r_r_e_n_t_/_k_a_d_e_m_l_i_a_/_d_h_t___s_t_o_r_a_g_e_._h_p_p" │ │ │ │ │ -std::unique_ptr ddhhtt__ddeeffaauulltt__ssttoorraaggee__ccoonnssttrruuccttoorr ( │ │ │ │ │ - settings_interface const& settings); │ │ │ │ │ -constructor for the default DHT storage. The DHT storage is responsible for │ │ │ │ │ -maintaining peers and mutable and immutable items announced and stored/put to │ │ │ │ │ -the DHT node. │ │ │ │ │ -[_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ************ ssiiggnn__mmuuttaabbllee__iitteemm(()) ************ │ │ │ │ │ Declared in "_l_i_b_t_o_r_r_e_n_t_/_k_a_d_e_m_l_i_a_/_i_t_e_m_._h_p_p" │ │ │ │ │ signature ssiiggnn__mmuuttaabbllee__iitteemm ( │ │ │ │ │ span v │ │ │ │ │ , span salt │ │ │ │ │ , sequence_number seq │ │ │ │ │ , public_key const& pk │ │ │ │ │ , secret_key const& sk); │ │ │ │ │ given a byte range v and an optional byte range salt, a sequence number, public │ │ │ │ │ key pk (must be 32 bytes) and a secret key sk (must be 64 bytes), this function │ │ │ │ │ produces a signature which is written into a 64 byte buffer pointed to by sig. │ │ │ │ │ The caller is responsible for allocating the destination buffer that's passed │ │ │ │ │ in as the sig argument. Typically it would be allocated on the stack. │ │ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ +************ ddhhtt__ddeeffaauulltt__ssttoorraaggee__ccoonnssttrruuccttoorr(()) ************ │ │ │ │ │ +Declared in "_l_i_b_t_o_r_r_e_n_t_/_k_a_d_e_m_l_i_a_/_d_h_t___s_t_o_r_a_g_e_._h_p_p" │ │ │ │ │ +std::unique_ptr ddhhtt__ddeeffaauulltt__ssttoorraaggee__ccoonnssttrruuccttoorr ( │ │ │ │ │ + settings_interface const& settings); │ │ │ │ │ +constructor for the default DHT storage. The DHT storage is responsible for │ │ │ │ │ +maintaining peers and mutable and immutable items announced and stored/put to │ │ │ │ │ +the DHT node. │ │ │ │ │ +[_r_e_p_o_r_t_ _i_s_s_u_e] │ │ │ │ │ ************ aannnnoouunnccee__ffllaaggss__tt ************ │ │ │ │ │ Declared in "_l_i_b_t_o_r_r_e_n_t_/_k_a_d_e_m_l_i_a_/_a_n_n_o_u_n_c_e___f_l_a_g_s_._h_p_p" │ │ │ │ │ seed │ │ │ │ │ announce to DHT as a seed │ │ │ │ │ implied_port │ │ │ │ │ announce to DHT with the implied-port flag set. This tells the network to │ │ │ │ │ use your source UDP port as your listen port, rather than the one │ │ │ ├── ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-Error_Codes.html │ │ │ │ @@ -33,44 +33,44 @@ │ │ │ │

    Table of contents

    │ │ │ │ │ │ │ │
    │ │ │ │ [report issue]
    │ │ │ │

    storage_error

    │ │ │ │

    Declared in "libtorrent/error_code.hpp"

    │ │ │ │

    used by storage to return errors │ │ │ │ also includes which underlying file the │ │ │ │ error happened on

    │ │ │ │
    │ │ │ │  struct storage_error
    │ │ │ │  {
    │ │ │ │     explicit operator bool () const;
    │ │ │ │ -   void file (file_index_t f);
    │ │ │ │     file_index_t file () const;
    │ │ │ │ +   void file (file_index_t f);
    │ │ │ │  
    │ │ │ │     error_code ec;
    │ │ │ │     operation_t operation;
    │ │ │ │  };
    │ │ │ │  
    │ │ │ │ [report issue]
    │ │ │ │

    bool()

    │ │ │ │ @@ -79,54 +79,31 @@ │ │ │ │
    │ │ │ │

    explicitly converts to true if this object represents an error, and │ │ │ │ false if it does not.

    │ │ │ │ [report issue] │ │ │ │
    │ │ │ │

    file()

    │ │ │ │
    │ │ │ │ -void file (file_index_t f);
    │ │ │ │  file_index_t file () const;
    │ │ │ │ +void file (file_index_t f);
    │ │ │ │  
    │ │ │ │

    set and query the index (in the torrent) of the file this error │ │ │ │ occurred on. This may also have special values defined in │ │ │ │ torrent_status.

    │ │ │ │ [report issue]
    │ │ │ │
    ec
    │ │ │ │
    the error that occurred
    │ │ │ │
    │ │ │ │ [report issue]
    │ │ │ │
    operation
    │ │ │ │
    A code from operation_t enum, indicating what │ │ │ │ kind of operation failed.
    │ │ │ │
    │ │ │ │ -[report issue]
    │ │ │ │ - │ │ │ │ -
    │ │ │ │ -

    i2p_category()

    │ │ │ │ -

    Declared in "libtorrent/i2p_stream.hpp"

    │ │ │ │ -
    │ │ │ │ -boost::system::error_category& i2p_category ();
    │ │ │ │ -
    │ │ │ │ -

    returns the error category for I2P errors

    │ │ │ │ -[report issue]
    │ │ │ │ -
    │ │ │ │ -

    bdecode_category()

    │ │ │ │ -

    Declared in "libtorrent/bdecode.hpp"

    │ │ │ │ -
    │ │ │ │ -boost::system::error_category& bdecode_category ();
    │ │ │ │ -
    │ │ │ │ -[report issue]
    │ │ │ │ -
    │ │ │ │ -

    socks_category()

    │ │ │ │ -

    Declared in "libtorrent/socks5_stream.hpp"

    │ │ │ │ -
    │ │ │ │ -boost::system::error_category& socks_category ();
    │ │ │ │ -
    │ │ │ │ -

    returns the error_category for SOCKS5 errors

    │ │ │ │ [report issue]
    │ │ │ │ + │ │ │ │
    │ │ │ │

    libtorrent_category()

    │ │ │ │

    Declared in "libtorrent/error_code.hpp"

    │ │ │ │
    │ │ │ │  boost::system::error_category& libtorrent_category ();
    │ │ │ │  
    │ │ │ │

    return the instance of the libtorrent_error_category which │ │ │ │ @@ -135,216 +112,62 @@ │ │ │ │

    │ │ │ │

    http_category()

    │ │ │ │

    Declared in "libtorrent/error_code.hpp"

    │ │ │ │
    │ │ │ │  boost::system::error_category& http_category ();
    │ │ │ │  
    │ │ │ │

    returns the error_category for HTTP errors

    │ │ │ │ +[report issue]
    │ │ │ │ +
    │ │ │ │ +

    pcp_category()

    │ │ │ │ +

    Declared in "libtorrent/natpmp.hpp"

    │ │ │ │ +
    │ │ │ │ +boost::system::error_category& pcp_category ();
    │ │ │ │ +
    │ │ │ │ [report issue]
    │ │ │ │
    │ │ │ │

    upnp_category()

    │ │ │ │

    Declared in "libtorrent/upnp.hpp"

    │ │ │ │
    │ │ │ │  boost::system::error_category& upnp_category ();
    │ │ │ │  
    │ │ │ │

    the boost.system error category for UPnP errors

    │ │ │ │ -[report issue]
    │ │ │ │ -
    │ │ │ │ -

    pcp_category()

    │ │ │ │ -

    Declared in "libtorrent/natpmp.hpp"

    │ │ │ │ -
    │ │ │ │ -boost::system::error_category& pcp_category ();
    │ │ │ │ -
    │ │ │ │ [report issue]
    │ │ │ │
    │ │ │ │

    gzip_category()

    │ │ │ │

    Declared in "libtorrent/gzip.hpp"

    │ │ │ │
    │ │ │ │  boost::system::error_category& gzip_category ();
    │ │ │ │  
    │ │ │ │

    get the error_category for zip errors

    │ │ │ │ -[report issue]
    │ │ │ │ -
    │ │ │ │ -

    enum i2p_error_code

    │ │ │ │ +[report issue]
    │ │ │ │ +
    │ │ │ │ +

    socks_category()

    │ │ │ │ +

    Declared in "libtorrent/socks5_stream.hpp"

    │ │ │ │ +
    │ │ │ │ +boost::system::error_category& socks_category ();
    │ │ │ │ +
    │ │ │ │ +

    returns the error_category for SOCKS5 errors

    │ │ │ │ +[report issue]
    │ │ │ │ +
    │ │ │ │ +

    i2p_category()

    │ │ │ │

    Declared in "libtorrent/i2p_stream.hpp"

    │ │ │ │ - │ │ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ -
    namevaluedescription
    no_error0 
    parse_failed1 
    cant_reach_peer2 
    i2p_error3 
    invalid_key4 
    invalid_id5 
    timeout6 
    key_not_found7 
    duplicated_id8 
    num_errors9 
    │ │ │ │ -[report issue]
    │ │ │ │ -
    │ │ │ │ -

    enum error_code_enum

    │ │ │ │ +
    │ │ │ │ +boost::system::error_category& i2p_category ();
    │ │ │ │ +
    │ │ │ │ +

    returns the error category for I2P errors

    │ │ │ │ +[report issue]
    │ │ │ │ +
    │ │ │ │ +

    bdecode_category()

    │ │ │ │

    Declared in "libtorrent/bdecode.hpp"

    │ │ │ │ - │ │ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ -
    namevaluedescription
    no_error0Not an error
    expected_digit1expected digit in bencoded string
    expected_colon2expected colon in bencoded string
    unexpected_eof3unexpected end of file in bencoded string
    expected_value4expected value (list, dict, int or string) in bencoded string
    depth_exceeded5bencoded recursion depth limit exceeded
    limit_exceeded6bencoded item count limit exceeded
    overflow7integer overflow
    error_code_max8the number of error codes
    │ │ │ │ -[report issue]
    │ │ │ │ -
    │ │ │ │ -

    enum socks_error_code

    │ │ │ │ -

    Declared in "libtorrent/socks5_stream.hpp"

    │ │ │ │ - │ │ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ -
    namevaluedescription
    no_error0 
    unsupported_version1 
    unsupported_authentication_method2 
    unsupported_authentication_version3 
    authentication_error4 
    username_required5 
    general_failure6 
    command_not_supported7 
    no_identd8 
    identd_error9 
    num_errors10 
    │ │ │ │ +
    │ │ │ │ +boost::system::error_category& bdecode_category ();
    │ │ │ │ +
    │ │ │ │ [report issue]
    │ │ │ │ -
    │ │ │ │ +
    │ │ │ │

    enum error_code_enum

    │ │ │ │

    Declared in "libtorrent/error_code.hpp"

    │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ @@ -1164,83 +987,14 @@ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
    service_unavailable503 
    │ │ │ │ -[report issue]
    │ │ │ │ -
    │ │ │ │ -

    enum error_code_enum

    │ │ │ │ -

    Declared in "libtorrent/upnp.hpp"

    │ │ │ │ - │ │ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ -
    namevaluedescription
    no_error0No error
    invalid_argument402One of the arguments in the request is invalid
    action_failed501The request failed
    value_not_in_array714The specified value does not exist in the array
    source_ip_cannot_be_wildcarded715The source IP address cannot be wild-carded, but │ │ │ │ -must be fully specified
    external_port_cannot_be_wildcarded716The external port cannot be a wildcard, but must │ │ │ │ -be specified
    port_mapping_conflict718The port mapping entry specified conflicts with a │ │ │ │ -mapping assigned previously to another client
    internal_port_must_match_external724Internal and external port value must be the same
    only_permanent_leases_supported725The NAT implementation only supports permanent │ │ │ │ -lease times on port mappings
    remote_host_must_be_wildcard726RemoteHost must be a wildcard and cannot be a │ │ │ │ -specific IP address or DNS name
    external_port_must_be_wildcard727ExternalPort must be a wildcard and cannot be a │ │ │ │ -specific port
    │ │ │ │ [report issue]
    │ │ │ │
    │ │ │ │

    enum pcp_errors

    │ │ │ │

    Declared in "libtorrent/natpmp.hpp"

    │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ @@ -1309,15 +1063,84 @@ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
    pcp_excessive_remote_peers13 
    │ │ │ │ [report issue]
    │ │ │ │ -
    │ │ │ │ +
    │ │ │ │ +

    enum error_code_enum

    │ │ │ │ +

    Declared in "libtorrent/upnp.hpp"

    │ │ │ │ + │ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ +
    namevaluedescription
    no_error0No error
    invalid_argument402One of the arguments in the request is invalid
    action_failed501The request failed
    value_not_in_array714The specified value does not exist in the array
    source_ip_cannot_be_wildcarded715The source IP address cannot be wild-carded, but │ │ │ │ +must be fully specified
    external_port_cannot_be_wildcarded716The external port cannot be a wildcard, but must │ │ │ │ +be specified
    port_mapping_conflict718The port mapping entry specified conflicts with a │ │ │ │ +mapping assigned previously to another client
    internal_port_must_match_external724Internal and external port value must be the same
    only_permanent_leases_supported725The NAT implementation only supports permanent │ │ │ │ +lease times on port mappings
    remote_host_must_be_wildcard726RemoteHost must be a wildcard and cannot be a │ │ │ │ +specific IP address or DNS name
    external_port_must_be_wildcard727ExternalPort must be a wildcard and cannot be a │ │ │ │ +specific port
    │ │ │ │ +[report issue]
    │ │ │ │ +
    │ │ │ │

    enum error_code_enum

    │ │ │ │

    Declared in "libtorrent/gzip.hpp"

    │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ @@ -1396,14 +1219,191 @@ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
    error_code_max16the number of error codes
    │ │ │ │ +[report issue]
    │ │ │ │ +
    │ │ │ │ +

    enum socks_error_code

    │ │ │ │ +

    Declared in "libtorrent/socks5_stream.hpp"

    │ │ │ │ + │ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ +
    namevaluedescription
    no_error0 
    unsupported_version1 
    unsupported_authentication_method2 
    unsupported_authentication_version3 
    authentication_error4 
    username_required5 
    general_failure6 
    command_not_supported7 
    no_identd8 
    identd_error9 
    num_errors10 
    │ │ │ │ +[report issue]
    │ │ │ │ +
    │ │ │ │ +

    enum i2p_error_code

    │ │ │ │ +

    Declared in "libtorrent/i2p_stream.hpp"

    │ │ │ │ + │ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ +
    namevaluedescription
    no_error0 
    parse_failed1 
    cant_reach_peer2 
    i2p_error3 
    invalid_key4 
    invalid_id5 
    timeout6 
    key_not_found7 
    duplicated_id8 
    num_errors9 
    │ │ │ │ +[report issue]
    │ │ │ │ +
    │ │ │ │ +

    enum error_code_enum

    │ │ │ │ +

    Declared in "libtorrent/bdecode.hpp"

    │ │ │ │ + │ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ +
    namevaluedescription
    no_error0Not an error
    expected_digit1expected digit in bencoded string
    expected_colon2expected colon in bencoded string
    unexpected_eof3unexpected end of file in bencoded string
    expected_value4expected value (list, dict, int or string) in bencoded string
    depth_exceeded5bencoded recursion depth limit exceeded
    limit_exceeded6bencoded item count limit exceeded
    overflow7integer overflow
    error_code_max8the number of error codes
    │ │ │ │
    │ │ │ │ │ │ │ │
    │ │ │ │
    │ │ │ │
    │ │ │ │
    │ │ │ │ │ │ │ │ -
    │ │ │ │ -

    on_piece_pass() on_piece_failed()

    │ │ │ │ + │ │ │ │ +[report issue]
    │ │ │ │ +
    │ │ │ │ +

    on_piece_failed() on_piece_pass()

    │ │ │ │
    │ │ │ │ -virtual void on_piece_failed (piece_index_t);
    │ │ │ │  virtual void on_piece_pass (piece_index_t);
    │ │ │ │ +virtual void on_piece_failed (piece_index_t);
    │ │ │ │  
    │ │ │ │

    These hooks are called when a piece passes the hash check or fails the hash │ │ │ │ check, respectively. The index is the piece index that was downloaded. │ │ │ │ It is possible to access the list of peers that participated in sending the │ │ │ │ piece through the torrent and the piece_picker.

    │ │ │ │ [report issue]
    │ │ │ │
    │ │ │ │

    tick()

    │ │ │ │
    │ │ │ │  virtual void tick ();
    │ │ │ │  
    │ │ │ │

    This hook is called approximately once per second. It is a way of making it │ │ │ │ easy for plugins to do timed events, for sending messages or whatever.

    │ │ │ │ - │ │ │ │ -[report issue]
    │ │ │ │ -
    │ │ │ │ -

    on_resume() on_pause()

    │ │ │ │ + │ │ │ │ +[report issue]
    │ │ │ │ +
    │ │ │ │ +

    on_pause() on_resume()

    │ │ │ │
    │ │ │ │ -virtual bool on_pause ();
    │ │ │ │  virtual bool on_resume ();
    │ │ │ │ +virtual bool on_pause ();
    │ │ │ │  
    │ │ │ │

    These hooks are called when the torrent is paused and resumed respectively. │ │ │ │ The return value indicates if the event was handled. A return value of │ │ │ │ true indicates that it was handled, and no other plugin after this one │ │ │ │ will have this hook function called, and the standard handler will also not be │ │ │ │ invoked. So, returning true effectively overrides the standard behavior of │ │ │ │ pause or resume.

    │ │ │ │ @@ -475,51 +475,51 @@ │ │ │ │ { │ │ │ │ virtual string_view type () const; │ │ │ │ virtual void add_handshake (entry&); │ │ │ │ virtual void on_disconnect (error_code const&); │ │ │ │ virtual void on_connected (); │ │ │ │ virtual bool on_handshake (span<char const>); │ │ │ │ virtual bool on_extension_handshake (bdecode_node const&); │ │ │ │ - virtual bool on_allowed_fast (piece_index_t); │ │ │ │ virtual bool on_choke (); │ │ │ │ - virtual bool on_have_none (); │ │ │ │ virtual bool on_bitfield (bitfield const& /*bitfield*/); │ │ │ │ virtual bool on_have_all (); │ │ │ │ virtual bool on_interested (); │ │ │ │ - virtual bool on_not_interested (); │ │ │ │ - virtual bool on_request (peer_request const&); │ │ │ │ - virtual bool on_dont_have (piece_index_t); │ │ │ │ virtual bool on_have (piece_index_t); │ │ │ │ + virtual bool on_have_none (); │ │ │ │ + virtual bool on_dont_have (piece_index_t); │ │ │ │ + virtual bool on_allowed_fast (piece_index_t); │ │ │ │ virtual bool on_unchoke (); │ │ │ │ + virtual bool on_not_interested (); │ │ │ │ + virtual bool on_request (peer_request const&); │ │ │ │ virtual bool on_piece (peer_request const& /*piece*/ │ │ │ │ , span<char const> /*buf*/); │ │ │ │ virtual bool on_reject (peer_request const&); │ │ │ │ - virtual bool on_suggest (piece_index_t); │ │ │ │ virtual bool on_cancel (peer_request const&); │ │ │ │ + virtual bool on_suggest (piece_index_t); │ │ │ │ virtual void sent_cancel (peer_request const&); │ │ │ │ + virtual void sent_choke (); │ │ │ │ + virtual void sent_reject_request (peer_request const&); │ │ │ │ virtual void sent_request (peer_request const&); │ │ │ │ virtual void sent_have_all (); │ │ │ │ - virtual void sent_have_none (); │ │ │ │ virtual void sent_suggest (piece_index_t); │ │ │ │ - virtual void sent_reject_request (peer_request const&); │ │ │ │ virtual void sent_allow_fast (piece_index_t); │ │ │ │ - virtual void sent_choke (); │ │ │ │ + virtual void sent_have_none (); │ │ │ │ + virtual void sent_piece (peer_request const&); │ │ │ │ + virtual void sent_not_interested (); │ │ │ │ virtual void sent_have (piece_index_t); │ │ │ │ virtual void sent_interested (); │ │ │ │ virtual void sent_unchoke (); │ │ │ │ - virtual void sent_piece (peer_request const&); │ │ │ │ - virtual void sent_not_interested (); │ │ │ │ virtual void sent_payload (int /* bytes */); │ │ │ │ virtual bool can_disconnect (error_code const& /*ec*/); │ │ │ │ virtual bool on_extended (int /*length*/, int /*msg*/, │ │ │ │ span<char const> /*body*/); │ │ │ │ virtual bool on_unknown_message (int /*length*/, int /*msg*/, │ │ │ │ span<char const> /*body*/); │ │ │ │ - virtual void on_piece_failed (piece_index_t); │ │ │ │ virtual void on_piece_pass (piece_index_t); │ │ │ │ + virtual void on_piece_failed (piece_index_t); │ │ │ │ virtual void tick (); │ │ │ │ virtual bool write_request (peer_request const&); │ │ │ │ }; │ │ │ │ │ │ │ │ [report issue]
    │ │ │ │

    type()

    │ │ │ │
    │ │ │ │ @@ -569,39 +569,39 @@
    │ │ │ │  virtual bool on_extension_handshake (bdecode_node const&);
    │ │ │ │  
    │ │ │ │

    called when the extension handshake from the other end is received │ │ │ │ if this returns false, it means that this extension isn't │ │ │ │ supported by this peer. It will result in this peer_plugin │ │ │ │ being removed from the peer_connection and destructed. │ │ │ │ this is not called for web seeds

    │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ + │ │ │ │ │ │ │ │ - │ │ │ │ - │ │ │ │ │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ │ │ │ │ - │ │ │ │ │ │ │ │ -[report issue]
    │ │ │ │ -
    │ │ │ │ -

    on_choke() on_interested() on_allowed_fast() on_have() on_unchoke() on_request() on_have_none() on_have_all() on_dont_have() on_not_interested() on_bitfield()

    │ │ │ │ + │ │ │ │ +[report issue]
    │ │ │ │ +
    │ │ │ │ +

    on_dont_have() on_have() on_have_none() on_allowed_fast() on_bitfield() on_unchoke() on_choke() on_have_all() on_not_interested() on_request() on_interested()

    │ │ │ │
    │ │ │ │ -virtual bool on_allowed_fast (piece_index_t);
    │ │ │ │  virtual bool on_choke ();
    │ │ │ │ -virtual bool on_have_none ();
    │ │ │ │  virtual bool on_bitfield (bitfield const& /*bitfield*/);
    │ │ │ │  virtual bool on_have_all ();
    │ │ │ │  virtual bool on_interested ();
    │ │ │ │ -virtual bool on_not_interested ();
    │ │ │ │ -virtual bool on_request (peer_request const&);
    │ │ │ │ -virtual bool on_dont_have (piece_index_t);
    │ │ │ │  virtual bool on_have (piece_index_t);
    │ │ │ │ +virtual bool on_have_none ();
    │ │ │ │ +virtual bool on_dont_have (piece_index_t);
    │ │ │ │ +virtual bool on_allowed_fast (piece_index_t);
    │ │ │ │  virtual bool on_unchoke ();
    │ │ │ │ +virtual bool on_not_interested ();
    │ │ │ │ +virtual bool on_request (peer_request const&);
    │ │ │ │  
    │ │ │ │

    returning true from any of the message handlers │ │ │ │ indicates that the plugin has handled the message. │ │ │ │ it will break the plugin chain traversing and not let │ │ │ │ anyone else handle the message, including the default │ │ │ │ handler.

    │ │ │ │ [report issue]
    │ │ │ │ @@ -613,27 +613,27 @@ │ │ │ │ │ │ │ │

    This function is called when the peer connection is receiving │ │ │ │ a piece. buf points (non-owning pointer) to the data in an │ │ │ │ internal immutable disk buffer. The length of the data is specified │ │ │ │ in the length member of the piece parameter. │ │ │ │ returns true to indicate that the piece is handled and the │ │ │ │ rest of the logic should be ignored.

    │ │ │ │ - │ │ │ │ - │ │ │ │ - │ │ │ │ │ │ │ │ -[report issue]
    │ │ │ │ -
    │ │ │ │ -

    sent_piece() sent_not_interested() sent_unchoke() sent_have() sent_interested()

    │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ +[report issue]
    │ │ │ │ +
    │ │ │ │ +

    sent_have() sent_unchoke() sent_not_interested() sent_interested() sent_piece()

    │ │ │ │
    │ │ │ │ +virtual void sent_piece (peer_request const&);
    │ │ │ │ +virtual void sent_not_interested ();
    │ │ │ │  virtual void sent_have (piece_index_t);
    │ │ │ │  virtual void sent_interested ();
    │ │ │ │  virtual void sent_unchoke ();
    │ │ │ │ -virtual void sent_piece (peer_request const&);
    │ │ │ │ -virtual void sent_not_interested ();
    │ │ │ │  
    │ │ │ │

    called after a choke message has been sent to the peer

    │ │ │ │ [report issue]
    │ │ │ │
    │ │ │ │

    sent_payload()

    │ │ │ │
    │ │ │ │  virtual void sent_payload (int /* bytes */);
    │ │ │ │ @@ -669,21 +669,21 @@
    │ │ │ │  
    │ │ │ │

    on_unknown_message()

    │ │ │ │
    │ │ │ │  virtual bool on_unknown_message (int /*length*/, int /*msg*/,
    │ │ │ │        span<char const> /*body*/);
    │ │ │ │  
    │ │ │ │

    this is not called for web seeds

    │ │ │ │ - │ │ │ │ -[report issue]
    │ │ │ │ -
    │ │ │ │ -

    on_piece_pass() on_piece_failed()

    │ │ │ │ + │ │ │ │ +[report issue]
    │ │ │ │ +
    │ │ │ │ +

    on_piece_failed() on_piece_pass()

    │ │ │ │
    │ │ │ │ -virtual void on_piece_failed (piece_index_t);
    │ │ │ │  virtual void on_piece_pass (piece_index_t);
    │ │ │ │ +virtual void on_piece_failed (piece_index_t);
    │ │ │ │  
    │ │ │ │

    called when a piece that this peer participated in either │ │ │ │ fails or passes the hash_check

    │ │ │ │ [report issue]
    │ │ │ │
    │ │ │ │

    tick()

    │ │ │ │
    │ │ │ │ @@ -736,86 +736,72 @@
    │ │ │ │  connection object, to be used by plugins. This is a low level interface that
    │ │ │ │  may not be stable across libtorrent versions

    │ │ │ │
    │ │ │ │  struct peer_connection_handle
    │ │ │ │  {
    │ │ │ │     explicit peer_connection_handle (std::weak_ptr<peer_connection> impl);
    │ │ │ │     connection_type type () const;
    │ │ │ │ -   peer_plugin const* find_plugin (string_view type) const;
    │ │ │ │     void add_extension (std::shared_ptr<peer_plugin>);
    │ │ │ │ +   peer_plugin const* find_plugin (string_view type) const;
    │ │ │ │     bool is_seed () const;
    │ │ │ │     bool upload_only () const;
    │ │ │ │     peer_id const& pid () const;
    │ │ │ │     bool has_piece (piece_index_t i) const;
    │ │ │ │ -   bool is_interesting () const;
    │ │ │ │     bool is_choked () const;
    │ │ │ │ +   bool is_interesting () const;
    │ │ │ │     bool is_peer_interested () const;
    │ │ │ │     bool has_peer_choked () const;
    │ │ │ │ -   void maybe_unchoke_this_peer ();
    │ │ │ │     void choke_this_peer ();
    │ │ │ │ +   void maybe_unchoke_this_peer ();
    │ │ │ │     void get_peer_info (peer_info& p) const;
    │ │ │ │     torrent_handle associated_torrent () const;
    │ │ │ │ -   tcp::endpoint const& remote () const;
    │ │ │ │     tcp::endpoint local_endpoint () const;
    │ │ │ │ +   tcp::endpoint const& remote () const;
    │ │ │ │ +   bool is_disconnecting () const;
    │ │ │ │     bool is_outgoing () const;
    │ │ │ │     bool is_connecting () const;
    │ │ │ │     void disconnect (error_code const& ec, operation_t op
    │ │ │ │        , disconnect_severity_t = peer_connection_interface::normal);
    │ │ │ │ -   bool is_disconnecting () const;
    │ │ │ │     bool ignore_unchoke_slots () const;
    │ │ │ │     bool on_local_network () const;
    │ │ │ │     bool failed () const;
    │ │ │ │ -   bool should_log (peer_log_alert::direction_t direction) const;
    │ │ │ │     void peer_log (peer_log_alert::direction_t direction
    │ │ │ │        , char const* event, char const* fmt = "", ...) const TORRENT_FORMAT(4,5);
    │ │ │ │ +   bool should_log (peer_log_alert::direction_t direction) const;
    │ │ │ │     bool can_disconnect (error_code const& ec) const;
    │ │ │ │     bool has_metadata () const;
    │ │ │ │     bool in_handshake () const;
    │ │ │ │     void send_buffer (char const* begin, int size);
    │ │ │ │ -   std::time_t last_seen_complete () const;
    │ │ │ │     time_point time_of_last_unchoke () const;
    │ │ │ │ -   bool operator< (peer_connection_handle const& o) const;
    │ │ │ │ -   bool operator== (peer_connection_handle const& o) const;
    │ │ │ │ +   std::time_t last_seen_complete () const;
    │ │ │ │     bool operator!= (peer_connection_handle const& o) const;
    │ │ │ │ +   bool operator== (peer_connection_handle const& o) const;
    │ │ │ │ +   bool operator< (peer_connection_handle const& o) const;
    │ │ │ │     std::shared_ptr<peer_connection> native_handle () const;
    │ │ │ │  };
    │ │ │ │  
    │ │ │ │ [report issue]
    │ │ │ │
    │ │ │ │

    bt_peer_connection_handle

    │ │ │ │

    Declared in "libtorrent/peer_connection_handle.hpp"

    │ │ │ │

    The bt_peer_connection_handle provides a handle to the internal bittorrent │ │ │ │ peer connection object to plugins. It's low level and may not be a stable API │ │ │ │ across libtorrent versions.

    │ │ │ │
    │ │ │ │  struct bt_peer_connection_handle : peer_connection_handle
    │ │ │ │  {
    │ │ │ │     explicit bt_peer_connection_handle (peer_connection_handle pc);
    │ │ │ │ -   bool packet_finished () const;
    │ │ │ │     bool support_extensions () const;
    │ │ │ │ +   bool packet_finished () const;
    │ │ │ │     bool supports_encryption () const;
    │ │ │ │     void switch_send_crypto (std::shared_ptr<crypto_plugin> crypto);
    │ │ │ │     void switch_recv_crypto (std::shared_ptr<crypto_plugin> crypto);
    │ │ │ │     std::shared_ptr<bt_peer_connection> native_handle () const;
    │ │ │ │  };
    │ │ │ │  
    │ │ │ │ -[report issue]
    │ │ │ │ -
    │ │ │ │ -

    create_ut_pex_plugin()

    │ │ │ │ -

    Declared in "libtorrent/extensions/ut_pex.hpp"

    │ │ │ │ -
    │ │ │ │ -std::shared_ptr<torrent_plugin> create_ut_pex_plugin (torrent_handle const&, client_data_t);
    │ │ │ │ -
    │ │ │ │ -

    constructor function for the ut_pex extension. The ut_pex │ │ │ │ -extension allows peers to gossip about their connections, allowing │ │ │ │ -the swarm stay well connected and peers aware of more peers in the │ │ │ │ -swarm. This extension is enabled by default unless explicitly disabled in │ │ │ │ -the session constructor.

    │ │ │ │ -

    This can either be passed in the add_torrent_params::extensions field, or │ │ │ │ -via torrent_handle::add_extension().

    │ │ │ │ [report issue]
    │ │ │ │
    │ │ │ │

    create_ut_metadata_plugin()

    │ │ │ │

    Declared in "libtorrent/extensions/ut_metadata.hpp"

    │ │ │ │
    │ │ │ │  std::shared_ptr<torrent_plugin> create_ut_metadata_plugin (torrent_handle const&, client_data_t);
    │ │ │ │  
    │ │ │ │ @@ -836,14 +822,28 @@ │ │ │ │
    │ │ │ │

    constructor function for the smart ban extension. The extension keeps │ │ │ │ track of the data peers have sent us for failing pieces and once the │ │ │ │ piece completes and passes the hash check bans the peers that turned │ │ │ │ out to have sent corrupt data. │ │ │ │ This function can either be passed in the add_torrent_params::extensions │ │ │ │ field, or via torrent_handle::add_extension().

    │ │ │ │ +[report issue]
    │ │ │ │ +
    │ │ │ │ +

    create_ut_pex_plugin()

    │ │ │ │ +

    Declared in "libtorrent/extensions/ut_pex.hpp"

    │ │ │ │ +
    │ │ │ │ +std::shared_ptr<torrent_plugin> create_ut_pex_plugin (torrent_handle const&, client_data_t);
    │ │ │ │ +
    │ │ │ │ +

    constructor function for the ut_pex extension. The ut_pex │ │ │ │ +extension allows peers to gossip about their connections, allowing │ │ │ │ +the swarm stay well connected and peers aware of more peers in the │ │ │ │ +swarm. This extension is enabled by default unless explicitly disabled in │ │ │ │ +the session constructor.

    │ │ │ │ +

    This can either be passed in the add_torrent_params::extensions field, or │ │ │ │ +via torrent_handle::add_extension().

    │ │ │ │
    │ │ │ │ │ │ │ │
    │ │ │ │
    │ │ │ │
    │ │ │ │
    │ │ │ │ │ │ │ │
    │ │ │ │
    │ │ │ │ relevance 0../src/add_torrent_params.cpp:84it would be nice if this was nothrow default constructible static_assert(std::is_nothrow_default_constructible::value , "should be nothrow default constructible");

    it would be nice if this was nothrow default constructible │ │ │ │ static_assert(std::is_nothrow_default_constructible::value │ │ │ │ , "should be nothrow default constructible");

    ../src/add_torrent_params.cpp:84

    			DECL_FLAG(pinned);
    │ │ │ │  			DECL_FLAG(stop_when_ready);
    │ │ │ │  			DECL_FLAG(override_trackers);
    │ │ │ │  			DECL_FLAG(override_web_seeds);
    │ │ │ │  			DECL_FLAG(need_save_resume);
    │ │ │ │  			DECL_FLAG(override_resume_data);
    │ │ │ │ @@ -7923,246 +6758,47 @@
    │ │ │ │  	{
    │ │ │ │  		return !atp.have_pieces.empty()
    │ │ │ │  			|| (atp.flags & torrent_flags::seed_mode);
    │ │ │ │  	}
    │ │ │ │  }
    │ │ │ │  
    │ │ │ │  }
    │ │ │ │ -
    relevance 0../src/load_torrent.cpp:121move the loading logic from torrent_info constructor into here

    move the loading logic from torrent_info constructor into here

    ../src/load_torrent.cpp:121

    				mask.resize(std::size_t(full_size), false);
    │ │ │ │ -				for (int i = merkle_first_leaf(piece_layer_size)
    │ │ │ │ -					, end = i + num_pieces; i < end; ++i)
    │ │ │ │ -				{
    │ │ │ │ -					mask[std::size_t(i)] = true;
    │ │ │ │ -				}
    │ │ │ │ -			}
    │ │ │ │ -			ti->free_piece_layers();
    │ │ │ │ -		}
    │ │ │ │ -		atp.info_hashes = atp.ti->info_hashes();
    │ │ │ │ -	}
    │ │ │ │ -}
    │ │ │ │ -
    │ │ │ │ -	add_torrent_params load_torrent_file(std::string const& filename)
    │ │ │ │ -	{ return load_torrent_file(filename, load_torrent_limits{}); }
    │ │ │ │ -	add_torrent_params load_torrent_buffer(span<char const> buffer)
    │ │ │ │ -	{ return load_torrent_buffer(buffer, load_torrent_limits{}); }
    │ │ │ │ -	add_torrent_params load_torrent_parsed(bdecode_node const& torrent_file)
    │ │ │ │ -	{ return load_torrent_parsed(torrent_file, load_torrent_limits{}); }
    │ │ │ │ -
    │ │ │ │ -
    add_torrent_params load_torrent_file(std::string const& filename, load_torrent_limits const& cfg) │ │ │ │ -
    { │ │ │ │ - add_torrent_params ret; │ │ │ │ - ret.ti = std::make_shared<torrent_info>(filename, cfg); │ │ │ │ - update_atp(ret); │ │ │ │ - return ret; │ │ │ │ - } │ │ │ │ - │ │ │ │ - add_torrent_params load_torrent_buffer(span<char const> buffer, load_torrent_limits const& cfg) │ │ │ │ - { │ │ │ │ - add_torrent_params ret; │ │ │ │ - ret.ti = std::make_shared<torrent_info>(buffer, cfg, from_span); │ │ │ │ - update_atp(ret); │ │ │ │ - return ret; │ │ │ │ - } │ │ │ │ - │ │ │ │ - add_torrent_params load_torrent_parsed(bdecode_node const& torrent_file, load_torrent_limits const& cfg) │ │ │ │ - { │ │ │ │ - add_torrent_params ret; │ │ │ │ - ret.ti = std::make_shared<torrent_info>(torrent_file, cfg); │ │ │ │ - update_atp(ret); │ │ │ │ - return ret; │ │ │ │ - } │ │ │ │ - │ │ │ │ -} │ │ │ │ - │ │ │ │ -
    relevance 0../src/web_connection_base.cpp:72introduce a web-seed default class which has a low download priority

    introduce a web-seed default class which has a low download priority

    ../src/web_connection_base.cpp:72

    		: peer_connection(pack)
    │ │ │ │ -		, m_first_request(true)
    │ │ │ │ -		, m_ssl(false)
    │ │ │ │ -		, m_external_auth(web.auth)
    │ │ │ │ -		, m_extra_headers(web.extra_headers)
    │ │ │ │ -		, m_parser(http_parser::dont_parse_chunks)
    │ │ │ │ -		, m_body_start(0)
    │ │ │ │ +
    relevance 0../src/session.cpp:540In C++17. use if constexpr instead

    In C++17. use if constexpr instead

    ../src/session.cpp:540

    	{}
    │ │ │ │ +	session_proxy::session_proxy(session_proxy const&) = default;
    │ │ │ │ +	session_proxy& session_proxy::operator=(session_proxy const&) & = default;
    │ │ │ │ +	session_proxy::session_proxy(session_proxy&&) noexcept = default;
    │ │ │ │ +	session_proxy& session_proxy::operator=(session_proxy&&) & noexcept = default;
    │ │ │ │ +	session_proxy::~session_proxy()
    │ │ │ │  	{
    │ │ │ │ -		TORRENT_ASSERT(&web.peer_info == pack.peerinfo);
    │ │ │ │ -		// when going through a proxy, we don't necessarily have an endpoint here,
    │ │ │ │ -		// since the proxy might be resolving the hostname, not us
    │ │ │ │ -		TORRENT_ASSERT(web.endpoints.empty() || web.endpoints.front() == pack.endp);
    │ │ │ │ -
    │ │ │ │ -		INVARIANT_CHECK;
    │ │ │ │ -
    │ │ │ │ -		TORRENT_ASSERT(is_outgoing());
    │ │ │ │ -
    │ │ │ │ -		TORRENT_ASSERT(!m_torrent.lock()->is_upload_only());
    │ │ │ │ -
    │ │ │ │ -		// we only want left-over bandwidth
    │ │ │ │ -
    │ │ │ │ -
    std::string protocol; │ │ │ │ - error_code ec; │ │ │ │ - std::tie(protocol, m_basic_auth, m_host, m_port, m_path) │ │ │ │ - = parse_url_components(web.url, ec); │ │ │ │ - TORRENT_ASSERT(!ec); │ │ │ │ - │ │ │ │ - if (m_port == -1 && protocol == "http") │ │ │ │ - m_port = 80; │ │ │ │ - │ │ │ │ -#if TORRENT_USE_SSL │ │ │ │ - if (protocol == "https") │ │ │ │ + if (m_thread && m_thread.use_count() == 1) │ │ │ │ { │ │ │ │ - m_ssl = true; │ │ │ │ - if (m_port == -1) m_port = 443; │ │ │ │ - } │ │ │ │ +#if defined TORRENT_ASIO_DEBUGGING │ │ │ │ + wait_for_asio_handlers(); │ │ │ │ #endif │ │ │ │ - │ │ │ │ - if (!m_basic_auth.empty()) │ │ │ │ - m_basic_auth = base64encode(m_basic_auth); │ │ │ │ - │ │ │ │ - m_server_string = m_host; │ │ │ │ - aux::verify_encoding(m_server_string); │ │ │ │ + m_thread->join(); │ │ │ │ + } │ │ │ │ } │ │ │ │ │ │ │ │ - int web_connection_base::timeout() const │ │ │ │ + TORRENT_EXPORT std::unique_ptr<disk_interface> default_disk_io_constructor( │ │ │ │ + io_context& ios, settings_interface const& sett, counters& cnt) │ │ │ │ { │ │ │ │ - // since this is a web seed, change the timeout │ │ │ │ - // according to the settings. │ │ │ │ - return m_settings.get_int(settings_pack::urlseed_timeout); │ │ │ │ - } │ │ │ │ -
    relevance 0../src/pe_crypto.cpp:60it would be nice to get the literal working

    it would be nice to get the literal working

    ../src/pe_crypto.cpp:60

    #include <algorithm>
    │ │ │ │ -#include <random>
    │ │ │ │ -
    │ │ │ │ -#include "libtorrent/aux_/disable_warnings_push.hpp"
    │ │ │ │ -
    │ │ │ │ -#include <boost/multiprecision/integer.hpp>
    │ │ │ │ -#include <boost/multiprecision/cpp_int.hpp>
    │ │ │ │ -
    │ │ │ │ +#if TORRENT_HAVE_MMAP || TORRENT_HAVE_MAP_VIEW_OF_FILE
    │ │ │ │ +
    #include "libtorrent/aux_/disable_deprecation_warnings_push.hpp" │ │ │ │ +
    if (sizeof(void*) == 8) │ │ │ │ + return mmap_disk_io_constructor(ios, sett, cnt); │ │ │ │ + else │ │ │ │ + return posix_disk_io_constructor(ios, sett, cnt); │ │ │ │ #include "libtorrent/aux_/disable_warnings_pop.hpp" │ │ │ │ - │ │ │ │ -#include "libtorrent/random.hpp" │ │ │ │ -#include "libtorrent/aux_/alloca.hpp" │ │ │ │ -#include "libtorrent/pe_crypto.hpp" │ │ │ │ -#include "libtorrent/hasher.hpp" │ │ │ │ - │ │ │ │ -namespace libtorrent { │ │ │ │ - │ │ │ │ - namespace mp = boost::multiprecision; │ │ │ │ - │ │ │ │ - namespace { │ │ │ │ -
    key_t const dh_prime │ │ │ │ -
    ("0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63A36210000000000090563"); │ │ │ │ - } │ │ │ │ - │ │ │ │ - std::array<char, 96> export_key(key_t const& k) │ │ │ │ - { │ │ │ │ - std::array<char, 96> ret; │ │ │ │ - auto* begin = reinterpret_cast<std::uint8_t*>(ret.data()); │ │ │ │ - std::uint8_t* end = mp::export_bits(k, begin, 8); │ │ │ │ - │ │ │ │ -
    relevance 0../src/pe_crypto.cpp:71it would be nice to be able to export to a fixed width field, so we wouldn't have to shift it later

    it would be nice to be able to export to a fixed width field, so │ │ │ │ -we wouldn't have to shift it later

    ../src/pe_crypto.cpp:71

    #include "libtorrent/random.hpp"
    │ │ │ │ -#include "libtorrent/aux_/alloca.hpp"
    │ │ │ │ -#include "libtorrent/pe_crypto.hpp"
    │ │ │ │ -#include "libtorrent/hasher.hpp"
    │ │ │ │ -
    │ │ │ │ -namespace libtorrent {
    │ │ │ │ -
    │ │ │ │ -	namespace mp = boost::multiprecision;
    │ │ │ │ -
    │ │ │ │ -	namespace {
    │ │ │ │ -		key_t const dh_prime
    │ │ │ │ -			("0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63A36210000000000090563");
    │ │ │ │ -	}
    │ │ │ │ -
    │ │ │ │ -	std::array<char, 96> export_key(key_t const& k)
    │ │ │ │ -	{
    │ │ │ │ -		std::array<char, 96> ret;
    │ │ │ │ -		auto* begin = reinterpret_cast<std::uint8_t*>(ret.data());
    │ │ │ │ -		std::uint8_t* end = mp::export_bits(k, begin, 8);
    │ │ │ │ -
    │ │ │ │ -
    if (end < begin + 96) │ │ │ │ -
    { │ │ │ │ - int const len = int(end - begin); │ │ │ │ -#if defined __GNUC__ && __GNUC__ == 12 │ │ │ │ -#pragma GCC diagnostic push │ │ │ │ -#pragma GCC diagnostic ignored "-Wstringop-overflow" │ │ │ │ -#endif │ │ │ │ - std::memmove(begin + 96 - len, begin, aux::numeric_cast<std::size_t>(len)); │ │ │ │ -#if defined __GNUC__ && __GNUC__ == 12 │ │ │ │ -#pragma GCC diagnostic pop │ │ │ │ +#else │ │ │ │ + return posix_disk_io_constructor(ios, sett, cnt); │ │ │ │ #endif │ │ │ │ - std::memset(begin, 0, aux::numeric_cast<std::size_t>(96 - len)); │ │ │ │ - } │ │ │ │ - return ret; │ │ │ │ } │ │ │ │ │ │ │ │ - void rc4_init(const unsigned char* in, std::size_t len, rc4 *state); │ │ │ │ - std::size_t rc4_encrypt(unsigned char *out, std::size_t outlen, rc4 *state); │ │ │ │ - │ │ │ │ - // Set the prime P and the generator, generate local public key │ │ │ │ - dh_key_exchange::dh_key_exchange() │ │ │ │ - { │ │ │ │ - aux::array<std::uint8_t, 96> random_key; │ │ │ │ - aux::random_bytes({reinterpret_cast<char*>(random_key.data()) │ │ │ │ - , static_cast<std::ptrdiff_t>(random_key.size())}); │ │ │ │ - │ │ │ │ - // create local key (random) │ │ │ │ - mp::import_bits(m_dh_local_secret, random_key.begin(), random_key.end()); │ │ │ │ - │ │ │ │ - // key = (2 ^ secret) % prime │ │ │ │ - m_dh_local_key = mp::powm(key_t(2), m_dh_local_secret, dh_prime); │ │ │ │ -
    relevance 0../src/ut_metadata.cpp:281we really need to increment the refcounter on the torrent while this buffer is still in the peer's send buffer

    we really need to increment the refcounter on the torrent │ │ │ │ -while this buffer is still in the peer's send buffer

    ../src/ut_metadata.cpp:281

    				int const offset = piece * 16 * 1024;
    │ │ │ │ -				metadata = m_tp.metadata().data() + offset;
    │ │ │ │ -				metadata_piece_size = std::min(
    │ │ │ │ -					int(m_tp.metadata().size()) - offset, 16 * 1024);
    │ │ │ │ -				TORRENT_ASSERT(metadata_piece_size > 0);
    │ │ │ │ -				TORRENT_ASSERT(offset >= 0);
    │ │ │ │ -				TORRENT_ASSERT(offset + metadata_piece_size <= m_tp.metadata().size());
    │ │ │ │ -			}
    │ │ │ │ -
    │ │ │ │ -			char msg[200];
    │ │ │ │ -			char* header = msg;
    │ │ │ │ -			char* p = &msg[6];
    │ │ │ │ -			int const len = bencode(p, e);
    │ │ │ │ -			int const total_size = 2 + len + metadata_piece_size;
    │ │ │ │ -			namespace io = aux;
    │ │ │ │ -			io::write_uint32(total_size, header);
    │ │ │ │ -			io::write_uint8(bt_peer_connection::msg_extended, header);
    │ │ │ │ -			io::write_uint8(m_message_index, header);
    │ │ │ │ -
    │ │ │ │ -			m_pc.send_buffer({msg, len + 6});
    │ │ │ │ -
    if (metadata_piece_size) │ │ │ │ -
    { │ │ │ │ - m_pc.append_const_send_buffer( │ │ │ │ - span<char>(const_cast<char*>(metadata), metadata_piece_size), metadata_piece_size); │ │ │ │ - } │ │ │ │ - │ │ │ │ - m_pc.stats_counters().inc_stats_counter(counters::num_outgoing_extended); │ │ │ │ - m_pc.stats_counters().inc_stats_counter(counters::num_outgoing_metadata); │ │ │ │ - } │ │ │ │ - │ │ │ │ - bool on_extended(int const length │ │ │ │ - , int const extended_msg, span<char const> body) override │ │ │ │ - { │ │ │ │ - if (extended_msg != 2) return false; │ │ │ │ - if (m_message_index == 0) return false; │ │ │ │ - │ │ │ │ - if (length > 17 * 1024) │ │ │ │ - { │ │ │ │ -#ifndef TORRENT_DISABLE_LOGGING │ │ │ │ - m_pc.peer_log(peer_log_alert::incoming_message, "UT_METADATA" │ │ │ │ - , "packet too big %d", length); │ │ │ │ -#endif │ │ │ │ - m_pc.disconnect(errors::invalid_metadata_message, operation_t::bittorrent, peer_connection_interface::peer_error); │ │ │ │ - return true; │ │ │ │ - } │ │ │ │ - │ │ │ │ - if (!m_pc.packet_finished()) return true; │ │ │ │ - │ │ │ │ - error_code ec; │ │ │ │ - bdecode_node msg = bdecode(body, ec); │ │ │ │ - if (msg.type() != bdecode_node::dict_t) │ │ │ │ -
    relevance 0../src/enum_net.cpp:144in C++17, use __has_include for this. Other operating systems are likely to require this as well

    in C++17, use __has_include for this. Other operating systems are │ │ │ │ +} │ │ │ │ +relevance 0../src/enum_net.cpp:144in C++17, use __has_include for this. Other operating systems are likely to require this as well

    in C++17, use __has_include for this. Other operating systems are │ │ │ │ likely to require this as well

    ../src/enum_net.cpp:144

    #include <arpa/inet.h>
    │ │ │ │  #include <cstring>
    │ │ │ │  #include <cstdlib>
    │ │ │ │  #include <unistd.h>
    │ │ │ │  #include <sys/types.h>
    │ │ │ │  
    │ │ │ │  #if defined TORRENT_ANDROID && !defined IFA_F_DADFAILED
    │ │ │ │ @@ -8206,15 +6842,15 @@
    │ │ │ │  		~socket_closer() { ::close(m_socket); }
    │ │ │ │  	private:
    │ │ │ │  		int m_socket;
    │ │ │ │  	};
    │ │ │ │  #endif
    │ │ │ │  
    │ │ │ │  #if !defined TORRENT_BUILD_SIMULATOR
    │ │ │ │ -
    relevance 0../src/enum_net.cpp:268if we get here, the caller still assumes the error code is reported via errno

    if we get here, the caller still assumes the error code │ │ │ │ +relevance 0../src/enum_net.cpp:268if we get here, the caller still assumes the error code is reported via errno

    if we get here, the caller still assumes the error code │ │ │ │ is reported via errno

    ../src/enum_net.cpp:268

    		;
    │ │ │ │  	}
    │ │ │ │  #endif
    │ │ │ │  
    │ │ │ │  #if TORRENT_USE_NETLINK
    │ │ │ │  
    │ │ │ │  	int read_nl_sock(int sock, std::uint32_t const seq, std::uint32_t const pid
    │ │ │ │ @@ -8231,15 +6867,15 @@
    │ │ │ │  
    │ │ │ │  			for (; len > 0 && aux::nlmsg_ok(nl_hdr, len); nl_hdr = aux::nlmsg_next(nl_hdr, len))
    │ │ │ │  			{
    │ │ │ │  
    if ((aux::nlmsg_ok(nl_hdr, read_len) == 0) || (nl_hdr->nlmsg_type == NLMSG_ERROR)) │ │ │ │
    return -1; │ │ │ │ // this function doesn't handle multiple requests at the same time │ │ │ │ // so report an error if the message does not have the expected seq and pid │ │ │ │ -
    relevance 0../src/enum_net.cpp:274if we get here, the caller still assumes the error code is reported via errno

    if we get here, the caller still assumes the error code │ │ │ │ +relevance 0../src/enum_net.cpp:274if we get here, the caller still assumes the error code is reported via errno

    if we get here, the caller still assumes the error code │ │ │ │ is reported via errno

    ../src/enum_net.cpp:274

    #if TORRENT_USE_NETLINK
    │ │ │ │  
    │ │ │ │  	int read_nl_sock(int sock, std::uint32_t const seq, std::uint32_t const pid
    │ │ │ │  		, std::function<void(nlmsghdr const*)> on_msg)
    │ │ │ │  	{
    │ │ │ │  		std::array<char, 4096> buf;
    │ │ │ │  		for (;;)
    │ │ │ │ @@ -8283,498 +6919,274 @@
    │ │ │ │  			return -1;
    │ │ │ │  
    │ │ │ │  		// get the socket's port ID so that we can verify it in the response
    │ │ │ │  		sockaddr_nl sock_addr;
    │ │ │ │  		socklen_t sock_addr_len = sizeof(sock_addr);
    │ │ │ │  		if (::getsockname(sock, reinterpret_cast<sockaddr*>(&sock_addr), &sock_addr_len) < 0)
    │ │ │ │  			return -1;
    │ │ │ │ -
    relevance 0../src/torrent.cpp:1941this could be optimized by looking up which files are complete and just look at those

    this could be optimized by looking up which files are │ │ │ │ -complete and just look at those

    ../src/torrent.cpp:1941

    //				TORRENT_ASSERT(picker().have_piece(i));
    │ │ │ │ -				we_have(i);
    │ │ │ │ -			}
    │ │ │ │ -		}
    │ │ │ │ -
    │ │ │ │ -		set_state(torrent_status::checking_resume_data);
    │ │ │ │ -
    │ │ │ │ -		aux::vector<std::string, file_index_t> links;
    │ │ │ │ -#ifndef TORRENT_DISABLE_MUTABLE_TORRENTS
    │ │ │ │ -		if (!m_torrent_file->similar_torrents().empty()
    │ │ │ │ -			|| !m_torrent_file->collections().empty())
    │ │ │ │ -		{
    │ │ │ │ -			resolve_links res(m_torrent_file);
    │ │ │ │ -
    │ │ │ │ -			for (auto const& ih : m_torrent_file->similar_torrents())
    │ │ │ │ -			{
    │ │ │ │ -				std::shared_ptr<torrent> t = m_ses.find_torrent(info_hash_t(ih)).lock();
    │ │ │ │ -				if (!t) continue;
    │ │ │ │ -
    │ │ │ │ -				// Only attempt to reuse files from torrents that are seeding.
    │ │ │ │ -
    if (!t->is_seed()) continue; │ │ │ │ -
    │ │ │ │ - res.match(t->get_torrent_file(), t->save_path()); │ │ │ │ - } │ │ │ │ - for (auto const& c : m_torrent_file->collections()) │ │ │ │ - { │ │ │ │ - std::vector<std::shared_ptr<torrent>> ts = m_ses.find_collection(c); │ │ │ │ +
    relevance 0../src/web_connection_base.cpp:72introduce a web-seed default class which has a low download priority

    introduce a web-seed default class which has a low download priority

    ../src/web_connection_base.cpp:72

    		: peer_connection(pack)
    │ │ │ │ +		, m_first_request(true)
    │ │ │ │ +		, m_ssl(false)
    │ │ │ │ +		, m_external_auth(web.auth)
    │ │ │ │ +		, m_extra_headers(web.extra_headers)
    │ │ │ │ +		, m_parser(http_parser::dont_parse_chunks)
    │ │ │ │ +		, m_body_start(0)
    │ │ │ │ +	{
    │ │ │ │ +		TORRENT_ASSERT(&web.peer_info == pack.peerinfo);
    │ │ │ │ +		// when going through a proxy, we don't necessarily have an endpoint here,
    │ │ │ │ +		// since the proxy might be resolving the hostname, not us
    │ │ │ │ +		TORRENT_ASSERT(web.endpoints.empty() || web.endpoints.front() == pack.endp);
    │ │ │ │  
    │ │ │ │ -				for (auto const& t : ts)
    │ │ │ │ -				{
    │ │ │ │ -					// Only attempt to reuse files from torrents that are seeding.
    │ │ │ │ -
    relevance 0../src/torrent.cpp:1954this could be optimized by looking up which files are complete and just look at those

    this could be optimized by looking up which files are │ │ │ │ -complete and just look at those

    ../src/torrent.cpp:1954

    		{
    │ │ │ │ -			resolve_links res(m_torrent_file);
    │ │ │ │ +		INVARIANT_CHECK;
    │ │ │ │  
    │ │ │ │ -			for (auto const& ih : m_torrent_file->similar_torrents())
    │ │ │ │ -			{
    │ │ │ │ -				std::shared_ptr<torrent> t = m_ses.find_torrent(info_hash_t(ih)).lock();
    │ │ │ │ -				if (!t) continue;
    │ │ │ │ +		TORRENT_ASSERT(is_outgoing());
    │ │ │ │  
    │ │ │ │ -				// Only attempt to reuse files from torrents that are seeding.
    │ │ │ │ -				if (!t->is_seed()) continue;
    │ │ │ │ +		TORRENT_ASSERT(!m_torrent.lock()->is_upload_only());
    │ │ │ │  
    │ │ │ │ -				res.match(t->get_torrent_file(), t->save_path());
    │ │ │ │ -			}
    │ │ │ │ -			for (auto const& c : m_torrent_file->collections())
    │ │ │ │ -			{
    │ │ │ │ -				std::vector<std::shared_ptr<torrent>> ts = m_ses.find_collection(c);
    │ │ │ │ +		// we only want left-over bandwidth
    │ │ │ │ +
    │ │ │ │ +
    std::string protocol; │ │ │ │ + error_code ec; │ │ │ │ + std::tie(protocol, m_basic_auth, m_host, m_port, m_path) │ │ │ │ + = parse_url_components(web.url, ec); │ │ │ │ + TORRENT_ASSERT(!ec); │ │ │ │ │ │ │ │ - for (auto const& t : ts) │ │ │ │ - { │ │ │ │ - // Only attempt to reuse files from torrents that are seeding. │ │ │ │ -
    if (!t->is_seed()) continue; │ │ │ │ -
    │ │ │ │ - res.match(t->get_torrent_file(), t->save_path()); │ │ │ │ - } │ │ │ │ - } │ │ │ │ + if (m_port == -1 && protocol == "http") │ │ │ │ + m_port = 80; │ │ │ │ │ │ │ │ - std::vector<resolve_links::link_t> const& l = res.get_links(); │ │ │ │ - if (!l.empty()) │ │ │ │ - { │ │ │ │ - links.resize(m_torrent_file->files().num_files()); │ │ │ │ - for (auto const& i : l) │ │ │ │ - { │ │ │ │ - if (!i.ti) continue; │ │ │ │ - links[i.file_idx] = combine_path(i.save_path │ │ │ │ - , i.ti->files().file_path(i.file_idx)); │ │ │ │ - } │ │ │ │ - } │ │ │ │ +#if TORRENT_USE_SSL │ │ │ │ + if (protocol == "https") │ │ │ │ + { │ │ │ │ + m_ssl = true; │ │ │ │ + if (m_port == -1) m_port = 443; │ │ │ │ } │ │ │ │ -#endif // TORRENT_DISABLE_MUTABLE_TORRENTS │ │ │ │ - │ │ │ │ -#if TORRENT_USE_ASSERTS │ │ │ │ - TORRENT_ASSERT(m_outstanding_check_files == false); │ │ │ │ - m_outstanding_check_files = true; │ │ │ │ #endif │ │ │ │ │ │ │ │ - if (!m_add_torrent_params || !(m_add_torrent_params->flags & torrent_flags::no_verify_files)) │ │ │ │ - { │ │ │ │ - m_ses.disk_thread().async_check_files( │ │ │ │ - m_storage, m_add_torrent_params ? m_add_torrent_params.get() : nullptr │ │ │ │ - , std::move(links), [self = shared_from_this()](status_t st, storage_error const& error) │ │ │ │ - { self->on_resume_data_checked(st, error); }); │ │ │ │ -
    relevance 0../src/torrent.cpp:2715this pattern is repeated in a few places. Factor this into a function and generalize the concept of a torrent having a dedicated listen port

    this pattern is repeated in a few places. Factor this into │ │ │ │ -a function and generalize the concept of a torrent having a │ │ │ │ -dedicated listen port

    ../src/torrent.cpp:2715

    		// not ready for peers. Except, if we don't have metadata,
    │ │ │ │ -		// we need peers to download from
    │ │ │ │ -		if (!m_files_checked && valid_metadata()) return;
    │ │ │ │ +		if (!m_basic_auth.empty())
    │ │ │ │ +			m_basic_auth = base64encode(m_basic_auth);
    │ │ │ │  
    │ │ │ │ -		if (!m_announce_to_lsd) return;
    │ │ │ │ +		m_server_string = m_host;
    │ │ │ │ +		aux::verify_encoding(m_server_string);
    │ │ │ │ +	}
    │ │ │ │  
    │ │ │ │ -		// private torrents are never announced on LSD
    │ │ │ │ -		if (m_torrent_file->is_valid() && m_torrent_file->priv()) return;
    │ │ │ │ +	int web_connection_base::timeout() const
    │ │ │ │ +	{
    │ │ │ │ +		// since this is a web seed, change the timeout
    │ │ │ │ +		// according to the settings.
    │ │ │ │ +		return m_settings.get_int(settings_pack::urlseed_timeout);
    │ │ │ │ +	}
    │ │ │ │ +
    relevance 0../src/performance_counters.cpp:40move stats_counter_t out of counters

    move stats_counter_t out of counters

    ../src/performance_counters.cpp:40

    relevance 0../src/performance_counters.cpp:41should bittorrent keep-alive messages have a counter too?

    should bittorrent keep-alive messages have a counter too?

    ../src/performance_counters.cpp:41

    relevance 0../src/performance_counters.cpp:42It would be nice if this could be an internal type. default_disk_constructor depends on it now

    It would be nice if this could be an internal type. default_disk_constructor depends on it now

    ../src/performance_counters.cpp:42

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    │ │ │ │ +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    │ │ │ │ +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    │ │ │ │ +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
    │ │ │ │ +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    │ │ │ │ +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    │ │ │ │ +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    │ │ │ │ +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    │ │ │ │ +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    │ │ │ │ +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    │ │ │ │ +POSSIBILITY OF SUCH DAMAGE.
    │ │ │ │  
    │ │ │ │ -#if TORRENT_USE_I2P
    │ │ │ │ -		// i2p torrents are also never announced on LSD
    │ │ │ │ -		// unless we allow mixed swarms
    │ │ │ │ -		if (is_i2p() && !settings().get_bool(settings_pack::allow_i2p_mixed))
    │ │ │ │ -			return;
    │ │ │ │ -#endif
    │ │ │ │ +*/
    │ │ │ │  
    │ │ │ │ -		if (is_paused()) return;
    │ │ │ │ +#include "libtorrent/performance_counters.hpp"
    │ │ │ │ +#include "libtorrent/assert.hpp"
    │ │ │ │ +#include <cstring> // for memset
    │ │ │ │  
    │ │ │ │ -		if (!m_ses.has_lsd()) return;
    │ │ │ │ +namespace libtorrent {
    │ │ │ │  
    │ │ │ │ -
    #ifdef TORRENT_SSL_PEERS │ │ │ │ -
    int port = is_ssl_torrent() ? m_ses.ssl_listen_port() : m_ses.listen_port(); │ │ │ │ +
    counters::counters() TORRENT_COUNTER_NOEXCEPT │ │ │ │ +
    { │ │ │ │ +#ifdef ATOMIC_LLONG_LOCK_FREE │ │ │ │ + for (auto& counter : m_stats_counter) │ │ │ │ + counter.store(0, std::memory_order_relaxed); │ │ │ │ #else │ │ │ │ - int port = m_ses.listen_port(); │ │ │ │ + m_stats_counter.fill(0); │ │ │ │ #endif │ │ │ │ - │ │ │ │ - // announce with the local discovery service │ │ │ │ - m_torrent_file->info_hashes().for_each([&](sha1_hash const& ih, protocol_version) │ │ │ │ - { │ │ │ │ - m_ses.announce_lsd(ih, port); │ │ │ │ - }); │ │ │ │ } │ │ │ │ │ │ │ │ -#ifndef TORRENT_DISABLE_DHT │ │ │ │ - │ │ │ │ - void torrent::dht_announce() │ │ │ │ + counters::counters(counters const& c) TORRENT_COUNTER_NOEXCEPT │ │ │ │ { │ │ │ │ - TORRENT_ASSERT(is_single_thread()); │ │ │ │ - if (!m_ses.dht()) │ │ │ │ - { │ │ │ │ -#ifndef TORRENT_DISABLE_LOGGING │ │ │ │ - debug_log("DHT: no dht initialized"); │ │ │ │ -#endif │ │ │ │ - return; │ │ │ │ - } │ │ │ │ - if (!should_announce_dht()) │ │ │ │ - { │ │ │ │ -#ifndef TORRENT_DISABLE_LOGGING │ │ │ │ - if (should_log()) │ │ │ │ - { │ │ │ │ -#if TORRENT_USE_I2P │ │ │ │ -
    relevance 0../src/torrent.cpp:3870add one peer per IP the hostname resolves to

    add one peer per IP the hostname resolves to

    ../src/torrent.cpp:3870

    	catch (...) { handle_exception(); }
    │ │ │ │ +#ifdef ATOMIC_LLONG_LOCK_FREE
    │ │ │ │ +		for (int i = 0; i < m_stats_counter.end_index(); ++i)
    │ │ │ │ +			m_stats_counter[i].store(
    │ │ │ │ +				c.m_stats_counter[i].load(std::memory_order_relaxed)
    │ │ │ │ +					, std::memory_order_relaxed);
    │ │ │ │ +#else
    │ │ │ │ +		std::lock_guard<std::mutex> l(c.m_mutex);
    │ │ │ │ +		m_stats_counter = c.m_stats_counter;
    │ │ │ │  #endif
    │ │ │ │ +	}
    │ │ │ │  
    │ │ │ │ -	void torrent::on_peer_name_lookup(error_code const& e
    │ │ │ │ -		, std::vector<address> const& host_list, int const port
    │ │ │ │ -		, protocol_version const v) try
    │ │ │ │ +	counters& counters::operator=(counters const& c) & TORRENT_COUNTER_NOEXCEPT
    │ │ │ │  	{
    │ │ │ │ -		TORRENT_ASSERT(is_single_thread());
    │ │ │ │ -
    │ │ │ │ -		INVARIANT_CHECK;
    │ │ │ │ -
    │ │ │ │ -		COMPLETE_ASYNC("torrent::on_peer_name_lookup");
    │ │ │ │ -
    │ │ │ │ -#ifndef TORRENT_DISABLE_LOGGING
    │ │ │ │ -		if (e && should_log())
    │ │ │ │ -			debug_log("peer name lookup error: %s", e.message().c_str());
    │ │ │ │ -#endif
    │ │ │ │ -
    │ │ │ │ -		if (e || m_abort || host_list.empty() || m_ses.is_aborted()) return;
    │ │ │ │ -
    │ │ │ │ -
    tcp::endpoint host(host_list.front(), std::uint16_t(port)); │ │ │ │ -
    │ │ │ │ - if (m_ip_filter && m_ip_filter->access(host.address()) & ip_filter::blocked) │ │ │ │ - { │ │ │ │ -#ifndef TORRENT_DISABLE_LOGGING │ │ │ │ - if (should_log()) │ │ │ │ - { │ │ │ │ - debug_log("blocked ip from tracker: %s", host.address().to_string().c_str()); │ │ │ │ - } │ │ │ │ + if (&c == this) return *this; │ │ │ │ +#ifdef ATOMIC_LLONG_LOCK_FREE │ │ │ │ + for (int i = 0; i < m_stats_counter.end_index(); ++i) │ │ │ │ + m_stats_counter[i].store( │ │ │ │ + c.m_stats_counter[i].load(std::memory_order_relaxed) │ │ │ │ + , std::memory_order_relaxed); │ │ │ │ +
    relevance 0../src/torrent_handle.cpp:589support moving files into this call

    support moving files into this call

    ../src/torrent_handle.cpp:589

    		auto retp = &prio;
    │ │ │ │ +		sync_call(&torrent::piece_priorities, retp);
    │ │ │ │ +		std::vector<int> ret;
    │ │ │ │ +		ret.reserve(prio.size());
    │ │ │ │ +		for (auto p : prio)
    │ │ │ │ +			ret.push_back(int(static_cast<std::uint8_t>(p)));
    │ │ │ │ +		return ret;
    │ │ │ │ +	}
    │ │ │ │  #endif
    │ │ │ │ -			if (m_ses.alerts().should_post<peer_blocked_alert>())
    │ │ │ │ -				m_ses.alerts().emplace_alert<peer_blocked_alert>(get_handle()
    │ │ │ │ -					, host, peer_blocked_alert::ip_filter);
    │ │ │ │ -			return;
    │ │ │ │ -		}
    │ │ │ │ -
    │ │ │ │ -		if (add_peer(host, peer_info::tracker, v == protocol_version::V2 ? pex_lt_v2 : pex_flags_t(0)))
    │ │ │ │ -		{
    │ │ │ │ -			state_updated();
    │ │ │ │  
    │ │ │ │ -#ifndef TORRENT_DISABLE_LOGGING
    │ │ │ │ -			if (should_log())
    │ │ │ │ -			{
    │ │ │ │ -				debug_log("name-lookup add_peer() [ %s ] connect-candidates: %d"
    │ │ │ │ -					, host.address().to_string().c_str()
    │ │ │ │ -					, m_peer_list ? m_peer_list->num_connect_candidates() : -1);
    │ │ │ │ -			}
    │ │ │ │ -#endif
    │ │ │ │ -		}
    │ │ │ │ -		update_want_peers();
    │ │ │ │ +	void torrent_handle::file_priority(file_index_t index, download_priority_t priority) const
    │ │ │ │ +	{
    │ │ │ │ +		async_call(&torrent::set_file_priority, index, priority);
    │ │ │ │  	}
    │ │ │ │ -
    relevance 0../src/torrent.cpp:4562only do this if the piece size > 1 blocks This is a v2 torrent so we can request get block level hashes.

    only do this if the piece size > 1 blocks │ │ │ │ -This is a v2 torrent so we can request get block │ │ │ │ -level hashes.

    ../src/torrent.cpp:4562

    		{
    │ │ │ │ -			std::set<torrent_peer*> ret;
    │ │ │ │ -			if (!blocks.empty() && !downloaders.empty())
    │ │ │ │ -			{
    │ │ │ │ -				for (auto const b : blocks) ret.insert(downloaders[std::size_t(b)]);
    │ │ │ │ -			}
    │ │ │ │ -			else
    │ │ │ │ -			{
    │ │ │ │ -				std::copy(downloaders.begin(), downloaders.end(), std::inserter(ret, ret.begin()));
    │ │ │ │ -			}
    │ │ │ │ -			return ret;
    │ │ │ │ -		}();
    │ │ │ │  
    │ │ │ │ -		// if this piece wasn't downloaded from peers, we just found it on disk.
    │ │ │ │ -		// In that case, we should just consider it as "not-have" and there's no
    │ │ │ │ -		// need to try to get higher fidelity hashes (yet)
    │ │ │ │ -		bool const found_on_disk = peers.size() == 1 && peers.count(nullptr);
    │ │ │ │ +	download_priority_t torrent_handle::file_priority(file_index_t index) const
    │ │ │ │ +	{
    │ │ │ │ +		return sync_call_ret<download_priority_t>(dont_download, &torrent::file_priority, index);
    │ │ │ │ +	}
    │ │ │ │  
    │ │ │ │ -		if (!torrent_file().info_hashes().has_v1() && blocks.empty() && !found_on_disk)
    │ │ │ │ -		{
    │ │ │ │ -
    verify_block_hashes(index); │ │ │ │ -
    } │ │ │ │ +
    void torrent_handle::prioritize_files(std::vector<download_priority_t> const& files) const │ │ │ │ +
    { │ │ │ │ + async_call(&torrent::prioritize_files │ │ │ │ + , static_cast<aux::vector<download_priority_t, file_index_t> const&>(files)); │ │ │ │ + } │ │ │ │ │ │ │ │ - // the below code is penalizing peers that sent use bad data. │ │ │ │ - // increase the total amount of failed bytes │ │ │ │ - if (!found_on_disk) │ │ │ │ - { │ │ │ │ - if (blocks.empty()) │ │ │ │ - add_failed_bytes(m_torrent_file->piece_size(index)); │ │ │ │ - else │ │ │ │ - add_failed_bytes(static_cast<int>(blocks.size()) * default_block_size); │ │ │ │ + std::vector<download_priority_t> torrent_handle::get_file_priorities() const │ │ │ │ + { │ │ │ │ + aux::vector<download_priority_t, file_index_t> ret; │ │ │ │ + auto retp = &ret; │ │ │ │ + sync_call(&torrent::file_priorities, retp); │ │ │ │ + return TORRENT_RVO(ret); │ │ │ │ + } │ │ │ │ │ │ │ │ -#ifndef TORRENT_DISABLE_EXTENSIONS │ │ │ │ - for (auto& ext : m_extensions) │ │ │ │ - { │ │ │ │ - ext->on_piece_failed(index); │ │ │ │ - } │ │ │ │ -#endif │ │ │ │ +#if TORRENT_ABI_VERSION == 1 │ │ │ │ │ │ │ │ - // did we receive this piece from a single peer? │ │ │ │ - // if we know exactly which blocks failed the hash, we can also be certain │ │ │ │ - // that all peers in the list sent us bad data │ │ │ │ - bool const known_bad_peer = (!found_on_disk && peers.size() == 1) || !blocks.empty(); │ │ │ │ +// ============ start deprecation =============== │ │ │ │ │ │ │ │ - penalize_peers(peers, index, known_bad_peer); │ │ │ │ + void torrent_handle::prioritize_files(std::vector<int> const& files) const │ │ │ │ + { │ │ │ │ + aux::vector<download_priority_t, file_index_t> file_prio; │ │ │ │ + file_prio.reserve(files.size()); │ │ │ │ + for (auto const p : files) { │ │ │ │ + file_prio.push_back(download_priority_t(static_cast<std::uint8_t>(p))); │ │ │ │ } │ │ │ │ + async_call(&torrent::prioritize_files, file_prio); │ │ │ │ + } │ │ │ │ │ │ │ │ - // If m_storage isn't set here, it means we're shutting down │ │ │ │ - if (m_storage) │ │ │ │ - { │ │ │ │ - // it doesn't make much sense to fail to hash a piece │ │ │ │ -
    relevance 0../src/torrent.cpp:7501come up with a better way of doing this, instead of an immediately invoked lambda expression.

    come up with a better way of doing this, instead of an │ │ │ │ -immediately invoked lambda expression.

    ../src/torrent.cpp:7501

    					|| peerinfo->confirmed_supports_utp))
    │ │ │ │ -			{
    │ │ │ │ -				sm = m_ses.utp_socket_manager();
    │ │ │ │ -			}
    │ │ │ │ +	std::vector<int> torrent_handle::file_priorities() const
    │ │ │ │ +	{
    │ │ │ │ +		aux::vector<download_priority_t, file_index_t> prio;
    │ │ │ │ +
    relevance 0../src/posix_part_file.cpp:337what do we do if someone is currently reading from the disk from this piece? does it matter? Since we won't actively erase the data from disk, but it may be overwritten soon, it's probably not that big of a deal

    what do we do if someone is currently reading from the disk │ │ │ │ +from this piece? does it matter? Since we won't actively erase the │ │ │ │ +data from disk, but it may be overwritten soon, it's probably not that │ │ │ │ +big of a deal

    ../src/posix_part_file.cpp:337

    │ │ │ │ +			if (ec) return {};
    │ │ │ │  
    │ │ │ │ -			// don't make a TCP connection if it's disabled
    │ │ │ │ -			if (sm == nullptr && !settings().get_bool(settings_pack::enable_outgoing_tcp))
    │ │ │ │ -			{
    │ │ │ │ -#ifndef TORRENT_DISABLE_LOGGING
    │ │ │ │ -				if (should_log())
    │ │ │ │ -				{
    │ │ │ │ -					debug_log("discarding peer \"%s\": TCP connections disabled "
    │ │ │ │ -						"[ supports-utp: %d ]", peerinfo->to_string().c_str()
    │ │ │ │ -						, peerinfo->supports_utp);
    │ │ │ │ -				}
    │ │ │ │ +#ifdef TORRENT_WINDOWS
    │ │ │ │ +			ret = file_pointer(::_wfopen(convert_to_native_path_string(fn).c_str(), L"wb+"));
    │ │ │ │ +#else
    │ │ │ │ +			ret = file_pointer(::fopen(fn.c_str(), "wb+"));
    │ │ │ │  #endif
    │ │ │ │ -				return false;
    │ │ │ │ -			}
    │ │ │ │ -		}
    │ │ │ │ -
    │ │ │ │ -
    aux::socket_type s = [&] { │ │ │ │ -
    │ │ │ │ -#if TORRENT_USE_I2P │ │ │ │ - if (peerinfo->is_i2p_addr) │ │ │ │ - { │ │ │ │ - // It's not entirely obvious why this peer connection is not marked as │ │ │ │ - // one. The main feature of a peer connection is that whether or not we │ │ │ │ - // proxy it is configurable. When we use i2p, we want to always prox │ │ │ │ - // everything via i2p. │ │ │ │ - │ │ │ │ - aux::proxy_settings proxy; │ │ │ │ - proxy.hostname = settings().get_str(settings_pack::i2p_hostname); │ │ │ │ - proxy.port = std::uint16_t(settings().get_int(settings_pack::i2p_port)); │ │ │ │ - proxy.type = settings_pack::i2p_proxy; │ │ │ │ - │ │ │ │ - aux::socket_type ret = instantiate_connection(m_ses.get_context() │ │ │ │ - , proxy, nullptr, nullptr, false, false); │ │ │ │ - i2p_stream& str = boost::get<i2p_stream>(ret); │ │ │ │ - str.set_local_i2p_endpoint(m_ses.local_i2p_endpoint()); │ │ │ │ - str.set_destination(static_cast<i2p_peer*>(peerinfo)->dest()); │ │ │ │ - str.set_command(i2p_stream::cmd_connect); │ │ │ │ - str.set_session_id(m_ses.i2p_session()); │ │ │ │ - return ret; │ │ │ │ + if (ret.file() == nullptr) │ │ │ │ + ec.assign(errno, generic_category()); │ │ │ │ } │ │ │ │ - else │ │ │ │ -#endif │ │ │ │ - { │ │ │ │ - void* userdata = nullptr; │ │ │ │ -#ifdef TORRENT_SSL_PEERS │ │ │ │ - if (is_ssl_torrent()) │ │ │ │ - { │ │ │ │ -
    relevance 0../src/torrent.cpp:9091perhaps 0 should actually mean 0

    perhaps 0 should actually mean 0

    ../src/torrent.cpp:9091

    		// finished torrents may not change their queue positions, as it's set to
    │ │ │ │ -		// -1
    │ │ │ │ -		if ((m_abort || is_finished()) && p != no_pos) return;
    │ │ │ │ -
    │ │ │ │ -		TORRENT_ASSERT((p == no_pos) == is_finished()
    │ │ │ │ -			|| (!m_auto_managed && p == no_pos)
    │ │ │ │ -			|| (m_abort && p == no_pos)
    │ │ │ │ -			|| (!m_added && p == no_pos));
    │ │ │ │ -		if (p == m_sequence_number) return;
    │ │ │ │ -
    │ │ │ │ -		TORRENT_ASSERT(p >= no_pos);
    │ │ │ │ -
    │ │ │ │ -		state_updated();
    │ │ │ │ -
    │ │ │ │ -		m_ses.set_queue_position(this, p);
    │ │ │ │ +		if (ec) return {};
    │ │ │ │ +		return ret;
    │ │ │ │  	}
    │ │ │ │  
    │ │ │ │ -	void torrent::set_max_uploads(int limit, bool const state_update)
    │ │ │ │ +	void posix_part_file::free_piece(piece_index_t const piece)
    │ │ │ │  	{
    │ │ │ │ -		TORRENT_ASSERT(is_single_thread());
    │ │ │ │ -
    if (limit <= 0) limit = (1 << 24) - 1; │ │ │ │ -
    if (int(m_max_uploads) == limit) return; │ │ │ │ - if (state_update) state_updated(); │ │ │ │ - m_max_uploads = aux::numeric_cast<std::uint32_t>(limit); │ │ │ │ -#ifndef TORRENT_DISABLE_LOGGING │ │ │ │ - if (should_log() && state_update) │ │ │ │ - debug_log("*** set-max-uploads: %d", m_max_uploads); │ │ │ │ -#endif │ │ │ │ + auto const i = m_piece_map.find(piece); │ │ │ │ + if (i == m_piece_map.end()) return; │ │ │ │ │ │ │ │ - if (state_update) │ │ │ │ - set_need_save_resume(torrent_handle::if_config_changed); │ │ │ │ +
    │ │ │ │ +
    m_free_slots.push_back(i->second); │ │ │ │ + m_piece_map.erase(i); │ │ │ │ + m_dirty_metadata = true; │ │ │ │ } │ │ │ │ │ │ │ │ - void torrent::set_max_connections(int limit, bool const state_update) │ │ │ │ - { │ │ │ │ - TORRENT_ASSERT(is_single_thread()); │ │ │ │ -
    relevance 0../src/torrent.cpp:9108perhaps 0 should actually mean 0

    perhaps 0 should actually mean 0

    ../src/torrent.cpp:9108

    │ │ │ │ -	void torrent::set_max_uploads(int limit, bool const state_update)
    │ │ │ │ +	void posix_part_file::move_partfile(std::string const& path, error_code& ec)
    │ │ │ │  	{
    │ │ │ │ -		TORRENT_ASSERT(is_single_thread());
    │ │ │ │ -		if (limit <= 0) limit = (1 << 24) - 1;
    │ │ │ │ -		if (int(m_max_uploads) == limit) return;
    │ │ │ │ -		if (state_update) state_updated();
    │ │ │ │ -		m_max_uploads = aux::numeric_cast<std::uint32_t>(limit);
    │ │ │ │ -#ifndef TORRENT_DISABLE_LOGGING
    │ │ │ │ -		if (should_log() && state_update)
    │ │ │ │ -			debug_log("*** set-max-uploads: %d", m_max_uploads);
    │ │ │ │ -#endif
    │ │ │ │ -
    │ │ │ │ -		if (state_update)
    │ │ │ │ -			set_need_save_resume(torrent_handle::if_config_changed);
    │ │ │ │ -	}
    │ │ │ │ +		flush_metadata_impl(ec);
    │ │ │ │ +		if (ec) return;
    │ │ │ │  
    │ │ │ │ -	void torrent::set_max_connections(int limit, bool const state_update)
    │ │ │ │ -	{
    │ │ │ │ -		TORRENT_ASSERT(is_single_thread());
    │ │ │ │ -
    if (limit <= 0) limit = (1 << 24) - 1; │ │ │ │ -
    if (int(m_max_connections) == limit) return; │ │ │ │ - if (state_update) state_updated(); │ │ │ │ - m_max_connections = aux::numeric_cast<std::uint32_t>(limit); │ │ │ │ - update_want_peers(); │ │ │ │ + if (!m_piece_map.empty()) │ │ │ │ + { │ │ │ │ + std::string old_path = combine_path(m_path, m_name); │ │ │ │ + std::string new_path = combine_path(path, m_name); │ │ │ │ │ │ │ │ -#ifndef TORRENT_DISABLE_LOGGING │ │ │ │ - if (should_log() && state_update) │ │ │ │ - debug_log("*** set-max-connections: %d", m_max_connections); │ │ │ │ -#endif │ │ │ │ + rename(old_path, new_path, ec); │ │ │ │ + if (ec == boost::system::errc::no_such_file_or_directory) │ │ │ │ + ec.clear(); │ │ │ │ │ │ │ │ - if (num_peers() > int(m_max_connections)) │ │ │ │ - { │ │ │ │ - disconnect_peers(num_peers() - m_max_connections │ │ │ │ - , errors::too_many_connections); │ │ │ │ + if (ec) │ │ │ │ + { │ │ │ │ + storage_error se; │ │ │ │ + aux::copy_file(old_path, new_path, se); │ │ │ │ + ec = se.ec; │ │ │ │ + if (ec) return; │ │ │ │ + remove(old_path, ec); │ │ │ │ + } │ │ │ │ } │ │ │ │ - │ │ │ │ - if (state_update) │ │ │ │ - set_need_save_resume(torrent_handle::if_config_changed); │ │ │ │ + m_path = path; │ │ │ │ } │ │ │ │ +
    relevance 0../src/posix_part_file.cpp:425instead of rebuilding the whole file header and flushing it, update the slot entries as we go

    instead of rebuilding the whole file header │ │ │ │ +and flushing it, update the slot entries as we go

    ../src/posix_part_file.cpp:425

    				auto bytes_read = std::fread(buf.get(), 1, std::size_t(block_to_copy), file.file());
    │ │ │ │ +				if (int(bytes_read) != block_to_copy)
    │ │ │ │ +					ec.assign(errno, generic_category());
    │ │ │ │  
    │ │ │ │ -	void torrent::set_upload_limit(int const limit)
    │ │ │ │ -	{
    │ │ │ │ -		set_limit_impl(limit, peer_connection::upload_channel);
    │ │ │ │ -#ifndef TORRENT_DISABLE_LOGGING
    │ │ │ │ -		debug_log("*** set-upload-limit: %d", limit);
    │ │ │ │ -#endif
    │ │ │ │ -	}
    │ │ │ │ +				TORRENT_ASSERT(!ec);
    │ │ │ │ +				if (ec) return;
    │ │ │ │  
    │ │ │ │ -	void torrent::set_download_limit(int const limit)
    │ │ │ │ -	{
    │ │ │ │ -
    relevance 0../src/torrent.cpp:11034instead of resorting the whole list, insert the peers directly into the right place

    instead of resorting the whole list, insert the peers │ │ │ │ -directly into the right place

    ../src/torrent.cpp:11034

    				std::printf("timed out [average-piece-time: %d ms ]\n"
    │ │ │ │ -					, m_average_piece_time);
    │ │ │ │ -#endif
    │ │ │ │ +				f(file_offset, {buf.get(), block_to_copy});
    │ │ │ │  			}
    │ │ │ │ +			file_offset += block_to_copy;
    │ │ │ │ +			piece_offset = 0;
    │ │ │ │ +			size -= block_to_copy;
    │ │ │ │ +		}
    │ │ │ │ +	}
    │ │ │ │  
    │ │ │ │ -			// pick all blocks for this piece. the peers list is kept up to date
    │ │ │ │ -			// and sorted. when we issue a request to a peer, its download queue
    │ │ │ │ -			// time will increase and it may need to be bumped in the peers list,
    │ │ │ │ -			// since it's ordered by download queue time
    │ │ │ │ -			pick_time_critical_block(peers, ignore_peers
    │ │ │ │ -				, peers_with_requests
    │ │ │ │ -				, pi, &i, m_picker.get()
    │ │ │ │ -				, blocks_in_piece, timed_out);
    │ │ │ │ +	void posix_part_file::flush_metadata(error_code& ec)
    │ │ │ │ +	{
    │ │ │ │ +		flush_metadata_impl(ec);
    │ │ │ │ +	}
    │ │ │ │  
    │ │ │ │ -			// put back the peers we ignored into the peer list for the next piece
    │ │ │ │ -			if (!ignore_peers.empty())
    │ │ │ │ -			{
    │ │ │ │ -				peers.insert(peers.begin(), ignore_peers.begin(), ignore_peers.end());
    │ │ │ │ -				ignore_peers.clear();
    │ │ │ │ +
    void posix_part_file::flush_metadata_impl(error_code& ec) │ │ │ │ +
    { │ │ │ │ + // do we need to flush the metadata? │ │ │ │ + if (m_dirty_metadata == false) return; │ │ │ │ │ │ │ │ -
    std::sort(peers.begin(), peers.end() │ │ │ │ -
    , [] (peer_connection const* lhs, peer_connection const* rhs) │ │ │ │ - { return lhs->download_queue_time(16*1024) < rhs->download_queue_time(16*1024); }); │ │ │ │ - } │ │ │ │ + if (m_piece_map.empty()) │ │ │ │ + { │ │ │ │ + // if we don't have any pieces left in the │ │ │ │ + // part file, remove it │ │ │ │ + std::string const p = combine_path(m_path, m_name); │ │ │ │ + remove(p, ec); │ │ │ │ │ │ │ │ - // if this peer's download time exceeds 2 seconds, we're done. │ │ │ │ - // We don't want to build unreasonably long request queues │ │ │ │ - if (!peers.empty() && peers[0]->download_queue_time() > milliseconds(2000)) │ │ │ │ - break; │ │ │ │ + if (ec == boost::system::errc::no_such_file_or_directory) │ │ │ │ + ec.clear(); │ │ │ │ + return; │ │ │ │ } │ │ │ │ │ │ │ │ - // commit all the time critical requests │ │ │ │ - for (auto p : peers_with_requests) │ │ │ │ - { │ │ │ │ - p->send_block_requests(); │ │ │ │ - } │ │ │ │ - } │ │ │ │ -#endif // TORRENT_DISABLE_STREAMING │ │ │ │ + auto f = open_file(open_mode::read_write, ec); │ │ │ │ + if (ec) return; │ │ │ │ │ │ │ │ - std::set<std::string> torrent::web_seeds(web_seed_entry::type_t const type) const │ │ │ │ - { │ │ │ │ - TORRENT_ASSERT(is_single_thread()); │ │ │ │ - std::set<std::string> ret; │ │ │ │ - for (auto const& s : m_web_seeds) │ │ │ │ - { │ │ │ │ - if (s.peer_info.banned) continue; │ │ │ │ - if (s.removed) continue; │ │ │ │ - if (s.type != type) continue; │ │ │ │ - ret.insert(s.url); │ │ │ │ - } │ │ │ │ - return ret; │ │ │ │ -
    relevance 0../src/random.cpp:141improve calling RAND_bytes multiple times, using fallback for now

    improve calling RAND_bytes multiple times, using fallback for now

    ../src/random.cpp:141

    #else
    │ │ │ │ -			std::generate(buffer.begin(), buffer.end(), [] { return char(random(0xff)); });
    │ │ │ │ -#endif
    │ │ │ │ -		}
    │ │ │ │ +		std::vector<char> header(static_cast<std::size_t>(m_header_size));
    │ │ │ │  
    │ │ │ │ -		void crypto_random_bytes(span<char> buffer)
    │ │ │ │ -		{
    │ │ │ │ -#ifdef TORRENT_BUILD_SIMULATOR
    │ │ │ │ -			// In the simulator we want deterministic random numbers
    │ │ │ │ -			std::generate(buffer.begin(), buffer.end(), [] { return char(random(0xff)); });
    │ │ │ │ -#elif TORRENT_USE_CNG
    │ │ │ │ -			aux::cng_gen_random(buffer);
    │ │ │ │ -#elif TORRENT_USE_CRYPTOAPI
    │ │ │ │ -			// windows
    │ │ │ │ -			aux::crypt_gen_random(buffer);
    │ │ │ │ -#elif defined TORRENT_USE_LIBCRYPTO && !defined TORRENT_USE_WOLFSSL
    │ │ │ │ -// wolfSSL uses wc_RNG_GenerateBlock as the internal function for the
    │ │ │ │ -// openssl compatibility layer. This function API does not support
    │ │ │ │ -// an arbitrary buffer size (openssl does), it is limited by the
    │ │ │ │ -// constant RNG_MAX_BLOCK_LEN.
    │ │ │ │ -
    │ │ │ │ -
    // openssl │ │ │ │ - int r = RAND_bytes(reinterpret_cast<unsigned char*>(buffer.data()) │ │ │ │ - , int(buffer.size())); │ │ │ │ - if (r != 1) aux::throw_ex<system_error>(errors::no_entropy); │ │ │ │ -#elif TORRENT_USE_GETRANDOM │ │ │ │ - ssize_t const r = ::getrandom(buffer.data(), static_cast<std::size_t>(buffer.size()), 0); │ │ │ │ - if (r == ssize_t(buffer.size())) return; │ │ │ │ - if (r == -1 && errno != ENOSYS) aux::throw_ex<system_error>(error_code(errno, generic_category())); │ │ │ │ - static dev_random dev; │ │ │ │ - dev.read(buffer); │ │ │ │ -#elif TORRENT_USE_DEV_RANDOM │ │ │ │ - static dev_random dev; │ │ │ │ - dev.read(buffer); │ │ │ │ -#else │ │ │ │ + using namespace libtorrent::aux; │ │ │ │ │ │ │ │ -#if TORRENT_BROKEN_RANDOM_DEVICE │ │ │ │ - // even pseudo random numbers rely on being able to seed the random │ │ │ │ - // generator │ │ │ │ -#error "no entropy source available" │ │ │ │ -#else │ │ │ │ -#ifdef TORRENT_I_WANT_INSECURE_RANDOM_NUMBERS │ │ │ │ - std::generate(buffer.begin(), buffer.end(), [] { return char(random(0xff)); }); │ │ │ │ -#else │ │ │ │ -#error "no secure entropy source available. If you really want insecure random numbers, define TORRENT_I_WANT_INSECURE_RANDOM_NUMBERS" │ │ │ │ -#endif │ │ │ │ -#endif │ │ │ │ + char* ptr = header.data(); │ │ │ │ + write_uint32(m_max_pieces, ptr); │ │ │ │ + write_uint32(m_piece_size, ptr); │ │ │ │ │ │ │ │ -#endif │ │ │ │ - } │ │ │ │ -} │ │ │ │ -
    relevance 0../src/session_impl.cpp:615come up with some abstraction to do this for gnutls as well load certificates from the windows system certificate store

    come up with some abstraction to do this for gnutls as well │ │ │ │ + for (piece_index_t piece(0); piece < piece_index_t(m_max_pieces); ++piece) │ │ │ │ + { │ │ │ │ + auto const i = m_piece_map.find(piece); │ │ │ │ +relevance 0../src/session_impl.cpp:615come up with some abstraction to do this for gnutls as well load certificates from the windows system certificate store

    come up with some abstraction to do this for gnutls as well │ │ │ │ load certificates from the windows system certificate store

    ../src/session_impl.cpp:615

    		pause();
    │ │ │ │  	}
    │ │ │ │  #endif
    │ │ │ │  
    │ │ │ │  	// This function is called by the creating thread, not in the message loop's
    │ │ │ │  	// io_context thread.
    │ │ │ │  	void session_impl::start_session()
    │ │ │ │ @@ -8818,15 +7230,15 @@
    │ │ │ │  #endif
    │ │ │ │  #ifdef __APPLE__
    │ │ │ │  		m_ssl_ctx.load_verify_file("/etc/ssl/cert.pem", ec);
    │ │ │ │  #ifndef TORRENT_DISABLE_LOGGING
    │ │ │ │  		if (ec) session_log("SSL load_verify_file failed: %s", ec.message().c_str());
    │ │ │ │  		ec.clear();
    │ │ │ │  #endif
    │ │ │ │ -
    relevance 0../src/session_impl.cpp:1482it would be nice to reserve() these vectors up front

    it would be nice to reserve() these vectors up front

    ../src/session_impl.cpp:1482

    			bandwidth_channel* ch = &p->channel[peer_connection::download_channel];
    │ │ │ │ +
    relevance 0../src/session_impl.cpp:1482it would be nice to reserve() these vectors up front

    it would be nice to reserve() these vectors up front

    ../src/session_impl.cpp:1482

    			bandwidth_channel* ch = &p->channel[peer_connection::download_channel];
    │ │ │ │  			if (use_quota_overhead(ch, amount_down))
    │ │ │ │  				ret |= 1 << peer_connection::download_channel;
    │ │ │ │  			ch = &p->channel[peer_connection::upload_channel];
    │ │ │ │  			if (use_quota_overhead(ch, amount_up))
    │ │ │ │  				ret |= 1 << peer_connection::upload_channel;
    │ │ │ │  		}
    │ │ │ │  		return ret;
    │ │ │ │ @@ -8869,15 +7281,15 @@
    │ │ │ │  	bool get_setting_impl(Pack const& p, int name, bool*)
    │ │ │ │  	{ return p.get_bool(name); }
    │ │ │ │  
    │ │ │ │  	template <typename Pack>
    │ │ │ │  	std::string get_setting_impl(Pack const& p, int name, std::string*)
    │ │ │ │  	{ return p.get_str(name); }
    │ │ │ │  
    │ │ │ │ -
    relevance 0../src/session_impl.cpp:1996could this function be merged with expand_unspecified_addresses? right now both listen_endpoint_t and listen_interface_t are almost identical, maybe the latter could be removed too

    could this function be merged with expand_unspecified_addresses? │ │ │ │ +relevance 0../src/session_impl.cpp:1996could this function be merged with expand_unspecified_addresses? right now both listen_endpoint_t and listen_interface_t are almost identical, maybe the latter could be removed too

    could this function be merged with expand_unspecified_addresses? │ │ │ │ right now both listen_endpoint_t and listen_interface_t are almost │ │ │ │ identical, maybe the latter could be removed too

    ../src/session_impl.cpp:1996

    		session_log("FATAL SESSION ERROR (%s : %d) [%s]"
    │ │ │ │  			, ec.category().name(), ec.value(), ec.message().c_str());
    │ │ │ │  #endif
    │ │ │ │  		this->abort();
    │ │ │ │  	}
    │ │ │ │  
    │ │ │ │ @@ -8922,15 +7334,15 @@
    │ │ │ │  				// (which must be of the same family as the address we're
    │ │ │ │  				// connecting to)
    │ │ │ │  				if (iface.device != ipface.name) continue;
    │ │ │ │  
    │ │ │ │  				bool const local = iface.local
    │ │ │ │  					|| ipface.interface_address.is_loopback()
    │ │ │ │  					|| is_link_local(ipface.interface_address);
    │ │ │ │ -
    relevance 0../src/session_impl.cpp:2304it would probably be better to do this by having a listen-socket "version" number that gets bumped. And instead of setting a bool to disable a tracker, we set the version number that it was disabled at. This change would affect the ABI in 1.2, so should be done in 2.0 or later

    it would probably be better to do this by having a │ │ │ │ +relevance 0../src/session_impl.cpp:2304it would probably be better to do this by having a listen-socket "version" number that gets bumped. And instead of setting a bool to disable a tracker, we set the version number that it was disabled at. This change would affect the ABI in 1.2, so should be done in 2.0 or later

    it would probably be better to do this by having a │ │ │ │ listen-socket "version" number that gets bumped. And instead of │ │ │ │ setting a bool to disable a tracker, we set the version number that │ │ │ │ it was disabled at. This change would affect the ABI in 1.2, so │ │ │ │ should be done in 2.0 or later

    ../src/session_impl.cpp:2304

    		{
    │ │ │ │  			for (auto const& s : m_listen_sockets)
    │ │ │ │  				remap_ports(remap_natpmp_and_upnp, *s);
    │ │ │ │  		}
    │ │ │ │ @@ -8977,15 +7389,15 @@
    │ │ │ │  			if (ep != EndpointType())
    │ │ │ │  				map_handle = m.add_mapping(protocol, ep.port(), ep, device);
    │ │ │ │  		}
    │ │ │ │  	}
    │ │ │ │  
    │ │ │ │  	void session_impl::remap_ports(remap_port_mask_t const mask
    │ │ │ │  		, listen_socket_t& s)
    │ │ │ │ -
    relevance 0../src/session_impl.cpp:2864this size need to be capped

    this size need to be capped

    ../src/session_impl.cpp:2864

    				// handshaking
    │ │ │ │ +
    relevance 0../src/session_impl.cpp:2864this size need to be capped

    this size need to be capped

    ../src/session_impl.cpp:2864

    				// handshaking
    │ │ │ │  				return socket_type(ssl_stream<tcp::socket>(tcp::socket(std::move(s)), m_peer_ssl_ctx));
    │ │ │ │  			}
    │ │ │ │  			else
    │ │ │ │  #endif
    │ │ │ │  			{
    │ │ │ │  				return socket_type(tcp::socket(std::move(s)));
    │ │ │ │  			}
    │ │ │ │ @@ -9021,15 +7433,15 @@
    │ │ │ │  
    │ │ │ │  	void session_impl::on_incoming_utp_ssl(socket_type s)
    │ │ │ │  	{
    │ │ │ │  		TORRENT_ASSERT(is_ssl(s));
    │ │ │ │  
    │ │ │ │  		// save the socket so we can cancel the handshake
    │ │ │ │  
    │ │ │ │ -
    relevance 0../src/session_impl.cpp:2889this size need to be capped

    this size need to be capped

    ../src/session_impl.cpp:2889

    			// after the handshake is done
    │ │ │ │ +
    relevance 0../src/session_impl.cpp:2889this size need to be capped

    this size need to be capped

    ../src/session_impl.cpp:2889

    			// after the handshake is done
    │ │ │ │  			ADD_OUTSTANDING_ASYNC("session_impl::ssl_handshake");
    │ │ │ │  			boost::get<ssl_stream<tcp::socket>>(**iter).async_accept_handshake(
    │ │ │ │  				[this, sock] (error_code const& err) { ssl_handshake(err, sock); });
    │ │ │ │  		}
    │ │ │ │  		else
    │ │ │ │  #endif
    │ │ │ │  		{
    │ │ │ │ @@ -9072,15 +7484,15 @@
    │ │ │ │  		if (iter == m_incoming_sockets.end()) return;
    │ │ │ │  
    │ │ │ │  		socket_type s(std::move(**iter));
    │ │ │ │  		TORRENT_ASSERT(is_ssl(s));
    │ │ │ │  		m_incoming_sockets.erase(iter);
    │ │ │ │  
    │ │ │ │  		error_code e;
    │ │ │ │ -
    relevance 0../src/session_impl.cpp:3588have a separate list for these connections, instead of having to loop through all of them

    have a separate list for these connections, instead of having to loop through all of them

    ../src/session_impl.cpp:3588

    		// --------------------------------------------------------------
    │ │ │ │ +
    relevance 0../src/session_impl.cpp:3588have a separate list for these connections, instead of having to loop through all of them

    have a separate list for these connections, instead of having to loop through all of them

    ../src/session_impl.cpp:3588

    		// --------------------------------------------------------------
    │ │ │ │  		if (!m_paused) m_auto_manage_time_scaler--;
    │ │ │ │  		if (m_auto_manage_time_scaler < 0)
    │ │ │ │  		{
    │ │ │ │  			m_auto_manage_time_scaler = settings().get_int(settings_pack::auto_manage_interval);
    │ │ │ │  			recalculate_auto_managed_torrents();
    │ │ │ │  		}
    │ │ │ │  
    │ │ │ │ @@ -9123,15 +7535,15 @@
    │ │ │ │  
    │ │ │ │  			// if the call to second_tick caused the torrent
    │ │ │ │  			// to no longer want to be ticked (i.e. it was
    │ │ │ │  			// removed from the list) we need to back up the counter
    │ │ │ │  			// to not miss the torrent after it
    │ │ │ │  			if (!t.want_tick()) --i;
    │ │ │ │  		}
    │ │ │ │ -
    relevance 0../src/session_impl.cpp:3621this should apply to all bandwidth channels

    this should apply to all bandwidth channels

    ../src/session_impl.cpp:3621

    #if TORRENT_DEBUG_STREAMING > 0
    │ │ │ │ +
    relevance 0../src/session_impl.cpp:3621this should apply to all bandwidth channels

    this should apply to all bandwidth channels

    ../src/session_impl.cpp:3621

    #if TORRENT_DEBUG_STREAMING > 0
    │ │ │ │  		std::printf("\033[2J\033[0;0H");
    │ │ │ │  #endif
    │ │ │ │  
    │ │ │ │  		aux::vector<torrent*>& want_tick = m_torrent_lists[torrent_want_tick];
    │ │ │ │  		for (int i = 0; i < int(want_tick.size()); ++i)
    │ │ │ │  		{
    │ │ │ │  			torrent& t = *want_tick[i];
    │ │ │ │ @@ -9174,15 +7586,15 @@
    │ │ │ │  #endif
    │ │ │ │  
    │ │ │ │  		m_stat.second_tick(tick_interval_ms);
    │ │ │ │  
    │ │ │ │  		// --------------------------------------------------------------
    │ │ │ │  		// scrape paused torrents that are auto managed
    │ │ │ │  		// (unless the session is paused)
    │ │ │ │ -
    relevance 0../src/session_impl.cpp:4312use a lower limit than m_settings.connections_limit to allocate the to 10% or so of connection slots for incoming connections cap this at max - 1, since we may add one below

    use a lower limit than m_settings.connections_limit │ │ │ │ +relevance 0../src/session_impl.cpp:4312use a lower limit than m_settings.connections_limit to allocate the to 10% or so of connection slots for incoming connections cap this at max - 1, since we may add one below

    use a lower limit than m_settings.connections_limit │ │ │ │ to allocate the to 10% or so of connection slots for incoming │ │ │ │ connections │ │ │ │ cap this at max - 1, since we may add one below

    ../src/session_impl.cpp:4312

    		// boost, which are done immediately on a tracker response. These
    │ │ │ │  		// connections needs to be deducted from the regular connection attempt
    │ │ │ │  		// quota for this tick
    │ │ │ │  		if (m_boost_connections > 0)
    │ │ │ │  		{
    │ │ │ │ @@ -9228,15 +7640,15 @@
    │ │ │ │  
    │ │ │ │  			if (m_next_finished_connect_torrent >= int(want_peers_finished.size()))
    │ │ │ │  				m_next_finished_connect_torrent = 0;
    │ │ │ │  
    │ │ │ │  			torrent* t = nullptr;
    │ │ │ │  			// there are prioritized torrents. Pick one of those
    │ │ │ │  			while (!m_prio_torrents.empty())
    │ │ │ │ -
    relevance 0../src/session_impl.cpp:4457post a message to have this happen immediately instead of waiting for the next tick

    post a message to have this happen │ │ │ │ +relevance 0../src/session_impl.cpp:4457post a message to have this happen immediately instead of waiting for the next tick

    post a message to have this happen │ │ │ │ immediately instead of waiting for the next tick

    ../src/session_impl.cpp:4457

    				continue;
    │ │ │ │  			}
    │ │ │ │  
    │ │ │ │  			if (!p->is_peer_interested()
    │ │ │ │  				|| p->is_disconnecting()
    │ │ │ │  				|| p->is_connecting())
    │ │ │ │  			{
    │ │ │ │ @@ -9280,15 +7692,15 @@
    │ │ │ │  		if (should_log())
    │ │ │ │  		{
    │ │ │ │  			session_log("RECALCULATE UNCHOKE SLOTS: [ peers: %d "
    │ │ │ │  				"eligible-peers: %d"
    │ │ │ │  				" allowed-slots: %d ]"
    │ │ │ │  				, int(m_connections.size())
    │ │ │ │  				, int(peers.size())
    │ │ │ │ -
    relevance 0../src/session_impl.cpp:4784it might be a nice feature here to limit the number of torrents to send in a single update. By just posting the first n torrents, they would nicely be round-robined because the torrent lists are always pushed back. Perhaps the status_update_alert could even have a fixed array of n entries rather than a vector, to further improve memory locality.

    it might be a nice feature here to limit the number of torrents │ │ │ │ +relevance 0../src/session_impl.cpp:4784it might be a nice feature here to limit the number of torrents to send in a single update. By just posting the first n torrents, they would nicely be round-robined because the torrent lists are always pushed back. Perhaps the status_update_alert could even have a fixed array of n entries rather than a vector, to further improve memory locality.

    it might be a nice feature here to limit the number of torrents │ │ │ │ to send in a single update. By just posting the first n torrents, they │ │ │ │ would nicely be round-robined because the torrent lists are always │ │ │ │ pushed back. Perhaps the status_update_alert could even have a fixed │ │ │ │ array of n entries rather than a vector, to further improve memory │ │ │ │ locality.

    ../src/session_impl.cpp:4784

    			t->status(&st, flags);
    │ │ │ │  		}
    │ │ │ │  	}
    │ │ │ │ @@ -9336,15 +7748,15 @@
    │ │ │ │  			m_posted_stats_header = true;
    │ │ │ │  			m_alerts.emplace_alert<session_stats_header_alert>();
    │ │ │ │  		}
    │ │ │ │  		m_disk_thread->update_stats_counters(m_stats_counters);
    │ │ │ │  
    │ │ │ │  #ifndef TORRENT_DISABLE_DHT
    │ │ │ │  		if (m_dht)
    │ │ │ │ -
    relevance 0../src/session_impl.cpp:5159factor out this logic into a separate function for unit testing

    factor out this logic into a separate function for unit │ │ │ │ +relevance 0../src/session_impl.cpp:5159factor out this logic into a separate function for unit testing

    factor out this logic into a separate function for unit │ │ │ │ testing

    ../src/session_impl.cpp:5159

    		if (m_settings.get_int(settings_pack::outgoing_port) > 0)
    │ │ │ │  		{
    │ │ │ │  #ifdef TORRENT_WINDOWS
    │ │ │ │  			s.set_option(exclusive_address_use(true), ec);
    │ │ │ │  #else
    │ │ │ │  			s.set_option(tcp::acceptor::reuse_address(true), ec);
    │ │ │ │  #endif
    │ │ │ │ @@ -9388,15 +7800,15 @@
    │ │ │ │  
    │ │ │ │  				if (ls->flags & listen_socket_t::proxy
    │ │ │ │  					|| match_addr_mask(ls->local_endpoint.address(), remote_address, ls->netmask))
    │ │ │ │  				{
    │ │ │ │  					// is this better than the previous match?
    │ │ │ │  					match = ls;
    │ │ │ │  				}
    │ │ │ │ -
    relevance 0../src/session_impl.cpp:5878refactor, move the storage to dht_tracker

    refactor, move the storage to dht_tracker

    ../src/session_impl.cpp:5878

    #ifndef TORRENT_DISABLE_LOGGING
    │ │ │ │ +
    relevance 0../src/session_impl.cpp:5878refactor, move the storage to dht_tracker

    refactor, move the storage to dht_tracker

    ../src/session_impl.cpp:5878

    #ifndef TORRENT_DISABLE_LOGGING
    │ │ │ │  			session_log("not starting DHT, outstanding router lookups: %d"
    │ │ │ │  				, m_outstanding_router_lookups);
    │ │ │ │  #endif
    │ │ │ │  			return;
    │ │ │ │  		}
    │ │ │ │  
    │ │ │ │  		if (m_abort)
    │ │ │ │ @@ -9439,15 +7851,15 @@
    │ │ │ │  		for (auto const& n : m_dht_router_nodes)
    │ │ │ │  		{
    │ │ │ │  			m_dht->add_router_node(n);
    │ │ │ │  		}
    │ │ │ │  
    │ │ │ │  		for (auto const& n : m_dht_nodes)
    │ │ │ │  		{
    │ │ │ │ -
    relevance 0../src/session_impl.cpp:6265asserts that no outstanding async operations are still in flight

    asserts that no outstanding async operations are still in flight

    ../src/session_impl.cpp:6265

    		if (!m_dht) return;
    │ │ │ │ +
    relevance 0../src/session_impl.cpp:6265asserts that no outstanding async operations are still in flight

    asserts that no outstanding async operations are still in flight

    ../src/session_impl.cpp:6265

    		if (!m_dht) return;
    │ │ │ │  		m_dht->direct_request(ep, e, std::bind(&on_direct_response, std::ref(m_alerts), userdata, _1));
    │ │ │ │  	}
    │ │ │ │  
    │ │ │ │  #endif
    │ │ │ │  
    │ │ │ │  	bool session_impl::is_listening() const
    │ │ │ │  	{
    │ │ │ │ @@ -9490,15 +7902,903 @@
    │ │ │ │  			for (wakeup_t const& w : _wakeups)
    │ │ │ │  			{
    │ │ │ │  				bool const idle_wakeup = w.context_switches > prev_csw;
    │ │ │ │  				std::fprintf(f, "%" PRId64 "\t%" PRId64 "\t%" PRId64 "\t%c\t%s\n"
    │ │ │ │  					, total_microseconds(w.timestamp - m)
    │ │ │ │  					, total_microseconds(w.timestamp - prev)
    │ │ │ │  					, w.context_switches
    │ │ │ │ -
    relevance 0../src/piece_picker.cpp:121find a better place for this

    find a better place for this

    ../src/piece_picker.cpp:121

    			if (limit == 0)
    │ │ │ │ +
    relevance 0../src/load_torrent.cpp:121move the loading logic from torrent_info constructor into here

    move the loading logic from torrent_info constructor into here

    ../src/load_torrent.cpp:121

    				mask.resize(std::size_t(full_size), false);
    │ │ │ │ +				for (int i = merkle_first_leaf(piece_layer_size)
    │ │ │ │ +					, end = i + num_pieces; i < end; ++i)
    │ │ │ │ +				{
    │ │ │ │ +					mask[std::size_t(i)] = true;
    │ │ │ │ +				}
    │ │ │ │ +			}
    │ │ │ │ +			ti->free_piece_layers();
    │ │ │ │ +		}
    │ │ │ │ +		atp.info_hashes = atp.ti->info_hashes();
    │ │ │ │ +	}
    │ │ │ │ +}
    │ │ │ │ +
    │ │ │ │ +	add_torrent_params load_torrent_file(std::string const& filename)
    │ │ │ │ +	{ return load_torrent_file(filename, load_torrent_limits{}); }
    │ │ │ │ +	add_torrent_params load_torrent_buffer(span<char const> buffer)
    │ │ │ │ +	{ return load_torrent_buffer(buffer, load_torrent_limits{}); }
    │ │ │ │ +	add_torrent_params load_torrent_parsed(bdecode_node const& torrent_file)
    │ │ │ │ +	{ return load_torrent_parsed(torrent_file, load_torrent_limits{}); }
    │ │ │ │ +
    │ │ │ │ +
    add_torrent_params load_torrent_file(std::string const& filename, load_torrent_limits const& cfg) │ │ │ │ +
    { │ │ │ │ + add_torrent_params ret; │ │ │ │ + ret.ti = std::make_shared<torrent_info>(filename, cfg); │ │ │ │ + update_atp(ret); │ │ │ │ + return ret; │ │ │ │ + } │ │ │ │ + │ │ │ │ + add_torrent_params load_torrent_buffer(span<char const> buffer, load_torrent_limits const& cfg) │ │ │ │ + { │ │ │ │ + add_torrent_params ret; │ │ │ │ + ret.ti = std::make_shared<torrent_info>(buffer, cfg, from_span); │ │ │ │ + update_atp(ret); │ │ │ │ + return ret; │ │ │ │ + } │ │ │ │ + │ │ │ │ + add_torrent_params load_torrent_parsed(bdecode_node const& torrent_file, load_torrent_limits const& cfg) │ │ │ │ + { │ │ │ │ + add_torrent_params ret; │ │ │ │ + ret.ti = std::make_shared<torrent_info>(torrent_file, cfg); │ │ │ │ + update_atp(ret); │ │ │ │ + return ret; │ │ │ │ + } │ │ │ │ + │ │ │ │ +} │ │ │ │ + │ │ │ │ +
    relevance 0../src/cpuid.cpp:131enable when aarch64 is really tested

    enable when aarch64 is really tested

    ../src/cpuid.cpp:131

    	bool supports_mmx() noexcept
    │ │ │ │ +	{
    │ │ │ │ +#if TORRENT_HAS_SSE
    │ │ │ │ +		std::uint32_t cpui[4] = {0};
    │ │ │ │ +		cpuid(cpui, 1);
    │ │ │ │ +		return (cpui[2] & (1 << 23)) != 0;
    │ │ │ │ +#else
    │ │ │ │ +		return false;
    │ │ │ │ +#endif
    │ │ │ │ +	}
    │ │ │ │ +
    │ │ │ │ +	bool supports_arm_neon() noexcept
    │ │ │ │ +	{
    │ │ │ │ +#if TORRENT_HAS_ARM_NEON && TORRENT_HAS_AUXV
    │ │ │ │ +#if defined __arm__
    │ │ │ │ +		//return (getauxval(AT_HWCAP) & HWCAP_NEON);
    │ │ │ │ +		return (helper_getauxval(16) & (1 << 12));
    │ │ │ │ +#elif defined __aarch64__
    │ │ │ │ +		//return (getauxval(AT_HWCAP) & HWCAP_ASIMD);
    │ │ │ │ +		//return (getauxval(16) & (1 << 1));
    │ │ │ │ +
    return false; │ │ │ │ +
    #endif │ │ │ │ +#else │ │ │ │ + return false; │ │ │ │ +#endif │ │ │ │ + } │ │ │ │ + │ │ │ │ + bool supports_arm_crc32c() noexcept │ │ │ │ + { │ │ │ │ +#if TORRENT_HAS_ARM_CRC32 && TORRENT_HAS_AUXV │ │ │ │ +#if defined TORRENT_FORCE_ARM_CRC32 │ │ │ │ + return true; │ │ │ │ +#elif defined __arm__ │ │ │ │ + //return (getauxval(AT_HWCAP2) & HWCAP2_CRC32); │ │ │ │ + return (helper_getauxval(26) & (1 << 4)); │ │ │ │ +#elif defined __aarch64__ │ │ │ │ + //return (getauxval(AT_HWCAP) & HWCAP_CRC32); │ │ │ │ + return (helper_getauxval(16) & (1 << 7)); │ │ │ │ +#endif │ │ │ │ +#else │ │ │ │ + return false; │ │ │ │ +#endif │ │ │ │ + } │ │ │ │ + │ │ │ │ +} // anonymous namespace │ │ │ │ + │ │ │ │ + bool const sse42_support = supports_sse42(); │ │ │ │ + bool const mmx_support = supports_mmx(); │ │ │ │ + bool const arm_neon_support = supports_arm_neon(); │ │ │ │ + bool const arm_crc32c_support = supports_arm_crc32c(); │ │ │ │ +} } │ │ │ │ +
    relevance 0../src/torrent_info.cpp:875this should be considered a failure, and the .torrent file rejected

    this should be considered a failure, and the .torrent file │ │ │ │ +rejected

    ../src/torrent_info.cpp:875

    			std::string ext = extension(filename);
    │ │ │ │ +			int cnt = 0;
    │ │ │ │ +			for (;;)
    │ │ │ │ +			{
    │ │ │ │ +				++cnt;
    │ │ │ │ +				char new_ext[50];
    │ │ │ │ +				std::snprintf(new_ext, sizeof(new_ext), ".%d%s", cnt, ext.c_str());
    │ │ │ │ +				filename = base + new_ext;
    │ │ │ │ +
    │ │ │ │ +				boost::crc_optimal<32, 0x1EDC6F41, 0xFFFFFFFF, 0xFFFFFFFF, true, true> crc;
    │ │ │ │ +				process_string_lowercase(crc, filename);
    │ │ │ │ +				std::uint32_t const new_hash = crc.checksum();
    │ │ │ │ +				if (files.find(new_hash) == files.end())
    │ │ │ │ +				{
    │ │ │ │ +					files.insert({new_hash, {i, 0}});
    │ │ │ │ +					break;
    │ │ │ │ +				}
    │ │ │ │ +				++num_collisions;
    │ │ │ │ +				if (num_collisions > 100)
    │ │ │ │ +				{
    │ │ │ │ +
    } │ │ │ │ +
    } │ │ │ │ + │ │ │ │ + copy_on_write(); │ │ │ │ + m_files.rename_file(i, filename); │ │ │ │ + } │ │ │ │ + } │ │ │ │ + │ │ │ │ + void torrent_info::remap_files(file_storage const& f) │ │ │ │ + { │ │ │ │ + INVARIANT_CHECK; │ │ │ │ + │ │ │ │ + TORRENT_ASSERT(is_loaded()); │ │ │ │ + // the new specified file storage must have the exact │ │ │ │ + // same size as the current file storage │ │ │ │ + TORRENT_ASSERT(m_files.total_size() == f.total_size()); │ │ │ │ + │ │ │ │ + if (m_files.total_size() != f.total_size()) return; │ │ │ │ + copy_on_write(); │ │ │ │ + m_files = f; │ │ │ │ + m_files.set_num_pieces(m_orig_files->num_pieces()); │ │ │ │ + m_files.set_piece_length(m_orig_files->piece_length()); │ │ │ │ + } │ │ │ │ + │ │ │ │ +#if TORRENT_ABI_VERSION == 1 │ │ │ │ + // standard constructor that parses a torrent file │ │ │ │ + torrent_info::torrent_info(entry const& torrent_file) │ │ │ │ + { │ │ │ │ + std::vector<char> tmp; │ │ │ │ + std::back_insert_iterator<std::vector<char>> out(tmp); │ │ │ │ + bencode(out, torrent_file); │ │ │ │ +
    relevance 0../src/settings_pack.cpp:305deprecate this

    deprecate this

    ../src/settings_pack.cpp:305

    		SET(outgoing_port, 0, nullptr),
    │ │ │ │ +		SET(num_outgoing_ports, 0, nullptr),
    │ │ │ │ +		SET(peer_dscp, 0x04, &session_impl::update_peer_dscp),
    │ │ │ │ +		SET(active_downloads, 3, &session_impl::trigger_auto_manage),
    │ │ │ │ +		SET(active_seeds, 5, &session_impl::trigger_auto_manage),
    │ │ │ │ +		SET(active_checking, 1, &session_impl::trigger_auto_manage),
    │ │ │ │ +		SET(active_dht_limit, 88, nullptr),
    │ │ │ │ +		SET(active_tracker_limit, 1600, nullptr),
    │ │ │ │ +		SET(active_lsd_limit, 60, nullptr),
    │ │ │ │ +		SET(active_limit, 500, &session_impl::trigger_auto_manage),
    │ │ │ │ +		DEPRECATED_SET(active_loaded_limit, 0, &session_impl::trigger_auto_manage),
    │ │ │ │ +		SET(auto_manage_interval, 30, nullptr),
    │ │ │ │ +		SET(seed_time_limit, 24 * 60 * 60, nullptr),
    │ │ │ │ +		SET(auto_scrape_interval, 1800, nullptr),
    │ │ │ │ +		SET(auto_scrape_min_interval, 300, nullptr),
    │ │ │ │ +		SET(max_peerlist_size, 3000, nullptr),
    │ │ │ │ +		SET(max_paused_peerlist_size, 1000, nullptr),
    │ │ │ │ +		SET(min_announce_interval, 5 * 60, nullptr),
    │ │ │ │ +		SET(auto_manage_startup, 60, nullptr),
    │ │ │ │ +		SET(seeding_piece_quota, 20, nullptr),
    │ │ │ │ +
    SET(max_rejects, 50, nullptr), │ │ │ │ +
    SET(recv_socket_buffer_size, 0, &session_impl::update_socket_buffer_size), │ │ │ │ + SET(send_socket_buffer_size, 0, &session_impl::update_socket_buffer_size), │ │ │ │ + SET(max_peer_recv_buffer_size, 2 * 1024 * 1024, nullptr), │ │ │ │ + DEPRECATED_SET(file_checks_delay_per_block, 0, nullptr), │ │ │ │ + DEPRECATED2_SET(read_cache_line_size, 32, nullptr), │ │ │ │ + DEPRECATED2_SET(write_cache_line_size, 16, nullptr), │ │ │ │ + SET(optimistic_disk_retry, 10 * 60, nullptr), │ │ │ │ + SET(max_suggest_pieces, 16, nullptr), │ │ │ │ + SET(local_service_announce_interval, 5 * 60, nullptr), │ │ │ │ + SET(dht_announce_interval, 15 * 60, &session_impl::update_dht_announce_interval), │ │ │ │ + SET(udp_tracker_token_expiry, 60, nullptr), │ │ │ │ + DEPRECATED_SET(default_cache_min_age, 1, nullptr), │ │ │ │ + SET(num_optimistic_unchoke_slots, 0, nullptr), │ │ │ │ + DEPRECATED_SET(default_est_reciprocation_rate, 16000, nullptr), │ │ │ │ + DEPRECATED_SET(increase_est_reciprocation_rate, 20, nullptr), │ │ │ │ + DEPRECATED_SET(decrease_est_reciprocation_rate, 3, nullptr), │ │ │ │ + SET(max_pex_peers, 50, nullptr), │ │ │ │ + SET(tick_interval, 500, nullptr), │ │ │ │ + SET(share_mode_target, 3, nullptr), │ │ │ │ + SET(upload_rate_limit, 0, &session_impl::update_upload_rate), │ │ │ │ + SET(download_rate_limit, 0, &session_impl::update_download_rate), │ │ │ │ + DEPRECATED_SET(local_upload_rate_limit, 0, &session_impl::update_local_upload_rate), │ │ │ │ + DEPRECATED_SET(local_download_rate_limit, 0, &session_impl::update_local_download_rate), │ │ │ │ + SET(dht_upload_rate_limit, 8000, &session_impl::update_dht_upload_rate_limit), │ │ │ │ + SET(unchoke_slots_limit, 8, &session_impl::update_unchoke_limit), │ │ │ │ + DEPRECATED_SET(half_open_limit, 0, nullptr), │ │ │ │ + SET(connections_limit, 200, &session_impl::update_connections_limit), │ │ │ │ + SET(connections_slack, 10, nullptr), │ │ │ │ + SET(utp_target_delay, 100, nullptr), │ │ │ │ + SET(utp_gain_factor, 3000, nullptr), │ │ │ │ +
    relevance 0../src/settings_pack.cpp:589it would be nice to reserve() these vectors up front

    it would be nice to reserve() these vectors up front

    ../src/settings_pack.cpp:589

    			s.set_str(settings_pack::string_type_base | i, str_settings[i].default_value);
    │ │ │ │ +			TORRENT_ASSERT(s.get_str(settings_pack::string_type_base + i) == str_settings[i].default_value);
    │ │ │ │ +		}
    │ │ │ │ +
    │ │ │ │ +		for (int i = 0; i < settings_pack::num_int_settings; ++i)
    │ │ │ │ +		{
    │ │ │ │ +			s.set_int(settings_pack::int_type_base | i, int_settings[i].default_value);
    │ │ │ │ +			TORRENT_ASSERT(s.get_int(settings_pack::int_type_base + i) == int_settings[i].default_value);
    │ │ │ │ +		}
    │ │ │ │ +
    │ │ │ │ +		for (int i = 0; i < settings_pack::num_bool_settings; ++i)
    │ │ │ │ +		{
    │ │ │ │ +			s.set_bool(settings_pack::bool_type_base | i, bool_settings[i].default_value);
    │ │ │ │ +			TORRENT_ASSERT(s.get_bool(settings_pack::bool_type_base + i) == bool_settings[i].default_value);
    │ │ │ │ +		}
    │ │ │ │ +	}
    │ │ │ │ +
    │ │ │ │ +	settings_pack default_settings()
    │ │ │ │ +	{
    │ │ │ │ +		settings_pack ret;
    │ │ │ │ +
    for (int i = 0; i < settings_pack::num_string_settings; ++i) │ │ │ │ +
    { │ │ │ │ + if (str_settings[i].default_value == nullptr) continue; │ │ │ │ + ret.set_str(settings_pack::string_type_base + i, str_settings[i].default_value); │ │ │ │ + } │ │ │ │ + │ │ │ │ + for (int i = 0; i < settings_pack::num_int_settings; ++i) │ │ │ │ + { │ │ │ │ + ret.set_int(settings_pack::int_type_base + i, int_settings[i].default_value); │ │ │ │ + } │ │ │ │ + │ │ │ │ + for (int i = 0; i < settings_pack::num_bool_settings; ++i) │ │ │ │ + { │ │ │ │ + ret.set_bool(settings_pack::bool_type_base + i, bool_settings[i].default_value); │ │ │ │ + } │ │ │ │ + return ret; │ │ │ │ + } │ │ │ │ + │ │ │ │ + void apply_pack(settings_pack const* pack, aux::session_settings& sett │ │ │ │ + , aux::session_impl* ses) │ │ │ │ + { │ │ │ │ + using fun_t = void (aux::session_impl::*)(); │ │ │ │ + std::vector<fun_t> callbacks; │ │ │ │ + │ │ │ │ + sett.bulk_set([&](aux::session_settings_single_thread& s) │ │ │ │ + { │ │ │ │ + apply_pack_impl(pack, s, ses ? &callbacks : nullptr); │ │ │ │ + }); │ │ │ │ + │ │ │ │ + // call the callbacks once all the settings have been applied, and │ │ │ │ + // only once per callback │ │ │ │ +
    relevance 0../src/udp_socket.cpp:659perhaps an attempt should be made to bind m_socks5_sock to the device of m_listen_socket

    perhaps an attempt should be made to bind m_socks5_sock to the │ │ │ │ +device of m_listen_socket

    ../src/udp_socket.cpp:659

    	if (ec)
    │ │ │ │ +	{
    │ │ │ │ +		if (m_alerts.should_post<socks5_alert>())
    │ │ │ │ +			m_alerts.emplace_alert<socks5_alert>(m_proxy_addr, operation_t::sock_option, ec);
    │ │ │ │ +		ec.clear();
    │ │ │ │ +	}
    │ │ │ │ +#endif
    │ │ │ │ +#endif
    │ │ │ │ +
    │ │ │ │ +	tcp::endpoint const bind_ep(m_listen_socket.get_local_endpoint().address(), 0);
    │ │ │ │ +	m_socks5_sock.bind(bind_ep, ec);
    │ │ │ │ +	if (ec)
    │ │ │ │ +	{
    │ │ │ │ +		if (m_alerts.should_post<socks5_alert>())
    │ │ │ │ +			m_alerts.emplace_alert<socks5_alert>(m_proxy_addr, operation_t::sock_bind, ec);
    │ │ │ │ +		++m_failures;
    │ │ │ │ +		retry_connection();
    │ │ │ │ +		return;
    │ │ │ │ +	}
    │ │ │ │ +
    │ │ │ │ +
    │ │ │ │ +
    ADD_OUTSTANDING_ASYNC("socks5::on_connected"); │ │ │ │ + m_socks5_sock.async_connect(m_proxy_addr │ │ │ │ + , std::bind(&socks5::on_connected, self(), _1)); │ │ │ │ + │ │ │ │ + ADD_OUTSTANDING_ASYNC("socks5::on_connect_timeout"); │ │ │ │ + m_timer.expires_after(seconds(10)); │ │ │ │ + m_timer.async_wait(std::bind(&socks5::on_connect_timeout │ │ │ │ + , self(), _1)); │ │ │ │ +} │ │ │ │ + │ │ │ │ +void socks5::on_connect_timeout(error_code const& e) │ │ │ │ +{ │ │ │ │ + COMPLETE_ASYNC("socks5::on_connect_timeout"); │ │ │ │ + │ │ │ │ + if (e == boost::asio::error::operation_aborted) return; │ │ │ │ + │ │ │ │ + if (m_abort) return; │ │ │ │ + │ │ │ │ + if (m_alerts.should_post<socks5_alert>()) │ │ │ │ + m_alerts.emplace_alert<socks5_alert>(m_proxy_addr, operation_t::connect, errors::timed_out); │ │ │ │ + │ │ │ │ + error_code ignore; │ │ │ │ + m_socks5_sock.close(ignore); │ │ │ │ + │ │ │ │ + ++m_failures; │ │ │ │ + retry_connection(); │ │ │ │ +} │ │ │ │ + │ │ │ │ +void socks5::on_connected(error_code const& e) │ │ │ │ +{ │ │ │ │ +
    relevance 0../src/torrent.cpp:1941this could be optimized by looking up which files are complete and just look at those

    this could be optimized by looking up which files are │ │ │ │ +complete and just look at those

    ../src/torrent.cpp:1941

    //				TORRENT_ASSERT(picker().have_piece(i));
    │ │ │ │ +				we_have(i);
    │ │ │ │ +			}
    │ │ │ │ +		}
    │ │ │ │ +
    │ │ │ │ +		set_state(torrent_status::checking_resume_data);
    │ │ │ │ +
    │ │ │ │ +		aux::vector<std::string, file_index_t> links;
    │ │ │ │ +#ifndef TORRENT_DISABLE_MUTABLE_TORRENTS
    │ │ │ │ +		if (!m_torrent_file->similar_torrents().empty()
    │ │ │ │ +			|| !m_torrent_file->collections().empty())
    │ │ │ │ +		{
    │ │ │ │ +			resolve_links res(m_torrent_file);
    │ │ │ │ +
    │ │ │ │ +			for (auto const& ih : m_torrent_file->similar_torrents())
    │ │ │ │ +			{
    │ │ │ │ +				std::shared_ptr<torrent> t = m_ses.find_torrent(info_hash_t(ih)).lock();
    │ │ │ │ +				if (!t) continue;
    │ │ │ │ +
    │ │ │ │ +				// Only attempt to reuse files from torrents that are seeding.
    │ │ │ │ +
    if (!t->is_seed()) continue; │ │ │ │ +
    │ │ │ │ + res.match(t->get_torrent_file(), t->save_path()); │ │ │ │ + } │ │ │ │ + for (auto const& c : m_torrent_file->collections()) │ │ │ │ + { │ │ │ │ + std::vector<std::shared_ptr<torrent>> ts = m_ses.find_collection(c); │ │ │ │ + │ │ │ │ + for (auto const& t : ts) │ │ │ │ + { │ │ │ │ + // Only attempt to reuse files from torrents that are seeding. │ │ │ │ +
    relevance 0../src/torrent.cpp:1954this could be optimized by looking up which files are complete and just look at those

    this could be optimized by looking up which files are │ │ │ │ +complete and just look at those

    ../src/torrent.cpp:1954

    		{
    │ │ │ │ +			resolve_links res(m_torrent_file);
    │ │ │ │ +
    │ │ │ │ +			for (auto const& ih : m_torrent_file->similar_torrents())
    │ │ │ │ +			{
    │ │ │ │ +				std::shared_ptr<torrent> t = m_ses.find_torrent(info_hash_t(ih)).lock();
    │ │ │ │ +				if (!t) continue;
    │ │ │ │ +
    │ │ │ │ +				// Only attempt to reuse files from torrents that are seeding.
    │ │ │ │ +				if (!t->is_seed()) continue;
    │ │ │ │ +
    │ │ │ │ +				res.match(t->get_torrent_file(), t->save_path());
    │ │ │ │ +			}
    │ │ │ │ +			for (auto const& c : m_torrent_file->collections())
    │ │ │ │ +			{
    │ │ │ │ +				std::vector<std::shared_ptr<torrent>> ts = m_ses.find_collection(c);
    │ │ │ │ +
    │ │ │ │ +				for (auto const& t : ts)
    │ │ │ │ +				{
    │ │ │ │ +					// Only attempt to reuse files from torrents that are seeding.
    │ │ │ │ +
    if (!t->is_seed()) continue; │ │ │ │ +
    │ │ │ │ + res.match(t->get_torrent_file(), t->save_path()); │ │ │ │ + } │ │ │ │ + } │ │ │ │ + │ │ │ │ + std::vector<resolve_links::link_t> const& l = res.get_links(); │ │ │ │ + if (!l.empty()) │ │ │ │ + { │ │ │ │ + links.resize(m_torrent_file->files().num_files()); │ │ │ │ + for (auto const& i : l) │ │ │ │ + { │ │ │ │ + if (!i.ti) continue; │ │ │ │ + links[i.file_idx] = combine_path(i.save_path │ │ │ │ + , i.ti->files().file_path(i.file_idx)); │ │ │ │ + } │ │ │ │ + } │ │ │ │ + } │ │ │ │ +#endif // TORRENT_DISABLE_MUTABLE_TORRENTS │ │ │ │ + │ │ │ │ +#if TORRENT_USE_ASSERTS │ │ │ │ + TORRENT_ASSERT(m_outstanding_check_files == false); │ │ │ │ + m_outstanding_check_files = true; │ │ │ │ +#endif │ │ │ │ + │ │ │ │ + if (!m_add_torrent_params || !(m_add_torrent_params->flags & torrent_flags::no_verify_files)) │ │ │ │ + { │ │ │ │ + m_ses.disk_thread().async_check_files( │ │ │ │ + m_storage, m_add_torrent_params ? m_add_torrent_params.get() : nullptr │ │ │ │ + , std::move(links), [self = shared_from_this()](status_t st, storage_error const& error) │ │ │ │ + { self->on_resume_data_checked(st, error); }); │ │ │ │ +
    relevance 0../src/torrent.cpp:2715this pattern is repeated in a few places. Factor this into a function and generalize the concept of a torrent having a dedicated listen port

    this pattern is repeated in a few places. Factor this into │ │ │ │ +a function and generalize the concept of a torrent having a │ │ │ │ +dedicated listen port

    ../src/torrent.cpp:2715

    		// not ready for peers. Except, if we don't have metadata,
    │ │ │ │ +		// we need peers to download from
    │ │ │ │ +		if (!m_files_checked && valid_metadata()) return;
    │ │ │ │ +
    │ │ │ │ +		if (!m_announce_to_lsd) return;
    │ │ │ │ +
    │ │ │ │ +		// private torrents are never announced on LSD
    │ │ │ │ +		if (m_torrent_file->is_valid() && m_torrent_file->priv()) return;
    │ │ │ │ +
    │ │ │ │ +#if TORRENT_USE_I2P
    │ │ │ │ +		// i2p torrents are also never announced on LSD
    │ │ │ │ +		// unless we allow mixed swarms
    │ │ │ │ +		if (is_i2p() && !settings().get_bool(settings_pack::allow_i2p_mixed))
    │ │ │ │ +			return;
    │ │ │ │ +#endif
    │ │ │ │ +
    │ │ │ │ +		if (is_paused()) return;
    │ │ │ │ +
    │ │ │ │ +		if (!m_ses.has_lsd()) return;
    │ │ │ │ +
    │ │ │ │ +
    #ifdef TORRENT_SSL_PEERS │ │ │ │ +
    int port = is_ssl_torrent() ? m_ses.ssl_listen_port() : m_ses.listen_port(); │ │ │ │ +#else │ │ │ │ + int port = m_ses.listen_port(); │ │ │ │ +#endif │ │ │ │ + │ │ │ │ + // announce with the local discovery service │ │ │ │ + m_torrent_file->info_hashes().for_each([&](sha1_hash const& ih, protocol_version) │ │ │ │ + { │ │ │ │ + m_ses.announce_lsd(ih, port); │ │ │ │ + }); │ │ │ │ + } │ │ │ │ + │ │ │ │ +#ifndef TORRENT_DISABLE_DHT │ │ │ │ + │ │ │ │ + void torrent::dht_announce() │ │ │ │ + { │ │ │ │ + TORRENT_ASSERT(is_single_thread()); │ │ │ │ + if (!m_ses.dht()) │ │ │ │ + { │ │ │ │ +#ifndef TORRENT_DISABLE_LOGGING │ │ │ │ + debug_log("DHT: no dht initialized"); │ │ │ │ +#endif │ │ │ │ + return; │ │ │ │ + } │ │ │ │ + if (!should_announce_dht()) │ │ │ │ + { │ │ │ │ +#ifndef TORRENT_DISABLE_LOGGING │ │ │ │ + if (should_log()) │ │ │ │ + { │ │ │ │ +#if TORRENT_USE_I2P │ │ │ │ +
    relevance 0../src/torrent.cpp:3870add one peer per IP the hostname resolves to

    add one peer per IP the hostname resolves to

    ../src/torrent.cpp:3870

    	catch (...) { handle_exception(); }
    │ │ │ │ +#endif
    │ │ │ │ +
    │ │ │ │ +	void torrent::on_peer_name_lookup(error_code const& e
    │ │ │ │ +		, std::vector<address> const& host_list, int const port
    │ │ │ │ +		, protocol_version const v) try
    │ │ │ │ +	{
    │ │ │ │ +		TORRENT_ASSERT(is_single_thread());
    │ │ │ │ +
    │ │ │ │ +		INVARIANT_CHECK;
    │ │ │ │ +
    │ │ │ │ +		COMPLETE_ASYNC("torrent::on_peer_name_lookup");
    │ │ │ │ +
    │ │ │ │ +#ifndef TORRENT_DISABLE_LOGGING
    │ │ │ │ +		if (e && should_log())
    │ │ │ │ +			debug_log("peer name lookup error: %s", e.message().c_str());
    │ │ │ │ +#endif
    │ │ │ │ +
    │ │ │ │ +		if (e || m_abort || host_list.empty() || m_ses.is_aborted()) return;
    │ │ │ │ +
    │ │ │ │ +
    tcp::endpoint host(host_list.front(), std::uint16_t(port)); │ │ │ │ +
    │ │ │ │ + if (m_ip_filter && m_ip_filter->access(host.address()) & ip_filter::blocked) │ │ │ │ + { │ │ │ │ +#ifndef TORRENT_DISABLE_LOGGING │ │ │ │ + if (should_log()) │ │ │ │ + { │ │ │ │ + debug_log("blocked ip from tracker: %s", host.address().to_string().c_str()); │ │ │ │ + } │ │ │ │ +#endif │ │ │ │ + if (m_ses.alerts().should_post<peer_blocked_alert>()) │ │ │ │ + m_ses.alerts().emplace_alert<peer_blocked_alert>(get_handle() │ │ │ │ + , host, peer_blocked_alert::ip_filter); │ │ │ │ + return; │ │ │ │ + } │ │ │ │ + │ │ │ │ + if (add_peer(host, peer_info::tracker, v == protocol_version::V2 ? pex_lt_v2 : pex_flags_t(0))) │ │ │ │ + { │ │ │ │ + state_updated(); │ │ │ │ + │ │ │ │ +#ifndef TORRENT_DISABLE_LOGGING │ │ │ │ + if (should_log()) │ │ │ │ + { │ │ │ │ + debug_log("name-lookup add_peer() [ %s ] connect-candidates: %d" │ │ │ │ + , host.address().to_string().c_str() │ │ │ │ + , m_peer_list ? m_peer_list->num_connect_candidates() : -1); │ │ │ │ + } │ │ │ │ +#endif │ │ │ │ + } │ │ │ │ + update_want_peers(); │ │ │ │ + } │ │ │ │ +
    relevance 0../src/torrent.cpp:4562only do this if the piece size > 1 blocks This is a v2 torrent so we can request get block level hashes.

    only do this if the piece size > 1 blocks │ │ │ │ +This is a v2 torrent so we can request get block │ │ │ │ +level hashes.

    ../src/torrent.cpp:4562

    		{
    │ │ │ │ +			std::set<torrent_peer*> ret;
    │ │ │ │ +			if (!blocks.empty() && !downloaders.empty())
    │ │ │ │ +			{
    │ │ │ │ +				for (auto const b : blocks) ret.insert(downloaders[std::size_t(b)]);
    │ │ │ │ +			}
    │ │ │ │ +			else
    │ │ │ │ +			{
    │ │ │ │ +				std::copy(downloaders.begin(), downloaders.end(), std::inserter(ret, ret.begin()));
    │ │ │ │ +			}
    │ │ │ │ +			return ret;
    │ │ │ │ +		}();
    │ │ │ │ +
    │ │ │ │ +		// if this piece wasn't downloaded from peers, we just found it on disk.
    │ │ │ │ +		// In that case, we should just consider it as "not-have" and there's no
    │ │ │ │ +		// need to try to get higher fidelity hashes (yet)
    │ │ │ │ +		bool const found_on_disk = peers.size() == 1 && peers.count(nullptr);
    │ │ │ │ +
    │ │ │ │ +		if (!torrent_file().info_hashes().has_v1() && blocks.empty() && !found_on_disk)
    │ │ │ │ +		{
    │ │ │ │ +
    verify_block_hashes(index); │ │ │ │ +
    } │ │ │ │ + │ │ │ │ + // the below code is penalizing peers that sent use bad data. │ │ │ │ + // increase the total amount of failed bytes │ │ │ │ + if (!found_on_disk) │ │ │ │ + { │ │ │ │ + if (blocks.empty()) │ │ │ │ + add_failed_bytes(m_torrent_file->piece_size(index)); │ │ │ │ + else │ │ │ │ + add_failed_bytes(static_cast<int>(blocks.size()) * default_block_size); │ │ │ │ + │ │ │ │ +#ifndef TORRENT_DISABLE_EXTENSIONS │ │ │ │ + for (auto& ext : m_extensions) │ │ │ │ + { │ │ │ │ + ext->on_piece_failed(index); │ │ │ │ + } │ │ │ │ +#endif │ │ │ │ + │ │ │ │ + // did we receive this piece from a single peer? │ │ │ │ + // if we know exactly which blocks failed the hash, we can also be certain │ │ │ │ + // that all peers in the list sent us bad data │ │ │ │ + bool const known_bad_peer = (!found_on_disk && peers.size() == 1) || !blocks.empty(); │ │ │ │ + │ │ │ │ + penalize_peers(peers, index, known_bad_peer); │ │ │ │ + } │ │ │ │ + │ │ │ │ + // If m_storage isn't set here, it means we're shutting down │ │ │ │ + if (m_storage) │ │ │ │ + { │ │ │ │ + // it doesn't make much sense to fail to hash a piece │ │ │ │ +
    relevance 0../src/torrent.cpp:7501come up with a better way of doing this, instead of an immediately invoked lambda expression.

    come up with a better way of doing this, instead of an │ │ │ │ +immediately invoked lambda expression.

    ../src/torrent.cpp:7501

    					|| peerinfo->confirmed_supports_utp))
    │ │ │ │ +			{
    │ │ │ │ +				sm = m_ses.utp_socket_manager();
    │ │ │ │ +			}
    │ │ │ │ +
    │ │ │ │ +			// don't make a TCP connection if it's disabled
    │ │ │ │ +			if (sm == nullptr && !settings().get_bool(settings_pack::enable_outgoing_tcp))
    │ │ │ │ +			{
    │ │ │ │ +#ifndef TORRENT_DISABLE_LOGGING
    │ │ │ │ +				if (should_log())
    │ │ │ │ +				{
    │ │ │ │ +					debug_log("discarding peer \"%s\": TCP connections disabled "
    │ │ │ │ +						"[ supports-utp: %d ]", peerinfo->to_string().c_str()
    │ │ │ │ +						, peerinfo->supports_utp);
    │ │ │ │ +				}
    │ │ │ │ +#endif
    │ │ │ │ +				return false;
    │ │ │ │ +			}
    │ │ │ │ +		}
    │ │ │ │ +
    │ │ │ │ +
    aux::socket_type s = [&] { │ │ │ │ +
    │ │ │ │ +#if TORRENT_USE_I2P │ │ │ │ + if (peerinfo->is_i2p_addr) │ │ │ │ + { │ │ │ │ + // It's not entirely obvious why this peer connection is not marked as │ │ │ │ + // one. The main feature of a peer connection is that whether or not we │ │ │ │ + // proxy it is configurable. When we use i2p, we want to always prox │ │ │ │ + // everything via i2p. │ │ │ │ + │ │ │ │ + aux::proxy_settings proxy; │ │ │ │ + proxy.hostname = settings().get_str(settings_pack::i2p_hostname); │ │ │ │ + proxy.port = std::uint16_t(settings().get_int(settings_pack::i2p_port)); │ │ │ │ + proxy.type = settings_pack::i2p_proxy; │ │ │ │ + │ │ │ │ + aux::socket_type ret = instantiate_connection(m_ses.get_context() │ │ │ │ + , proxy, nullptr, nullptr, false, false); │ │ │ │ + i2p_stream& str = boost::get<i2p_stream>(ret); │ │ │ │ + str.set_local_i2p_endpoint(m_ses.local_i2p_endpoint()); │ │ │ │ + str.set_destination(static_cast<i2p_peer*>(peerinfo)->dest()); │ │ │ │ + str.set_command(i2p_stream::cmd_connect); │ │ │ │ + str.set_session_id(m_ses.i2p_session()); │ │ │ │ + return ret; │ │ │ │ + } │ │ │ │ + else │ │ │ │ +#endif │ │ │ │ + { │ │ │ │ + void* userdata = nullptr; │ │ │ │ +#ifdef TORRENT_SSL_PEERS │ │ │ │ + if (is_ssl_torrent()) │ │ │ │ + { │ │ │ │ +
    relevance 0../src/torrent.cpp:9091perhaps 0 should actually mean 0

    perhaps 0 should actually mean 0

    ../src/torrent.cpp:9091

    		// finished torrents may not change their queue positions, as it's set to
    │ │ │ │ +		// -1
    │ │ │ │ +		if ((m_abort || is_finished()) && p != no_pos) return;
    │ │ │ │ +
    │ │ │ │ +		TORRENT_ASSERT((p == no_pos) == is_finished()
    │ │ │ │ +			|| (!m_auto_managed && p == no_pos)
    │ │ │ │ +			|| (m_abort && p == no_pos)
    │ │ │ │ +			|| (!m_added && p == no_pos));
    │ │ │ │ +		if (p == m_sequence_number) return;
    │ │ │ │ +
    │ │ │ │ +		TORRENT_ASSERT(p >= no_pos);
    │ │ │ │ +
    │ │ │ │ +		state_updated();
    │ │ │ │ +
    │ │ │ │ +		m_ses.set_queue_position(this, p);
    │ │ │ │ +	}
    │ │ │ │ +
    │ │ │ │ +	void torrent::set_max_uploads(int limit, bool const state_update)
    │ │ │ │ +	{
    │ │ │ │ +		TORRENT_ASSERT(is_single_thread());
    │ │ │ │ +
    if (limit <= 0) limit = (1 << 24) - 1; │ │ │ │ +
    if (int(m_max_uploads) == limit) return; │ │ │ │ + if (state_update) state_updated(); │ │ │ │ + m_max_uploads = aux::numeric_cast<std::uint32_t>(limit); │ │ │ │ +#ifndef TORRENT_DISABLE_LOGGING │ │ │ │ + if (should_log() && state_update) │ │ │ │ + debug_log("*** set-max-uploads: %d", m_max_uploads); │ │ │ │ +#endif │ │ │ │ + │ │ │ │ + if (state_update) │ │ │ │ + set_need_save_resume(torrent_handle::if_config_changed); │ │ │ │ + } │ │ │ │ + │ │ │ │ + void torrent::set_max_connections(int limit, bool const state_update) │ │ │ │ + { │ │ │ │ + TORRENT_ASSERT(is_single_thread()); │ │ │ │ +
    relevance 0../src/torrent.cpp:9108perhaps 0 should actually mean 0

    perhaps 0 should actually mean 0

    ../src/torrent.cpp:9108

    │ │ │ │ +	void torrent::set_max_uploads(int limit, bool const state_update)
    │ │ │ │ +	{
    │ │ │ │ +		TORRENT_ASSERT(is_single_thread());
    │ │ │ │ +		if (limit <= 0) limit = (1 << 24) - 1;
    │ │ │ │ +		if (int(m_max_uploads) == limit) return;
    │ │ │ │ +		if (state_update) state_updated();
    │ │ │ │ +		m_max_uploads = aux::numeric_cast<std::uint32_t>(limit);
    │ │ │ │ +#ifndef TORRENT_DISABLE_LOGGING
    │ │ │ │ +		if (should_log() && state_update)
    │ │ │ │ +			debug_log("*** set-max-uploads: %d", m_max_uploads);
    │ │ │ │ +#endif
    │ │ │ │ +
    │ │ │ │ +		if (state_update)
    │ │ │ │ +			set_need_save_resume(torrent_handle::if_config_changed);
    │ │ │ │ +	}
    │ │ │ │ +
    │ │ │ │ +	void torrent::set_max_connections(int limit, bool const state_update)
    │ │ │ │ +	{
    │ │ │ │ +		TORRENT_ASSERT(is_single_thread());
    │ │ │ │ +
    if (limit <= 0) limit = (1 << 24) - 1; │ │ │ │ +
    if (int(m_max_connections) == limit) return; │ │ │ │ + if (state_update) state_updated(); │ │ │ │ + m_max_connections = aux::numeric_cast<std::uint32_t>(limit); │ │ │ │ + update_want_peers(); │ │ │ │ + │ │ │ │ +#ifndef TORRENT_DISABLE_LOGGING │ │ │ │ + if (should_log() && state_update) │ │ │ │ + debug_log("*** set-max-connections: %d", m_max_connections); │ │ │ │ +#endif │ │ │ │ + │ │ │ │ + if (num_peers() > int(m_max_connections)) │ │ │ │ + { │ │ │ │ + disconnect_peers(num_peers() - m_max_connections │ │ │ │ + , errors::too_many_connections); │ │ │ │ + } │ │ │ │ + │ │ │ │ + if (state_update) │ │ │ │ + set_need_save_resume(torrent_handle::if_config_changed); │ │ │ │ + } │ │ │ │ + │ │ │ │ + void torrent::set_upload_limit(int const limit) │ │ │ │ + { │ │ │ │ + set_limit_impl(limit, peer_connection::upload_channel); │ │ │ │ +#ifndef TORRENT_DISABLE_LOGGING │ │ │ │ + debug_log("*** set-upload-limit: %d", limit); │ │ │ │ +#endif │ │ │ │ + } │ │ │ │ + │ │ │ │ + void torrent::set_download_limit(int const limit) │ │ │ │ + { │ │ │ │ +
    relevance 0../src/torrent.cpp:11034instead of resorting the whole list, insert the peers directly into the right place

    instead of resorting the whole list, insert the peers │ │ │ │ +directly into the right place

    ../src/torrent.cpp:11034

    				std::printf("timed out [average-piece-time: %d ms ]\n"
    │ │ │ │ +					, m_average_piece_time);
    │ │ │ │ +#endif
    │ │ │ │ +			}
    │ │ │ │ +
    │ │ │ │ +			// pick all blocks for this piece. the peers list is kept up to date
    │ │ │ │ +			// and sorted. when we issue a request to a peer, its download queue
    │ │ │ │ +			// time will increase and it may need to be bumped in the peers list,
    │ │ │ │ +			// since it's ordered by download queue time
    │ │ │ │ +			pick_time_critical_block(peers, ignore_peers
    │ │ │ │ +				, peers_with_requests
    │ │ │ │ +				, pi, &i, m_picker.get()
    │ │ │ │ +				, blocks_in_piece, timed_out);
    │ │ │ │ +
    │ │ │ │ +			// put back the peers we ignored into the peer list for the next piece
    │ │ │ │ +			if (!ignore_peers.empty())
    │ │ │ │ +			{
    │ │ │ │ +				peers.insert(peers.begin(), ignore_peers.begin(), ignore_peers.end());
    │ │ │ │ +				ignore_peers.clear();
    │ │ │ │ +
    │ │ │ │ +
    std::sort(peers.begin(), peers.end() │ │ │ │ +
    , [] (peer_connection const* lhs, peer_connection const* rhs) │ │ │ │ + { return lhs->download_queue_time(16*1024) < rhs->download_queue_time(16*1024); }); │ │ │ │ + } │ │ │ │ + │ │ │ │ + // if this peer's download time exceeds 2 seconds, we're done. │ │ │ │ + // We don't want to build unreasonably long request queues │ │ │ │ + if (!peers.empty() && peers[0]->download_queue_time() > milliseconds(2000)) │ │ │ │ + break; │ │ │ │ + } │ │ │ │ + │ │ │ │ + // commit all the time critical requests │ │ │ │ + for (auto p : peers_with_requests) │ │ │ │ + { │ │ │ │ + p->send_block_requests(); │ │ │ │ + } │ │ │ │ + } │ │ │ │ +#endif // TORRENT_DISABLE_STREAMING │ │ │ │ + │ │ │ │ + std::set<std::string> torrent::web_seeds(web_seed_entry::type_t const type) const │ │ │ │ + { │ │ │ │ + TORRENT_ASSERT(is_single_thread()); │ │ │ │ + std::set<std::string> ret; │ │ │ │ + for (auto const& s : m_web_seeds) │ │ │ │ + { │ │ │ │ + if (s.peer_info.banned) continue; │ │ │ │ + if (s.removed) continue; │ │ │ │ + if (s.type != type) continue; │ │ │ │ + ret.insert(s.url); │ │ │ │ + } │ │ │ │ + return ret; │ │ │ │ +
    relevance 0../src/random.cpp:141improve calling RAND_bytes multiple times, using fallback for now

    improve calling RAND_bytes multiple times, using fallback for now

    ../src/random.cpp:141

    #else
    │ │ │ │ +			std::generate(buffer.begin(), buffer.end(), [] { return char(random(0xff)); });
    │ │ │ │ +#endif
    │ │ │ │ +		}
    │ │ │ │ +
    │ │ │ │ +		void crypto_random_bytes(span<char> buffer)
    │ │ │ │ +		{
    │ │ │ │ +#ifdef TORRENT_BUILD_SIMULATOR
    │ │ │ │ +			// In the simulator we want deterministic random numbers
    │ │ │ │ +			std::generate(buffer.begin(), buffer.end(), [] { return char(random(0xff)); });
    │ │ │ │ +#elif TORRENT_USE_CNG
    │ │ │ │ +			aux::cng_gen_random(buffer);
    │ │ │ │ +#elif TORRENT_USE_CRYPTOAPI
    │ │ │ │ +			// windows
    │ │ │ │ +			aux::crypt_gen_random(buffer);
    │ │ │ │ +#elif defined TORRENT_USE_LIBCRYPTO && !defined TORRENT_USE_WOLFSSL
    │ │ │ │ +// wolfSSL uses wc_RNG_GenerateBlock as the internal function for the
    │ │ │ │ +// openssl compatibility layer. This function API does not support
    │ │ │ │ +// an arbitrary buffer size (openssl does), it is limited by the
    │ │ │ │ +// constant RNG_MAX_BLOCK_LEN.
    │ │ │ │ +
    │ │ │ │ +
    // openssl │ │ │ │ + int r = RAND_bytes(reinterpret_cast<unsigned char*>(buffer.data()) │ │ │ │ + , int(buffer.size())); │ │ │ │ + if (r != 1) aux::throw_ex<system_error>(errors::no_entropy); │ │ │ │ +#elif TORRENT_USE_GETRANDOM │ │ │ │ + ssize_t const r = ::getrandom(buffer.data(), static_cast<std::size_t>(buffer.size()), 0); │ │ │ │ + if (r == ssize_t(buffer.size())) return; │ │ │ │ + if (r == -1 && errno != ENOSYS) aux::throw_ex<system_error>(error_code(errno, generic_category())); │ │ │ │ + static dev_random dev; │ │ │ │ + dev.read(buffer); │ │ │ │ +#elif TORRENT_USE_DEV_RANDOM │ │ │ │ + static dev_random dev; │ │ │ │ + dev.read(buffer); │ │ │ │ +#else │ │ │ │ + │ │ │ │ +#if TORRENT_BROKEN_RANDOM_DEVICE │ │ │ │ + // even pseudo random numbers rely on being able to seed the random │ │ │ │ + // generator │ │ │ │ +#error "no entropy source available" │ │ │ │ +#else │ │ │ │ +#ifdef TORRENT_I_WANT_INSECURE_RANDOM_NUMBERS │ │ │ │ + std::generate(buffer.begin(), buffer.end(), [] { return char(random(0xff)); }); │ │ │ │ +#else │ │ │ │ +#error "no secure entropy source available. If you really want insecure random numbers, define TORRENT_I_WANT_INSECURE_RANDOM_NUMBERS" │ │ │ │ +#endif │ │ │ │ +#endif │ │ │ │ + │ │ │ │ +#endif │ │ │ │ + } │ │ │ │ +} │ │ │ │ +
    relevance 0../src/magnet_uri.cpp:439what's the right number here?

    what's the right number here?

    ../src/magnet_uri.cpp:439

    			}
    │ │ │ │ +			else if (string_equal_no_case(name, "so"_sv)) // select-only (files)
    │ │ │ │ +			{
    │ │ │ │ +				// accept only digits, '-' and ','
    │ │ │ │ +				if (std::any_of(value.begin(), value.end(), [](char c)
    │ │ │ │ +					{ return !is_digit(c) && c != '-' && c != ','; }))
    │ │ │ │ +					continue;
    │ │ │ │ +
    │ │ │ │ +				// make sure all file priorities are set to 0, except the ones
    │ │ │ │ +				// we specify in the file_priorities
    │ │ │ │ +				p.flags |= torrent_flags::default_dont_download;
    │ │ │ │ +
    │ │ │ │ +				do
    │ │ │ │ +				{
    │ │ │ │ +					string_view token;
    │ │ │ │ +					std::tie(token, value) = split_string(value, ',');
    │ │ │ │ +
    │ │ │ │ +					if (token.empty()) continue;
    │ │ │ │ +
    │ │ │ │ +					int idx1, idx2;
    │ │ │ │ +
    constexpr int max_index = 10000; // can't risk out of memory │ │ │ │ +
    │ │ │ │ + auto const divider = token.find_first_of('-'); │ │ │ │ + if (divider != std::string::npos) // it's a range │ │ │ │ + { │ │ │ │ + if (divider == 0) // no start index │ │ │ │ + continue; │ │ │ │ + if (divider == token.size() - 1) // no end index │ │ │ │ + continue; │ │ │ │ + │ │ │ │ + idx1 = std::atoi(token.substr(0, divider).to_string().c_str()); │ │ │ │ + if (idx1 < 0 || idx1 > max_index) // invalid index │ │ │ │ + continue; │ │ │ │ + idx2 = std::atoi(token.substr(divider + 1).to_string().c_str()); │ │ │ │ + if (idx2 < 0 || idx2 > max_index) // invalid index │ │ │ │ + continue; │ │ │ │ + │ │ │ │ + if (idx1 > idx2) // wrong range limits │ │ │ │ + continue; │ │ │ │ + } │ │ │ │ + else // it's an index │ │ │ │ + { │ │ │ │ + idx1 = std::atoi(token.to_string().c_str()); │ │ │ │ + if (idx1 < 0 || idx1 > max_index) // invalid index │ │ │ │ + continue; │ │ │ │ + idx2 = idx1; │ │ │ │ + } │ │ │ │ + │ │ │ │ + if (int(p.file_priorities.size()) <= idx2) │ │ │ │ + p.file_priorities.resize(static_cast<std::size_t>(idx2) + 1, dont_download); │ │ │ │ + │ │ │ │ +
    relevance 0../src/udp_tracker_connection.cpp:633why is this a linked list?

    why is this a linked list?

    ../src/udp_tracker_connection.cpp:633

    				ipv6_peer_entry e{};
    │ │ │ │ +				std::memcpy(e.ip.data(), buf.data(), 16);
    │ │ │ │ +				buf = buf.subspan(16);
    │ │ │ │ +				e.port = aux::read_uint16(buf);
    │ │ │ │ +				resp.peers6.push_back(e);
    │ │ │ │ +			}
    │ │ │ │ +		}
    │ │ │ │ +		else
    │ │ │ │ +		{
    │ │ │ │ +			resp.peers4.reserve(static_cast<std::size_t>(num_peers));
    │ │ │ │ +			for (int i = 0; i < num_peers; ++i)
    │ │ │ │ +			{
    │ │ │ │ +				ipv4_peer_entry e{};
    │ │ │ │ +				std::memcpy(e.ip.data(), buf.data(), 4);
    │ │ │ │ +				buf = buf.subspan(4);
    │ │ │ │ +				e.port = aux::read_uint16(buf);
    │ │ │ │ +				resp.peers4.push_back(e);
    │ │ │ │ +			}
    │ │ │ │ +		}
    │ │ │ │ +
    │ │ │ │ +
    std::list<address> ip_list; │ │ │ │ +
    std::transform(m_endpoints.begin(), m_endpoints.end(), std::back_inserter(ip_list) │ │ │ │ + , [](tcp::endpoint const& ep) { return ep.address(); } ); │ │ │ │ + │ │ │ │ + cb->tracker_response(tracker_req(), m_target.address(), ip_list, resp); │ │ │ │ + │ │ │ │ + close(); │ │ │ │ + return true; │ │ │ │ + } │ │ │ │ + │ │ │ │ + bool udp_tracker_connection::on_scrape_response(span<char const> buf) │ │ │ │ + { │ │ │ │ + restart_read_timeout(); │ │ │ │ + auto const action = static_cast<action_t>(aux::read_int32(buf)); │ │ │ │ + std::uint32_t const transaction = aux::read_uint32(buf); │ │ │ │ + │ │ │ │ + if (transaction != m_transaction_id) │ │ │ │ + { │ │ │ │ + fail(error_code(errors::invalid_tracker_transaction_id), operation_t::bittorrent); │ │ │ │ + return false; │ │ │ │ + } │ │ │ │ + │ │ │ │ + if (action == action_t::error) │ │ │ │ + { │ │ │ │ + fail(error_code(errors::tracker_failure), operation_t::bittorrent │ │ │ │ + , std::string(buf.data(), static_cast<std::size_t>(buf.size())).c_str()); │ │ │ │ + return true; │ │ │ │ + } │ │ │ │ + │ │ │ │ + if (action != action_t::scrape) │ │ │ │ + { │ │ │ │ +
    relevance 0../src/piece_picker.cpp:121find a better place for this

    find a better place for this

    ../src/piece_picker.cpp:121

    			if (limit == 0)
    │ │ │ │  			{
    │ │ │ │  				std::cerr << " ...";
    │ │ │ │  				break;
    │ │ │ │  			}
    │ │ │ │  			if (*i == -1) break;
    │ │ │ │  			while (j != p.m_priority_boundaries.end() && *j <= index)
    │ │ │ │  			{
    │ │ │ │ @@ -9541,15 +8841,15 @@
    │ │ │ │  	constexpr int max_piece_affinity_extent = 4 * 1024 * 1024 / default_block_size;
    │ │ │ │  
    │ │ │ │  	piece_picker::piece_picker(std::int64_t const total_size, int const piece_size)
    │ │ │ │  		: m_priority_boundaries(1, m_pieces.end_index())
    │ │ │ │  	{
    │ │ │ │  		TORRENT_ASSERT(total_size > 0);
    │ │ │ │  		TORRENT_ASSERT(piece_size > 0);
    │ │ │ │ -
    relevance 0../src/piece_picker.cpp:2074this could probably be optimized by incrementally calling partial_sort to sort one more element in the list. Because chances are that we'll just need a single piece, and once we've picked from it we're done. Sorting the rest of the list in that case is a waste of time.

    this could probably be optimized by incrementally │ │ │ │ +relevance 0../src/piece_picker.cpp:2074this could probably be optimized by incrementally calling partial_sort to sort one more element in the list. Because chances are that we'll just need a single piece, and once we've picked from it we're done. Sorting the rest of the list in that case is a waste of time.

    this could probably be optimized by incrementally │ │ │ │ calling partial_sort to sort one more element in the list. Because │ │ │ │ chances are that we'll just need a single piece, and once we've │ │ │ │ picked from it we're done. Sorting the rest of the list in that │ │ │ │ case is a waste of time.

    ../src/piece_picker.cpp:2074

    			// now, copy over the pointers. We also apply a filter here to not
    │ │ │ │  			// include ineligible pieces in certain modes. For instance, a piece
    │ │ │ │  			// that the current peer doesn't have is not included.
    │ │ │ │  			for (auto& dp : m_downloads[piece_pos::piece_downloading])
    │ │ │ │ @@ -9596,15 +8896,15 @@
    │ │ │ │  			if (num_blocks <= 0) return ret;
    │ │ │ │  		}
    │ │ │ │  
    │ │ │ │  		if (!suggested_pieces.empty())
    │ │ │ │  		{
    │ │ │ │  			for (piece_index_t i : suggested_pieces)
    │ │ │ │  			{
    │ │ │ │ -
    relevance 0../src/piece_picker.cpp:2218Is it a good idea that this affinity takes precedence over piece priority?

    Is it a good idea that this affinity takes precedence over │ │ │ │ +relevance 0../src/piece_picker.cpp:2218Is it a good idea that this affinity takes precedence over piece priority?

    Is it a good idea that this affinity takes precedence over │ │ │ │ piece priority?

    ../src/piece_picker.cpp:2218

    					prio_index_t const end = priority_end(i);
    │ │ │ │  					for (prio_index_t p = prev(end); p >= start; --p)
    │ │ │ │  					{
    │ │ │ │  						pc.inc_stats_counter(counters::piece_picker_reverse_rare_loops);
    │ │ │ │  
    │ │ │ │  						if (!is_piece_free(m_pieces[p], pieces)) continue;
    │ │ │ │  
    │ │ │ │ @@ -9648,15 +8948,15 @@
    │ │ │ │  								return ret;
    │ │ │ │  							}
    │ │ │ │  						}
    │ │ │ │  						// if we have all pieces belonging to this extent, remove it
    │ │ │ │  						if (have_all) to_erase = idx;
    │ │ │ │  					}
    │ │ │ │  					if (to_erase != -1) m_recent_extents.erase(m_recent_extents.begin() + to_erase);
    │ │ │ │ -
    relevance 0../src/piece_picker.cpp:2572when expanding pieces for cache stripe reasons, the !downloading condition doesn't make much sense

    when expanding pieces for cache stripe reasons, │ │ │ │ +relevance 0../src/piece_picker.cpp:2572when expanding pieces for cache stripe reasons, the !downloading condition doesn't make much sense

    when expanding pieces for cache stripe reasons, │ │ │ │ the !downloading condition doesn't make much sense

    ../src/piece_picker.cpp:2572

    		TORRENT_ASSERT(index < m_piece_map.end_index());
    │ │ │ │  		if (next(index) == m_piece_map.end_index())
    │ │ │ │  			return m_blocks_in_last_piece;
    │ │ │ │  		else
    │ │ │ │  			return blocks_per_piece();
    │ │ │ │  	}
    │ │ │ │  
    │ │ │ │ @@ -9695,15 +8995,15 @@
    │ │ │ │  		}
    │ │ │ │  	}
    │ │ │ │  
    │ │ │ │  	// the first bool is true if this is the only peer that has requested and downloaded
    │ │ │ │  	// blocks from this piece.
    │ │ │ │  	// the second bool is true if this is the only active peer that is requesting
    │ │ │ │  	// and downloading blocks from this piece. Active means having a connection.
    │ │ │ │ -
    relevance 0../src/piece_picker.cpp:3150should 5 be configurable?

    should 5 be configurable?

    ../src/piece_picker.cpp:3150

    		bool have_all = true;
    │ │ │ │ +
    relevance 0../src/piece_picker.cpp:3150should 5 be configurable?

    should 5 be configurable?

    ../src/piece_picker.cpp:3150

    		bool have_all = true;
    │ │ │ │  
    │ │ │ │  		for (auto const piece : extent_for(this_extent))
    │ │ │ │  		{
    │ │ │ │  			if (piece == p) continue;
    │ │ │ │  
    │ │ │ │  			if (!m_piece_map[piece].have()) have_all = false;
    │ │ │ │  
    │ │ │ │ @@ -9746,66 +9046,276 @@
    │ │ │ │  		TORRENT_ASSERT(!m_piece_map[block.piece_index].have());
    │ │ │ │  
    │ │ │ │  		piece_pos& p = m_piece_map[block.piece_index];
    │ │ │ │  		if (p.download_queue() == piece_pos::piece_open)
    │ │ │ │  		{
    │ │ │ │  #ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS
    │ │ │ │  			INVARIANT_CHECK;
    │ │ │ │ -
    relevance 0../src/torrent_peer.cpp:181how do we deal with our external address changing?

    how do we deal with our external address changing?

    ../src/torrent_peer.cpp:181

    		// connections. If it fails, we'll
    │ │ │ │ -		// retry with encryption
    │ │ │ │ -		, pe_support(false)
    │ │ │ │ -#endif
    │ │ │ │ -		, is_v6_addr(false)
    │ │ │ │ -#if TORRENT_USE_I2P
    │ │ │ │ -		, is_i2p_addr(false)
    │ │ │ │ -#endif
    │ │ │ │ -		, on_parole(false)
    │ │ │ │ -		, banned(false)
    │ │ │ │ -		, supports_utp(true) // assume peers support utp
    │ │ │ │ -		, confirmed_supports_utp(false)
    │ │ │ │ -		, supports_holepunch(false)
    │ │ │ │ -		, web_seed(false)
    │ │ │ │ -		, protocol_v2(false)
    │ │ │ │ -	{}
    │ │ │ │ +
    relevance 0../src/storage_utils.cpp:230ideally, if we end up copying files because of a move across volumes, the source should not be deleted until they've all been copied. That would let us rollback with higher confidence.

    ideally, if we end up copying files because of a move across │ │ │ │ +volumes, the source should not be deleted until they've all been │ │ │ │ +copied. That would let us rollback with higher confidence.

    ../src/storage_utils.cpp:230

    		// later
    │ │ │ │ +		aux::vector<bool, file_index_t> copied_files(std::size_t(f.num_files()), false);
    │ │ │ │  
    │ │ │ │ -	std::uint32_t torrent_peer::rank(external_ip const& external, int external_port) const
    │ │ │ │ -	{
    │ │ │ │ -		TORRENT_ASSERT(in_use);
    │ │ │ │ -
    if (peer_rank == 0) │ │ │ │ -
    peer_rank = peer_priority( │ │ │ │ - tcp::endpoint(external.external_address(this->address()), std::uint16_t(external_port)) │ │ │ │ - , tcp::endpoint(this->address(), this->port)); │ │ │ │ - return peer_rank; │ │ │ │ + // track how far we got in case of an error │ │ │ │ + file_index_t file_index{}; │ │ │ │ + for (auto const i : f.file_range()) │ │ │ │ + { │ │ │ │ + // files moved out to absolute paths are not moved │ │ │ │ + if (f.file_absolute_path(i)) continue; │ │ │ │ + │ │ │ │ + std::string const old_path = combine_path(save_path, f.file_path(i)); │ │ │ │ + std::string const new_path = combine_path(new_save_path, f.file_path(i)); │ │ │ │ + │ │ │ │ + error_code ignore; │ │ │ │ + if (flags == move_flags_t::dont_replace && exists(new_path, ignore)) │ │ │ │ + { │ │ │ │ + if (ret == status_t::no_error) ret = status_t::need_full_check; │ │ │ │ + continue; │ │ │ │ + } │ │ │ │ + │ │ │ │ +
    move_file(old_path, new_path, ec); │ │ │ │ +
    │ │ │ │ + // if the source file doesn't exist. That's not a problem │ │ │ │ + // we just ignore that file │ │ │ │ + if (ec.ec == boost::system::errc::no_such_file_or_directory) │ │ │ │ + ec.ec.clear(); │ │ │ │ + else if (ec │ │ │ │ + && ec.ec != boost::system::errc::invalid_argument │ │ │ │ + && ec.ec != boost::system::errc::permission_denied) │ │ │ │ + { │ │ │ │ + // moving the file failed │ │ │ │ + // on OSX, the error when trying to rename a file across different │ │ │ │ + // volumes is EXDEV, which will make it fall back to copying. │ │ │ │ + ec.ec.clear(); │ │ │ │ + copy_file(old_path, new_path, ec); │ │ │ │ + if (!ec) copied_files[i] = true; │ │ │ │ + } │ │ │ │ + │ │ │ │ + if (ec) │ │ │ │ + { │ │ │ │ + ec.file(i); │ │ │ │ + file_index = i; │ │ │ │ + break; │ │ │ │ + } │ │ │ │ + } │ │ │ │ + │ │ │ │ + if (!ec && move_partfile) │ │ │ │ + { │ │ │ │ + error_code e; │ │ │ │ + move_partfile(new_save_path, e); │ │ │ │ + if (e) │ │ │ │ +
    relevance 0../src/storage_utils.cpp:538it would seem reasonable to, instead, set the have_pieces bits for the pieces representing these files, and resume with the normal logic

    it would seem reasonable to, instead, set the have_pieces bits │ │ │ │ +for the pieces representing these files, and resume with the normal │ │ │ │ +logic

    ../src/storage_utils.cpp:538

    					continue;
    │ │ │ │ +
    │ │ │ │ +				std::int64_t const size = get_filesize(stat, file_index, fs
    │ │ │ │ +					, save_path, ec);
    │ │ │ │ +				if (size < 0) return false;
    │ │ │ │ +
    │ │ │ │ +				if (size < fs.file_size(file_index))
    │ │ │ │ +				{
    │ │ │ │ +					ec.ec = errors::mismatching_file_size;
    │ │ │ │ +					ec.file(file_index);
    │ │ │ │ +					ec.operation = operation_t::check_resume;
    │ │ │ │ +					return false;
    │ │ │ │ +				}
    │ │ │ │ +			}
    │ │ │ │ +			return true;
    │ │ │ │ +		}
    │ │ │ │ +
    │ │ │ │ +#ifndef TORRENT_DISABLE_MUTABLE_TORRENTS
    │ │ │ │ +		// always trigger a full recheck when we pull in files from other
    │ │ │ │ +		// torrents, via hard links
    │ │ │ │ +
    if (added_files) return false; │ │ │ │ +
    #endif │ │ │ │ + │ │ │ │ + // parse have bitmask. Verify that the files we expect to have │ │ │ │ + // actually do exist │ │ │ │ + piece_index_t const end_piece = std::min(rd.have_pieces.end_index(), fs.end_piece()); │ │ │ │ + for (piece_index_t i(0); i < end_piece; ++i) │ │ │ │ + { │ │ │ │ + if (rd.have_pieces.get_bit(i) == false) continue; │ │ │ │ + │ │ │ │ + std::vector<file_slice> f = fs.map_block(i, 0, 1); │ │ │ │ + TORRENT_ASSERT(!f.empty()); │ │ │ │ + │ │ │ │ + file_index_t const file_index = f[0].file_index; │ │ │ │ + │ │ │ │ + // files with priority zero may not have been saved to disk at their │ │ │ │ + // expected location, but is likely to be in a partfile. Just exempt it │ │ │ │ + // from checking │ │ │ │ + if (file_index < file_priority.end_index() │ │ │ │ + && file_priority[file_index] == dont_download) │ │ │ │ + continue; │ │ │ │ + │ │ │ │ + if (fs.pad_file_at(file_index)) continue; │ │ │ │ + │ │ │ │ + if (get_filesize(stat, file_index, fs, save_path, ec) < 0) │ │ │ │ + return false; │ │ │ │ + │ │ │ │ + // OK, this file existed, good. Now, skip all remaining pieces in │ │ │ │ + // this file. We're just sanity-checking whether the files exist │ │ │ │ + // or not. │ │ │ │ + peer_request const pr = fs.map_file(file_index │ │ │ │ +
    relevance 0../src/peer_connection.cpp:1091this should be the global download rate

    this should be the global download rate

    ../src/peer_connection.cpp:1091

    │ │ │ │ +		int rate = 0;
    │ │ │ │ +
    │ │ │ │ +		// if we haven't received any data recently, the current download rate
    │ │ │ │ +		// is not representative
    │ │ │ │ +		if (aux::time_now() - m_last_piece.get(m_connect) > seconds(30) && m_download_rate_peak > 0)
    │ │ │ │ +		{
    │ │ │ │ +			rate = m_download_rate_peak;
    │ │ │ │ +		}
    │ │ │ │ +		else if (aux::time_now() - m_last_unchoked.get(m_connect) < seconds(5)
    │ │ │ │ +			&& m_statistics.total_payload_upload() < 2 * 0x4000)
    │ │ │ │ +		{
    │ │ │ │ +			// if we're have only been unchoked for a short period of time,
    │ │ │ │ +			// we don't know what rate we can get from this peer. Instead of assuming
    │ │ │ │ +			// the lowest possible rate, assume the average.
    │ │ │ │ +
    │ │ │ │ +			int peers_with_requests = int(stats_counters()[counters::num_peers_down_requests]);
    │ │ │ │ +			// avoid division by 0
    │ │ │ │ +			if (peers_with_requests == 0) peers_with_requests = 1;
    │ │ │ │ +
    │ │ │ │ +
    rate = t->statistics().transfer_rate(stat::download_payload) / peers_with_requests; │ │ │ │ +
    } │ │ │ │ + else │ │ │ │ + { │ │ │ │ + // current download rate in bytes per seconds │ │ │ │ + rate = m_statistics.transfer_rate(stat::download_payload); │ │ │ │ + } │ │ │ │ + │ │ │ │ + // avoid division by zero │ │ │ │ + if (rate < 50) rate = 50; │ │ │ │ + │ │ │ │ + // average of current rate and peak │ │ │ │ +// rate = (rate + m_download_rate_peak) / 2; │ │ │ │ + │ │ │ │ + return milliseconds((m_outstanding_bytes + extra_bytes │ │ │ │ + + m_queued_time_critical * t->block_size() * 1000) / rate); │ │ │ │ } │ │ │ │ │ │ │ │ -#ifndef TORRENT_DISABLE_LOGGING │ │ │ │ - std::string torrent_peer::to_string() const │ │ │ │ + void peer_connection::add_stat(std::int64_t const downloaded, std::int64_t const uploaded) │ │ │ │ { │ │ │ │ - TORRENT_ASSERT(in_use); │ │ │ │ -#if TORRENT_USE_I2P │ │ │ │ - if (is_i2p_addr) return dest().to_string(); │ │ │ │ -#endif // TORRENT_USE_I2P │ │ │ │ - return address().to_string(); │ │ │ │ + TORRENT_ASSERT(is_single_thread()); │ │ │ │ + m_statistics.add_stat(downloaded, uploaded); │ │ │ │ } │ │ │ │ -#endif │ │ │ │ │ │ │ │ - std::int64_t torrent_peer::total_download() const │ │ │ │ + sha1_hash peer_connection::associated_info_hash() const │ │ │ │ { │ │ │ │ - TORRENT_ASSERT(in_use); │ │ │ │ - if (connection != nullptr) │ │ │ │ - { │ │ │ │ - TORRENT_ASSERT(prev_amount_download == 0); │ │ │ │ - return connection->statistics().total_payload_download(); │ │ │ │ - } │ │ │ │ - else │ │ │ │ + std::shared_ptr<torrent> t = associated_torrent().lock(); │ │ │ │ + TORRENT_ASSERT(t); │ │ │ │ + auto const& ih = t->info_hash(); │ │ │ │ + // if protocol_v2 is set on the peer, this better be a v2 torrent, │ │ │ │ + // otherwise something isn't right │ │ │ │ +
    relevance 0../src/peer_connection.cpp:3520sort the allowed fast set in priority order

    sort the allowed fast set in priority order

    ../src/peer_connection.cpp:3520

    │ │ │ │ +		// if the peer has the piece and we want
    │ │ │ │ +		// to download it, request it
    │ │ │ │ +		if (index < m_have_piece.end_index()
    │ │ │ │ +			&& m_have_piece[index]
    │ │ │ │ +			&& !t->has_piece_passed(index)
    │ │ │ │ +			&& t->valid_metadata()
    │ │ │ │ +			&& t->has_picker()
    │ │ │ │ +			&& t->picker().piece_priority(index) > dont_download)
    │ │ │ │  		{
    │ │ │ │ -			return std::int64_t(prev_amount_download) << 10;
    │ │ │ │ +			t->peer_is_interesting(*this);
    │ │ │ │  		}
    │ │ │ │  	}
    │ │ │ │ -
    relevance 0../src/session_handle.cpp:485in C++14, use unique_ptr and move it into the lambda

    in C++14, use unique_ptr and move it into the lambda

    ../src/session_handle.cpp:485

    		async_add_torrent(add_torrent_params(params));
    │ │ │ │ +
    │ │ │ │ +	std::vector<piece_index_t> const& peer_connection::allowed_fast()
    │ │ │ │ +	{
    │ │ │ │ +		TORRENT_ASSERT(is_single_thread());
    │ │ │ │ +		std::shared_ptr<torrent> t = m_torrent.lock();
    │ │ │ │ +		TORRENT_ASSERT(t);
    │ │ │ │ +
    │ │ │ │ +
    return m_allowed_fast; │ │ │ │ +
    } │ │ │ │ + │ │ │ │ + bool peer_connection::can_request_time_critical() const │ │ │ │ + { │ │ │ │ + TORRENT_ASSERT(is_single_thread()); │ │ │ │ + if (has_peer_choked() || !is_interesting()) return false; │ │ │ │ + if (int(m_download_queue.size()) + int(m_request_queue.size()) │ │ │ │ + > m_desired_queue_size * 2) return false; │ │ │ │ + if (on_parole()) return false; │ │ │ │ + if (m_disconnecting) return false; │ │ │ │ + std::shared_ptr<torrent> t = m_torrent.lock(); │ │ │ │ + TORRENT_ASSERT(t); │ │ │ │ + if (t->upload_mode()) return false; │ │ │ │ + │ │ │ │ + // ignore snubbed peers, since they're not likely to return pieces in a │ │ │ │ + // timely manner anyway │ │ │ │ + if (m_snubbed) return false; │ │ │ │ + return true; │ │ │ │ + } │ │ │ │ + │ │ │ │ + bool peer_connection::make_time_critical(piece_block const& block) │ │ │ │ + { │ │ │ │ + TORRENT_ASSERT(is_single_thread()); │ │ │ │ + auto const rit = std::find_if(m_request_queue.begin() │ │ │ │ + , m_request_queue.end(), aux::has_block(block)); │ │ │ │ + if (rit == m_request_queue.end()) return false; │ │ │ │ +#if TORRENT_USE_ASSERTS │ │ │ │ + std::shared_ptr<torrent> t = m_torrent.lock(); │ │ │ │ + TORRENT_ASSERT(t); │ │ │ │ + TORRENT_ASSERT(t->has_picker()); │ │ │ │ +
    relevance 0../src/http_seed_connection.cpp:441technically, this isn't supposed to happen, but it seems to sometimes. Some of the accounting is probably wrong in certain cases

    technically, this isn't supposed to happen, but it seems to │ │ │ │ +sometimes. Some of the accounting is probably wrong in certain │ │ │ │ +cases

    ../src/http_seed_connection.cpp:441

    					// cut out the chunk header from the receive buffer
    │ │ │ │ +					TORRENT_ASSERT(m_chunk_pos + m_body_start < INT_MAX);
    │ │ │ │ +					m_recv_buffer.cut(header_size, t->block_size() + 1024, aux::numeric_cast<int>(m_chunk_pos + m_body_start));
    │ │ │ │ +					recv_buffer = m_recv_buffer.get();
    │ │ │ │ +					recv_buffer = recv_buffer.subspan(m_body_start);
    │ │ │ │ +					m_chunk_pos += chunk_size;
    │ │ │ │ +					if (chunk_size == 0)
    │ │ │ │ +					{
    │ │ │ │ +						TORRENT_ASSERT(m_recv_buffer.get().size() < m_chunk_pos + m_body_start + 1
    │ │ │ │ +							|| m_recv_buffer.get()[static_cast<std::ptrdiff_t>(m_chunk_pos + m_body_start)] == 'H'
    │ │ │ │ +							|| (m_parser.chunked_encoding()
    │ │ │ │ +								&& m_recv_buffer.get()[static_cast<std::ptrdiff_t>(m_chunk_pos + m_body_start)] == '\r'));
    │ │ │ │ +						m_chunk_pos = -1;
    │ │ │ │ +					}
    │ │ │ │ +				}
    │ │ │ │ +			}
    │ │ │ │ +
    │ │ │ │ +			int payload = int(bytes_transferred);
    │ │ │ │ +			if (payload > m_response_left) payload = int(m_response_left);
    │ │ │ │ +			if (payload > front_request.length) payload = front_request.length;
    │ │ │ │ +
    if (payload > outstanding_bytes()) payload = outstanding_bytes(); │ │ │ │ +
    received_bytes(payload, 0); │ │ │ │ + incoming_piece_fragment(payload); │ │ │ │ + m_response_left -= payload; │ │ │ │ + │ │ │ │ + if (m_parser.status_code() == 503) │ │ │ │ + { │ │ │ │ + if (!m_parser.finished()) return; │ │ │ │ + │ │ │ │ + int retry_time = std::atoi(std::string(recv_buffer.begin(), recv_buffer.end()).c_str()); │ │ │ │ + if (retry_time <= 0) retry_time = 60; │ │ │ │ +#ifndef TORRENT_DISABLE_LOGGING │ │ │ │ + peer_log(peer_log_alert::info, "CONNECT", "retrying in %d seconds", retry_time); │ │ │ │ +#endif │ │ │ │ + │ │ │ │ + received_bytes(0, int(bytes_transferred)); │ │ │ │ + // temporarily unavailable, retry later │ │ │ │ + t->retry_web_seed(this, seconds32(retry_time)); │ │ │ │ + disconnect(error_code(m_parser.status_code(), http_category()), operation_t::bittorrent, failure); │ │ │ │ + return; │ │ │ │ + } │ │ │ │ + │ │ │ │ + │ │ │ │ + // we only received the header, no data │ │ │ │ + if (recv_buffer.empty()) break; │ │ │ │ + │ │ │ │ + if (recv_buffer.size() < front_request.length) break; │ │ │ │ + │ │ │ │ + // if the response is chunked, we need to receive the last │ │ │ │ + // terminating chunk and the tail headers before we can proceed │ │ │ │ + if (m_parser.chunked_encoding() && m_chunk_pos >= 0) break; │ │ │ │ +
    relevance 0../src/session_handle.cpp:485in C++14, use unique_ptr and move it into the lambda

    in C++14, use unique_ptr and move it into the lambda

    ../src/session_handle.cpp:485

    		async_add_torrent(add_torrent_params(params));
    │ │ │ │  	}
    │ │ │ │  
    │ │ │ │  	void session_handle::async_add_torrent(add_torrent_params&& params)
    │ │ │ │  	{
    │ │ │ │  		TORRENT_ASSERT_PRECOND(!params.save_path.empty());
    │ │ │ │  
    │ │ │ │  #if TORRENT_ABI_VERSION < 3
    │ │ │ │ @@ -9848,267 +9358,556 @@
    │ │ │ │  		p.save_path = save_path;
    │ │ │ │  		if (resume_data.type() != entry::undefined_t)
    │ │ │ │  		{
    │ │ │ │  			bencode(std::back_inserter(p.resume_data), resume_data);
    │ │ │ │  		}
    │ │ │ │  		p.storage_mode = storage_mode;
    │ │ │ │  		if (add_paused) p.flags |= add_torrent_params::flag_paused;
    │ │ │ │ -
    relevance 0../src/torrent_handle.cpp:589support moving files into this call

    support moving files into this call

    ../src/torrent_handle.cpp:589

    		auto retp = &prio;
    │ │ │ │ -		sync_call(&torrent::piece_priorities, retp);
    │ │ │ │ -		std::vector<int> ret;
    │ │ │ │ -		ret.reserve(prio.size());
    │ │ │ │ -		for (auto p : prio)
    │ │ │ │ -			ret.push_back(int(static_cast<std::uint8_t>(p)));
    │ │ │ │ -		return ret;
    │ │ │ │ +
    relevance 0../src/part_file.cpp:300what do we do if someone is currently reading from the disk from this piece? does it matter? Since we won't actively erase the data from disk, but it may be overwritten soon, it's probably not that big of a deal

    what do we do if someone is currently reading from the disk │ │ │ │ +from this piece? does it matter? Since we won't actively erase the │ │ │ │ +data from disk, but it may be overwritten soon, it's probably not that │ │ │ │ +big of a deal

    ../src/part_file.cpp:300

    				create_directories(m_path, ec);
    │ │ │ │ +				if (ec) return {};
    │ │ │ │ +				return aux::file_handle(fn, 0, mode);
    │ │ │ │ +			}
    │ │ │ │ +			return {};
    │ │ │ │ +		}
    │ │ │ │  	}
    │ │ │ │ -#endif
    │ │ │ │ -
    │ │ │ │ -	void torrent_handle::file_priority(file_index_t index, download_priority_t priority) const
    │ │ │ │ +	catch (storage_error const& e)
    │ │ │ │  	{
    │ │ │ │ -		async_call(&torrent::set_file_priority, index, priority);
    │ │ │ │ +		ec = e.ec;
    │ │ │ │ +		return {};
    │ │ │ │  	}
    │ │ │ │  
    │ │ │ │ -	download_priority_t torrent_handle::file_priority(file_index_t index) const
    │ │ │ │ +	void part_file::free_piece(piece_index_t const piece)
    │ │ │ │  	{
    │ │ │ │ -		return sync_call_ret<download_priority_t>(dont_download, &torrent::file_priority, index);
    │ │ │ │ -	}
    │ │ │ │ +		std::lock_guard<std::mutex> l(m_mutex);
    │ │ │ │  
    │ │ │ │ -
    void torrent_handle::prioritize_files(std::vector<download_priority_t> const& files) const │ │ │ │ -
    { │ │ │ │ - async_call(&torrent::prioritize_files │ │ │ │ - , static_cast<aux::vector<download_priority_t, file_index_t> const&>(files)); │ │ │ │ + auto const i = m_piece_map.find(piece); │ │ │ │ + if (i == m_piece_map.end()) return; │ │ │ │ + │ │ │ │ +
    │ │ │ │ +
    m_free_slots.push_back(i->second); │ │ │ │ + m_piece_map.erase(i); │ │ │ │ + m_dirty_metadata = true; │ │ │ │ } │ │ │ │ │ │ │ │ - std::vector<download_priority_t> torrent_handle::get_file_priorities() const │ │ │ │ + void part_file::move_partfile(std::string const& path, error_code& ec) │ │ │ │ { │ │ │ │ - aux::vector<download_priority_t, file_index_t> ret; │ │ │ │ - auto retp = &ret; │ │ │ │ - sync_call(&torrent::file_priorities, retp); │ │ │ │ - return TORRENT_RVO(ret); │ │ │ │ - } │ │ │ │ + std::lock_guard<std::mutex> l(m_mutex); │ │ │ │ │ │ │ │ -#if TORRENT_ABI_VERSION == 1 │ │ │ │ + flush_metadata_impl(ec); │ │ │ │ + if (ec) return; │ │ │ │ │ │ │ │ -// ============ start deprecation =============== │ │ │ │ + if (!m_piece_map.empty()) │ │ │ │ + { │ │ │ │ + std::string old_path = combine_path(m_path, m_name); │ │ │ │ + std::string new_path = combine_path(path, m_name); │ │ │ │ │ │ │ │ - void torrent_handle::prioritize_files(std::vector<int> const& files) const │ │ │ │ - { │ │ │ │ - aux::vector<download_priority_t, file_index_t> file_prio; │ │ │ │ - file_prio.reserve(files.size()); │ │ │ │ - for (auto const p : files) { │ │ │ │ - file_prio.push_back(download_priority_t(static_cast<std::uint8_t>(p))); │ │ │ │ + rename(old_path, new_path, ec); │ │ │ │ + if (ec == boost::system::errc::no_such_file_or_directory) │ │ │ │ + ec.clear(); │ │ │ │ + │ │ │ │ + if (ec) │ │ │ │ + { │ │ │ │ + storage_error se; │ │ │ │ + aux::copy_file(old_path, new_path, se); │ │ │ │ + ec = se.ec; │ │ │ │ + if (ec) return; │ │ │ │ + remove(old_path, ec); │ │ │ │ + } │ │ │ │ + } │ │ │ │ +
    relevance 0../src/part_file.cpp:412instead of rebuilding the whole file header and flushing it, update the slot entries as we go

    instead of rebuilding the whole file header │ │ │ │ +and flushing it, update the slot entries as we go

    ../src/part_file.cpp:412

    						TORRENT_ASSERT(j->second == slot);
    │ │ │ │ +						m_free_slots.push_back(j->second);
    │ │ │ │ +						m_piece_map.erase(j);
    │ │ │ │ +						m_dirty_metadata = true;
    │ │ │ │ +					}
    │ │ │ │ +				}
    │ │ │ │ +			}
    │ │ │ │ +			file_offset += block_to_copy;
    │ │ │ │ +			piece_offset = 0;
    │ │ │ │ +			size -= block_to_copy;
    │ │ │ │  		}
    │ │ │ │ -		async_call(&torrent::prioritize_files, file_prio);
    │ │ │ │  	}
    │ │ │ │  
    │ │ │ │ -	std::vector<int> torrent_handle::file_priorities() const
    │ │ │ │ +	void part_file::flush_metadata(error_code& ec)
    │ │ │ │  	{
    │ │ │ │ -		aux::vector<download_priority_t, file_index_t> prio;
    │ │ │ │ -
    relevance 0../src/kademlia/node_id.cpp:66it's a little bit weird to return 159 - leading zeroes. It should probably be 160 - leading zeroes, but all other code in here is tuned to this expectation now, and it doesn't really matter (other than complexity)

    it's a little bit weird to return 159 - leading zeroes. It should │ │ │ │ -probably be 160 - leading zeroes, but all other code in here is tuned to │ │ │ │ -this expectation now, and it doesn't really matter (other than complexity)

    ../src/kademlia/node_id.cpp:66

    │ │ │ │ -// returns the distance between the two nodes
    │ │ │ │ -// using the kademlia XOR-metric
    │ │ │ │ -node_id distance(node_id const& n1, node_id const& n2)
    │ │ │ │ -{
    │ │ │ │ -	return n1 ^ n2;
    │ │ │ │ -}
    │ │ │ │ +		std::lock_guard<std::mutex> l(m_mutex);
    │ │ │ │  
    │ │ │ │ -// returns true if: distance(n1, ref) < distance(n2, ref)
    │ │ │ │ -bool compare_ref(node_id const& n1, node_id const& n2, node_id const& ref)
    │ │ │ │ -{
    │ │ │ │ -	node_id const lhs = n1 ^ ref;
    │ │ │ │ -	node_id const rhs = n2 ^ ref;
    │ │ │ │ -	return lhs < rhs;
    │ │ │ │ -}
    │ │ │ │ +		flush_metadata_impl(ec);
    │ │ │ │ +	}
    │ │ │ │  
    │ │ │ │ -// returns n in: 2^n <= distance(n1, n2) < 2^(n+1)
    │ │ │ │ -// useful for finding out which bucket a node belongs to
    │ │ │ │ -int distance_exp(node_id const& n1, node_id const& n2)
    │ │ │ │ -{
    │ │ │ │ -
    return std::max(159 - distance(n1, n2).count_leading_zeroes(), 0); │ │ │ │ -
    } │ │ │ │ +
    void part_file::flush_metadata_impl(error_code& ec) │ │ │ │ +
    { │ │ │ │ + // do we need to flush the metadata? │ │ │ │ + if (m_dirty_metadata == false) return; │ │ │ │ │ │ │ │ -int min_distance_exp(node_id const& n1, std::vector<node_id> const& ids) │ │ │ │ -{ │ │ │ │ - TORRENT_ASSERT(ids.size() > 0); │ │ │ │ + if (m_piece_map.empty()) │ │ │ │ + { │ │ │ │ + // if we don't have any pieces left in the │ │ │ │ + // part file, remove it │ │ │ │ + std::string const p = combine_path(m_path, m_name); │ │ │ │ + remove(p, ec); │ │ │ │ │ │ │ │ - int min = 160; // see distance_exp for the why of this constant │ │ │ │ - for (auto const& node_id : ids) │ │ │ │ - { │ │ │ │ - min = std::min(min, distance_exp(n1, node_id)); │ │ │ │ + if (ec == boost::system::errc::no_such_file_or_directory) │ │ │ │ + ec.clear(); │ │ │ │ + return; │ │ │ │ + } │ │ │ │ + │ │ │ │ + auto f = open_file(aux::open_mode::write | aux::open_mode::hidden, ec); │ │ │ │ + if (ec) return; │ │ │ │ + │ │ │ │ + std::vector<char> header(static_cast<std::size_t>(m_header_size)); │ │ │ │ + │ │ │ │ + using namespace libtorrent::aux; │ │ │ │ + │ │ │ │ + char* ptr = header.data(); │ │ │ │ + write_uint32(m_max_pieces, ptr); │ │ │ │ + write_uint32(m_piece_size, ptr); │ │ │ │ + │ │ │ │ + for (piece_index_t piece(0); piece < piece_index_t(m_max_pieces); ++piece) │ │ │ │ + { │ │ │ │ + auto const i = m_piece_map.find(piece); │ │ │ │ +
    relevance 0../src/utp_socket_manager.cpp:204this should not be heap allocated, sockets should be movable

    this should not be heap allocated, sockets should be movable

    ../src/utp_socket_manager.cpp:204

    │ │ │ │ +//		UTP_LOGV("incoming packet id:%d source:%s\n", id, print_endpoint(ep).c_str());
    │ │ │ │ +
    │ │ │ │ +		if (!m_sett.get_bool(settings_pack::enable_incoming_utp))
    │ │ │ │ +			return false;
    │ │ │ │ +
    │ │ │ │ +		// if not found, see if it's a SYN packet, if it is,
    │ │ │ │ +		// create a new utp_stream
    │ │ │ │ +		if (ph->get_type() == ST_SYN)
    │ │ │ │ +		{
    │ │ │ │ +			// possible SYN flood. Just ignore
    │ │ │ │ +			if (int(m_utp_sockets.size()) > m_sett.get_int(settings_pack::connections_limit) * 2)
    │ │ │ │ +				return false;
    │ │ │ │ +
    │ │ │ │ +			TORRENT_ASSERT(m_new_connection == -1);
    │ │ │ │ +			// create the new socket with this ID
    │ │ │ │ +			m_new_connection = id;
    │ │ │ │ +
    │ │ │ │ +//			UTP_LOGV("not found, new connection id:%d\n", m_new_connection);
    │ │ │ │ +
    │ │ │ │ +
    aux::socket_type c(aux::instantiate_connection(m_ios, aux::proxy_settings(), m_ssl_context, this, true, false)); │ │ │ │ +
    │ │ │ │ + utp_stream* str = nullptr; │ │ │ │ +#ifdef TORRENT_SSL_PEERS │ │ │ │ + if (is_ssl(c)) │ │ │ │ + str = &boost::get<ssl_stream<utp_stream>>(c).next_layer(); │ │ │ │ + else │ │ │ │ +#endif │ │ │ │ + str = boost::get<utp_stream>(&c); │ │ │ │ + │ │ │ │ + TORRENT_ASSERT(str); │ │ │ │ + int const mtu = mtu_for_dest(ep.address()); │ │ │ │ + str->get_impl()->init_mtu(mtu); │ │ │ │ + str->get_impl()->m_sock = std::move(socket); │ │ │ │ + bool const ret = str->get_impl()->incoming_packet(p, ep, receive_time); │ │ │ │ + if (!ret) return false; │ │ │ │ + m_last_socket = str->get_impl(); │ │ │ │ + m_cb(std::move(c)); │ │ │ │ + // the connection most likely changed its connection ID here │ │ │ │ + // we need to move it to the correct ID │ │ │ │ + return true; │ │ │ │ + } │ │ │ │ + │ │ │ │ + if (ph->get_type() == ST_RESET) return false; │ │ │ │ + │ │ │ │ + // #error send reset │ │ │ │ + │ │ │ │ + return false; │ │ │ │ } │ │ │ │ │ │ │ │ - return min; │ │ │ │ -} │ │ │ │ + void utp_socket_manager::subscribe_writable(utp_socket_impl* s) │ │ │ │ +
    relevance 0../src/choker.cpp:255make configurable

    make configurable

    ../src/choker.cpp:255

    			// first reset the number of unchoke slots, because we'll calculate
    │ │ │ │ +			// it purely based on the current state of our peers.
    │ │ │ │ +			upload_slots = 0;
    │ │ │ │  
    │ │ │ │ -node_id generate_id_impl(address const& ip_, std::uint32_t r)
    │ │ │ │ -{
    │ │ │ │ -	std::uint8_t* ip = nullptr;
    │ │ │ │ +			int rate_threshold = sett.get_int(settings_pack::rate_choker_initial_threshold);
    │ │ │ │  
    │ │ │ │ -	static std::uint8_t const v4mask[] = { 0x03, 0x0f, 0x3f, 0xff };
    │ │ │ │ -	static std::uint8_t const v6mask[] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
    │ │ │ │ -	std::uint8_t const* mask = nullptr;
    │ │ │ │ -	int num_octets = 0;
    │ │ │ │ +			std::sort(peers.begin(), peers.end()
    │ │ │ │ +				, [](peer_connection const* lhs, peer_connection const* rhs)
    │ │ │ │ +				{ return upload_rate_compare(lhs, rhs); });
    │ │ │ │  
    │ │ │ │ -	address_v4::bytes_type b4{};
    │ │ │ │ -	address_v6::bytes_type b6{};
    │ │ │ │ -	if (ip_.is_v6())
    │ │ │ │ -	{
    │ │ │ │ -		b6 = ip_.to_v6().to_bytes();
    │ │ │ │ -		ip = b6.data();
    │ │ │ │ -
    relevance 0../src/kademlia/item.cpp:143implement ctor for entry from bdecode_node?

    implement ctor for entry from bdecode_node?

    ../src/kademlia/item.cpp:143

    	, secret_key const& sk)
    │ │ │ │ -{
    │ │ │ │ -	char str[1200];
    │ │ │ │ -	int const len = canonical_string(v, seq, salt, str);
    │ │ │ │ +			for (auto const* p : peers)
    │ │ │ │ +			{
    │ │ │ │ +				int const rate = int(p->uploaded_in_last_round()
    │ │ │ │ +					* 1000 / total_milliseconds(unchoke_interval));
    │ │ │ │  
    │ │ │ │ -	return ed25519_sign({str, len}, pk, sk);
    │ │ │ │ -}
    │ │ │ │ +				// always have at least 1 unchoke slot
    │ │ │ │ +				if (rate < rate_threshold) break;
    │ │ │ │  
    │ │ │ │ -item::item(public_key const& pk, span<char const> salt)
    │ │ │ │ -	: m_salt(salt.data(), static_cast<std::size_t>(salt.size()))
    │ │ │ │ -	, m_pk(pk)
    │ │ │ │ -	, m_mutable(true)
    │ │ │ │ -{}
    │ │ │ │ +				++upload_slots;
    │ │ │ │  
    │ │ │ │ -item::item(entry v)
    │ │ │ │ -	: m_value(std::move(v))
    │ │ │ │ -{}
    │ │ │ │ +
    rate_threshold += 2048; │ │ │ │ +
    } │ │ │ │ + ++upload_slots; │ │ │ │ + } │ │ │ │ │ │ │ │ -item::item(bdecode_node const& v) │ │ │ │ -{ │ │ │ │ -
    m_value = v; │ │ │ │ -
    } │ │ │ │ + // sorts the peers that are eligible for unchoke by download rate and │ │ │ │ + // secondary by total upload. The reason for this is, if all torrents are │ │ │ │ + // being seeded, the download rate will be 0, and the peers we have sent │ │ │ │ + // the least to should be unchoked │ │ │ │ │ │ │ │ -item::item(entry v, span<char const> salt │ │ │ │ - , sequence_number const seq, public_key const& pk, secret_key const& sk) │ │ │ │ -{ │ │ │ │ - assign(std::move(v), salt, seq, pk, sk); │ │ │ │ -} │ │ │ │ + // we use partial sort here, because we only care about the top │ │ │ │ + // upload_slots peers. │ │ │ │ │ │ │ │ -void item::assign(entry v) │ │ │ │ -{ │ │ │ │ - m_mutable = false; │ │ │ │ - m_value = std::move(v); │ │ │ │ -} │ │ │ │ + int const slots = std::min(upload_slots, int(peers.size())); │ │ │ │ │ │ │ │ -void item::assign(entry v, span<char const> salt │ │ │ │ - , sequence_number const seq, public_key const& pk, secret_key const& sk) │ │ │ │ -{ │ │ │ │ - std::array<char, 1000> buffer; │ │ │ │ - int const bsize = bencode(buffer.begin(), v); │ │ │ │ - TORRENT_ASSERT(bsize <= 1000); │ │ │ │ - m_sig = sign_mutable_item(span<char const>(buffer).first(bsize) │ │ │ │ - , salt, seq, pk, sk); │ │ │ │ - m_salt.assign(salt.data(), static_cast<std::size_t>(salt.size())); │ │ │ │ - m_pk = pk; │ │ │ │ - m_seq = seq; │ │ │ │ - m_mutable = true; │ │ │ │ - m_value = std::move(v); │ │ │ │ -} │ │ │ │ + if (sett.get_int(settings_pack::seed_choking_algorithm) │ │ │ │ + == settings_pack::round_robin) │ │ │ │ + { │ │ │ │ + int const pieces = sett.get_int(settings_pack::seeding_piece_quota); │ │ │ │ │ │ │ │ -void item::assign(bdecode_node const& v) │ │ │ │ -
    relevance 0../src/kademlia/dht_tracker.cpp:317pick the closest node rather than the first

    pick the closest node rather than the first

    ../src/kademlia/dht_tracker.cpp:317

    │ │ │ │ -#ifndef TORRENT_DISABLE_LOGGING
    │ │ │ │ -		m_log->log(dht_logger::tracker, "*** new write key*** %d nodes"
    │ │ │ │ -			, int(m_nodes.size()));
    │ │ │ │ +			std::nth_element(peers.begin(), peers.begin()
    │ │ │ │ +				+ slots, peers.end()
    │ │ │ │ +				, [pieces](peer_connection const* lhs, peer_connection const* rhs)
    │ │ │ │ +				{ return unchoke_compare_rr(lhs, rhs, pieces); });
    │ │ │ │ +		}
    │ │ │ │ +		else if (sett.get_int(settings_pack::seed_choking_algorithm)
    │ │ │ │ +			== settings_pack::fastest_upload)
    │ │ │ │ +		{
    │ │ │ │ +			std::nth_element(peers.begin(), peers.begin()
    │ │ │ │ +				+ slots, peers.end()
    │ │ │ │ +				, [](peer_connection const* lhs, peer_connection const* rhs)
    │ │ │ │ +
    relevance 0../src/torrent_peer.cpp:181how do we deal with our external address changing?

    how do we deal with our external address changing?

    ../src/torrent_peer.cpp:181

    		// connections. If it fails, we'll
    │ │ │ │ +		// retry with encryption
    │ │ │ │ +		, pe_support(false)
    │ │ │ │ +#endif
    │ │ │ │ +		, is_v6_addr(false)
    │ │ │ │ +#if TORRENT_USE_I2P
    │ │ │ │ +		, is_i2p_addr(false)
    │ │ │ │  #endif
    │ │ │ │ +		, on_parole(false)
    │ │ │ │ +		, banned(false)
    │ │ │ │ +		, supports_utp(true) // assume peers support utp
    │ │ │ │ +		, confirmed_supports_utp(false)
    │ │ │ │ +		, supports_holepunch(false)
    │ │ │ │ +		, web_seed(false)
    │ │ │ │ +		, protocol_v2(false)
    │ │ │ │ +	{}
    │ │ │ │ +
    │ │ │ │ +	std::uint32_t torrent_peer::rank(external_ip const& external, int external_port) const
    │ │ │ │ +	{
    │ │ │ │ +		TORRENT_ASSERT(in_use);
    │ │ │ │ +
    if (peer_rank == 0) │ │ │ │ +
    peer_rank = peer_priority( │ │ │ │ + tcp::endpoint(external.external_address(this->address()), std::uint16_t(external_port)) │ │ │ │ + , tcp::endpoint(this->address(), this->port)); │ │ │ │ + return peer_rank; │ │ │ │ } │ │ │ │ │ │ │ │ - void dht_tracker::update_storage_node_ids() │ │ │ │ +#ifndef TORRENT_DISABLE_LOGGING │ │ │ │ + std::string torrent_peer::to_string() const │ │ │ │ { │ │ │ │ - std::vector<sha1_hash> ids; │ │ │ │ - for (auto& n : m_nodes) │ │ │ │ - ids.push_back(n.second.dht.nid()); │ │ │ │ - m_storage.update_node_ids(ids); │ │ │ │ + TORRENT_ASSERT(in_use); │ │ │ │ +#if TORRENT_USE_I2P │ │ │ │ + if (is_i2p_addr) return dest().to_string(); │ │ │ │ +#endif // TORRENT_USE_I2P │ │ │ │ + return address().to_string(); │ │ │ │ } │ │ │ │ +#endif │ │ │ │ │ │ │ │ - node* dht_tracker::get_node(node_id const& id, std::string const& family_name) │ │ │ │ + std::int64_t torrent_peer::total_download() const │ │ │ │ { │ │ │ │ - TORRENT_UNUSED(id); │ │ │ │ - for (auto& n : m_nodes) │ │ │ │ + TORRENT_ASSERT(in_use); │ │ │ │ + if (connection != nullptr) │ │ │ │ { │ │ │ │ -
    if (n.second.dht.protocol_family_name() == family_name) │ │ │ │ -
    return &n.second.dht; │ │ │ │ + TORRENT_ASSERT(prev_amount_download == 0); │ │ │ │ + return connection->statistics().total_payload_download(); │ │ │ │ + } │ │ │ │ + else │ │ │ │ + { │ │ │ │ + return std::int64_t(prev_amount_download) << 10; │ │ │ │ } │ │ │ │ + } │ │ │ │ +
    relevance 0../src/hash_picker.cpp:309use structured bindings in C++17

    use structured bindings in C++17

    ../src/hash_picker.cpp:309

    		, int const offset, sha256_hash const& h)
    │ │ │ │ +	{
    │ │ │ │ +		TORRENT_ASSERT(offset >= 0);
    │ │ │ │ +		auto const f = m_files.file_index_at_piece(piece);
    │ │ │ │  
    │ │ │ │ -		return nullptr;
    │ │ │ │ +		if (m_files.pad_file_at(f))
    │ │ │ │ +			return { set_block_hash_result::result::success, 0, 0 };
    │ │ │ │ +
    │ │ │ │ +		auto& merkle_tree = m_merkle_trees[f];
    │ │ │ │ +		piece_index_t const file_first_piece = m_files.piece_index_at_file(f);
    │ │ │ │ +		std::int64_t const block_offset = static_cast<int>(piece) * std::int64_t(m_files.piece_length())
    │ │ │ │ +			+ offset - m_files.file_offset(f);
    │ │ │ │ +		int const block_index = aux::numeric_cast<int>(block_offset / default_block_size);
    │ │ │ │ +
    │ │ │ │ +		if (h.is_all_zeros())
    │ │ │ │ +		{
    │ │ │ │ +			TORRENT_ASSERT_FAIL();
    │ │ │ │ +			return set_block_hash_result::block_hash_failed();
    │ │ │ │ +		}
    │ │ │ │ +
    │ │ │ │ +
    aux::merkle_tree::set_block_result result; │ │ │ │ +
    int leafs_index; │ │ │ │ + int leafs_size; │ │ │ │ + std::tie(result, leafs_index, leafs_size) = merkle_tree.set_block(block_index, h); │ │ │ │ + │ │ │ │ + if (result == aux::merkle_tree::set_block_result::unknown) │ │ │ │ + return set_block_hash_result::unknown(); │ │ │ │ + if (result == aux::merkle_tree::set_block_result::block_hash_failed) │ │ │ │ + return set_block_hash_result::block_hash_failed(); │ │ │ │ + │ │ │ │ + auto const status = (result == aux::merkle_tree::set_block_result::hash_failed) │ │ │ │ + ? set_block_hash_result::result::piece_hash_failed │ │ │ │ + : set_block_hash_result::result::success; │ │ │ │ + │ │ │ │ + int const blocks_per_piece = m_files.piece_length() / default_block_size; │ │ │ │ + │ │ │ │ + return { status │ │ │ │ + , int(leafs_index - static_cast<int>(piece - file_first_piece) * blocks_per_piece) │ │ │ │ + , std::min(leafs_size, m_files.file_num_pieces(f) * blocks_per_piece - leafs_index) }; │ │ │ │ } │ │ │ │ │ │ │ │ - void dht_tracker::get_peers(sha1_hash const& ih │ │ │ │ - , std::function<void(std::vector<tcp::endpoint> const&)> f) │ │ │ │ + void hash_picker::hashes_rejected(hash_request const& req) │ │ │ │ { │ │ │ │ - for (auto& n : m_nodes) │ │ │ │ - n.second.dht.get_peers(ih, f, {}, {}); │ │ │ │ + TORRENT_ASSERT(req.base == m_piece_layer && req.index % 512 == 0); │ │ │ │ + │ │ │ │ + for (int i = req.index; i < req.index + req.count; i += 512) │ │ │ │ + { │ │ │ │ + m_piece_hash_requested[req.file][i / 512].last_request = min_time(); │ │ │ │ + --m_piece_hash_requested[req.file][i / 512].num_requests; │ │ │ │ + } │ │ │ │ + │ │ │ │ +
    relevance 0../src/disabled_disk_io.cpp:106it would be nice to return a valid hash of zeroes here

    it would be nice to return a valid hash of zeroes here

    ../src/disabled_disk_io.cpp:106

    		});
    │ │ │ │  	}
    │ │ │ │  
    │ │ │ │ -	void dht_tracker::announce(sha1_hash const& ih, int listen_port
    │ │ │ │ -		, announce_flags_t const flags
    │ │ │ │ -		, std::function<void(std::vector<tcp::endpoint> const&)> f)
    │ │ │ │ +	bool async_write(storage_index_t
    │ │ │ │ +		, peer_request const& r
    │ │ │ │ +		, char const*, std::shared_ptr<disk_observer>
    │ │ │ │ +		, std::function<void(storage_error const&)> handler
    │ │ │ │ +		, disk_job_flags_t) override
    │ │ │ │  	{
    │ │ │ │ -		for (auto& n : m_nodes)
    │ │ │ │ -			n.second.dht.announce(ih, listen_port, flags, f);
    │ │ │ │ +		TORRENT_ASSERT(r.length <= default_block_size);
    │ │ │ │ +		TORRENT_UNUSED(r);
    │ │ │ │ +
    │ │ │ │ +		post(m_ios, [h = std::move(handler)] { h(storage_error{}); });
    │ │ │ │ +		return false;
    │ │ │ │  	}
    │ │ │ │  
    │ │ │ │ -	void dht_tracker::sample_infohashes(udp::endpoint const& ep, sha1_hash const& target
    │ │ │ │ -		, std::function<void(node_id
    │ │ │ │ -			, time_duration
    │ │ │ │ -			, int, std::vector<sha1_hash>
    │ │ │ │ -			, std::vector<std::pair<sha1_hash, udp::endpoint>>)> f)
    │ │ │ │ +	void async_hash(storage_index_t
    │ │ │ │ +		, piece_index_t piece, span<sha256_hash>, disk_job_flags_t
    │ │ │ │ +		, std::function<void(piece_index_t, sha1_hash const&, storage_error const&)> handler) override
    │ │ │ │  	{
    │ │ │ │ -		for (auto& n : m_nodes)
    │ │ │ │ -		{
    │ │ │ │ -			if (ep.protocol() != (n.first.get_external_address().is_v4() ? udp::v4() : udp::v6()))
    │ │ │ │ -
    relevance 0../src/kademlia/put_data.cpp:92what if o is not an instance of put_data_observer? This need to be redesigned for better type safety.

    what if o is not an instance of put_data_observer? This need to be │ │ │ │ -redesigned for better type safety.

    ../src/kademlia/put_data.cpp:92

    	}
    │ │ │ │ -}
    │ │ │ │ +
    post(m_ios, [h = std::move(handler), piece] { h(piece, sha1_hash{}, storage_error{}); }); │ │ │ │ +
    } │ │ │ │ │ │ │ │ -void put_data::done() │ │ │ │ -{ │ │ │ │ - m_done = true; │ │ │ │ + void async_hash2(storage_index_t, piece_index_t piece, int │ │ │ │ + , disk_job_flags_t │ │ │ │ + , std::function<void(piece_index_t, sha256_hash const&, storage_error const&)> handler) override │ │ │ │ + { │ │ │ │ + post(m_ios, [h = std::move(handler), piece]() { h(piece, sha256_hash{}, storage_error{}); }); │ │ │ │ + } │ │ │ │ │ │ │ │ -#ifndef TORRENT_DISABLE_LOGGING │ │ │ │ - get_node().observer()->log(dht_logger::traversal, "[%u] %s DONE, response %d, timeout %d" │ │ │ │ - , id(), name(), num_responses(), num_timeouts()); │ │ │ │ + void async_move_storage(storage_index_t │ │ │ │ + , std::string p, move_flags_t │ │ │ │ + , std::function<void(status_t, std::string const&, storage_error const&)> handler) override │ │ │ │ + { │ │ │ │ + post(m_ios, [h = std::move(handler), path = std::move(p)] () mutable │ │ │ │ + { h(status_t::no_error, std::move(path), storage_error{}); }); │ │ │ │ + } │ │ │ │ + │ │ │ │ + void async_release_files(storage_index_t, std::function<void()> handler) override │ │ │ │ + { │ │ │ │ + post(m_ios, [h = std::move(handler)] { h(); }); │ │ │ │ + } │ │ │ │ + │ │ │ │ + void async_delete_files(storage_index_t │ │ │ │ + , remove_flags_t, std::function<void(storage_error const&)> handler) override │ │ │ │ + { │ │ │ │ + post(m_ios, [h = std::move(handler)] { h(storage_error{}); }); │ │ │ │ + } │ │ │ │ + │ │ │ │ + void async_check_files(storage_index_t │ │ │ │ + , add_torrent_params const* │ │ │ │ +
    relevance 0../src/mmap_disk_io.cpp:578in the future, propagate exceptions back to the handlers

    in the future, propagate exceptions back to the handlers

    ../src/mmap_disk_io.cpp:578

    #if DEBUG_DISK_THREAD
    │ │ │ │ +		{
    │ │ │ │ +			std::unique_lock<std::mutex> l(m_job_mutex);
    │ │ │ │ +
    │ │ │ │ +			DLOG("perform_job job: %s ( %s%s) piece: %d offset: %d outstanding: %d\n"
    │ │ │ │ +				, job_action_name[j->action]
    │ │ │ │ +				, (j->flags & mmap_disk_job::fence) ? "fence ": ""
    │ │ │ │ +				, (j->flags & mmap_disk_job::force_copy) ? "force_copy ": ""
    │ │ │ │ +				, static_cast<int>(j->piece), j->d.io.offset
    │ │ │ │ +				, j->storage ? j->storage->num_outstanding_jobs() : -1);
    │ │ │ │ +		}
    │ │ │ │  #endif
    │ │ │ │  
    │ │ │ │ -	m_put_callback(m_data, num_responses());
    │ │ │ │ -	traversal_algorithm::done();
    │ │ │ │ -}
    │ │ │ │ +		std::shared_ptr<mmap_storage> storage = j->storage;
    │ │ │ │  
    │ │ │ │ -bool put_data::invoke(observer_ptr o)
    │ │ │ │ -{
    │ │ │ │ -	if (m_done) return false;
    │ │ │ │ +		TORRENT_ASSERT(static_cast<int>(j->action) < int(job_functions.size()));
    │ │ │ │  
    │ │ │ │ -
    auto* po = static_cast<put_data_observer*>(o.get()); │ │ │ │ -
    │ │ │ │ - entry e; │ │ │ │ - e["y"] = "q"; │ │ │ │ - e["q"] = "put"; │ │ │ │ - entry& a = e["a"]; │ │ │ │ - a["v"] = m_data.value(); │ │ │ │ - a["token"] = po->m_token; │ │ │ │ - if (m_data.is_mutable()) │ │ │ │ - { │ │ │ │ - a["k"] = m_data.pk().bytes; │ │ │ │ - a["seq"] = m_data.seq().value; │ │ │ │ - a["sig"] = m_data.sig().bytes; │ │ │ │ - if (!m_data.salt().empty()) │ │ │ │ + m_stats_counters.inc_stats_counter(counters::num_running_disk_jobs, 1); │ │ │ │ + │ │ │ │ + // call disk function │ │ │ │ +
    status_t ret = status_t::no_error; │ │ │ │ +
    try │ │ │ │ { │ │ │ │ - a["salt"] = m_data.salt(); │ │ │ │ + int const idx = static_cast<int>(j->action); │ │ │ │ + ret = (this->*(job_functions[static_cast<std::size_t>(idx)]))(j); │ │ │ │ + } │ │ │ │ + catch (boost::system::system_error const& err) │ │ │ │ + { │ │ │ │ + ret = status_t::fatal_disk_error; │ │ │ │ + j->error.ec = err.code(); │ │ │ │ + j->error.operation = operation_t::exception; │ │ │ │ + } │ │ │ │ + catch (std::bad_alloc const&) │ │ │ │ + { │ │ │ │ + ret = status_t::fatal_disk_error; │ │ │ │ + j->error.ec = errors::no_memory; │ │ │ │ + j->error.operation = operation_t::exception; │ │ │ │ } │ │ │ │ + catch (std::exception const&) │ │ │ │ + { │ │ │ │ + ret = status_t::fatal_disk_error; │ │ │ │ + j->error.ec = boost::asio::error::fault; │ │ │ │ + j->error.operation = operation_t::exception; │ │ │ │ + } │ │ │ │ + │ │ │ │ + // note that -2 errors are OK │ │ │ │ + TORRENT_ASSERT(ret != status_t::fatal_disk_error │ │ │ │ + || (j->error.ec && j->error.operation != operation_t::unknown)); │ │ │ │ + │ │ │ │ + m_stats_counters.inc_stats_counter(counters::num_running_disk_jobs, -1); │ │ │ │ + │ │ │ │ +
    relevance 0../src/mmap_disk_io.cpp:1017this is potentially very expensive. One way to solve it would be to have a fence for just this one piece. but it hardly seems worth the complexity and cost just for the edge case of receiving a corrupt piece

    this is potentially very expensive. One way to solve │ │ │ │ +it would be to have a fence for just this one piece. │ │ │ │ +but it hardly seems worth the complexity and cost just for the edge │ │ │ │ +case of receiving a corrupt piece

    ../src/mmap_disk_io.cpp:1017

    		aux::mmap_disk_job* j = m_job_pool.allocate_job(aux::job_action_t::file_priority);
    │ │ │ │ +		j->storage = m_torrents[storage]->shared_from_this();
    │ │ │ │ +		j->argument = std::move(prios);
    │ │ │ │ +		j->callback = std::move(handler);
    │ │ │ │ +
    │ │ │ │ +		add_fence_job(j);
    │ │ │ │  	}
    │ │ │ │  
    │ │ │ │ -	m_node.stats_counters().inc_stats_counter(counters::dht_put_out);
    │ │ │ │ +	void mmap_disk_io::async_clear_piece(storage_index_t const storage
    │ │ │ │ +		, piece_index_t const index, std::function<void(piece_index_t)> handler)
    │ │ │ │ +	{
    │ │ │ │ +		aux::mmap_disk_job* j = m_job_pool.allocate_job(aux::job_action_t::clear_piece);
    │ │ │ │ +		j->storage = m_torrents[storage]->shared_from_this();
    │ │ │ │ +		j->piece = index;
    │ │ │ │ +		j->callback = std::move(handler);
    │ │ │ │  
    │ │ │ │ -	return m_node.m_rpc.invoke(e, o->target_ep(), o);
    │ │ │ │ -}
    │ │ │ │ +		// regular jobs are not guaranteed to be executed in-order
    │ │ │ │ +		// since clear piece must guarantee that all write jobs that
    │ │ │ │ +		// have been issued finish before the clear piece job completes
    │ │ │ │  
    │ │ │ │ -} } // namespace libtorrent::dht
    │ │ │ │ -
    relevance 0../src/kademlia/node.cpp:1177keep the returned value to pass as a limit to write_nodes_entries when implemented

    keep the returned value to pass as a limit │ │ │ │ +
    │ │ │ │ +
    relevance 0../src/mmap_disk_io.cpp:1022Perhaps the job queue could be traversed and all jobs for this piece could be cancelled. If there are no threads currently writing to this piece, we could skip the fence altogether

    Perhaps the job queue could be traversed and all jobs for this │ │ │ │ +piece could be cancelled. If there are no threads currently writing │ │ │ │ +to this piece, we could skip the fence altogether

    ../src/mmap_disk_io.cpp:1022

    		j->storage = m_torrents[storage]->shared_from_this();
    │ │ │ │ +		j->argument = std::move(prios);
    │ │ │ │ +		j->callback = std::move(handler);
    │ │ │ │ +
    │ │ │ │ +		add_fence_job(j);
    │ │ │ │ +	}
    │ │ │ │ +
    │ │ │ │ +	void mmap_disk_io::async_clear_piece(storage_index_t const storage
    │ │ │ │ +		, piece_index_t const index, std::function<void(piece_index_t)> handler)
    │ │ │ │ +	{
    │ │ │ │ +		aux::mmap_disk_job* j = m_job_pool.allocate_job(aux::job_action_t::clear_piece);
    │ │ │ │ +		j->storage = m_torrents[storage]->shared_from_this();
    │ │ │ │ +		j->piece = index;
    │ │ │ │ +		j->callback = std::move(handler);
    │ │ │ │ +
    │ │ │ │ +		// regular jobs are not guaranteed to be executed in-order
    │ │ │ │ +		// since clear piece must guarantee that all write jobs that
    │ │ │ │ +		// have been issued finish before the clear piece job completes
    │ │ │ │ +
    │ │ │ │ +
    │ │ │ │ +
    add_fence_job(j); │ │ │ │ +
    } │ │ │ │ + │ │ │ │ + status_t mmap_disk_io::do_hash(aux::mmap_disk_job* j) │ │ │ │ + { │ │ │ │ + // we're not using a cache. This is the simple path │ │ │ │ + // just read straight from the file │ │ │ │ + TORRENT_ASSERT(m_magic == 0x1337); │ │ │ │ + │ │ │ │ + bool const v1 = bool(j->flags & disk_interface::v1_hash); │ │ │ │ + bool const v2 = !j->d.h.block_hashes.empty(); │ │ │ │ + │ │ │ │ + int const piece_size = v1 ? j->storage->files().piece_size(j->piece) : 0; │ │ │ │ + int const piece_size2 = v2 ? j->storage->files().piece_size2(j->piece) : 0; │ │ │ │ + int const blocks_in_piece = v1 ? (piece_size + default_block_size - 1) / default_block_size : 0; │ │ │ │ + int const blocks_in_piece2 = v2 ? j->storage->files().blocks_in_piece2(j->piece) : 0; │ │ │ │ + aux::open_mode_t const file_mode = file_mode_for_job(j); │ │ │ │ + │ │ │ │ + TORRENT_ASSERT(!v2 || int(j->d.h.block_hashes.size()) >= blocks_in_piece2); │ │ │ │ + TORRENT_ASSERT(v1 || v2); │ │ │ │ + │ │ │ │ + hasher h; │ │ │ │ + int ret = 0; │ │ │ │ + int offset = 0; │ │ │ │ + int const blocks_to_read = std::max(blocks_in_piece, blocks_in_piece2); │ │ │ │ + time_point const start_time = clock_type::now(); │ │ │ │ + for (int i = 0; i < blocks_to_read; ++i) │ │ │ │ + { │ │ │ │ + bool const v2_block = i < blocks_in_piece2; │ │ │ │ + │ │ │ │ + DLOG("do_hash: reading (piece: %d block: %d)\n", int(j->piece), i); │ │ │ │ +
    relevance 0../src/ut_metadata.cpp:281we really need to increment the refcounter on the torrent while this buffer is still in the peer's send buffer

    we really need to increment the refcounter on the torrent │ │ │ │ +while this buffer is still in the peer's send buffer

    ../src/ut_metadata.cpp:281

    				int const offset = piece * 16 * 1024;
    │ │ │ │ +				metadata = m_tp.metadata().data() + offset;
    │ │ │ │ +				metadata_piece_size = std::min(
    │ │ │ │ +					int(m_tp.metadata().size()) - offset, 16 * 1024);
    │ │ │ │ +				TORRENT_ASSERT(metadata_piece_size > 0);
    │ │ │ │ +				TORRENT_ASSERT(offset >= 0);
    │ │ │ │ +				TORRENT_ASSERT(offset + metadata_piece_size <= m_tp.metadata().size());
    │ │ │ │ +			}
    │ │ │ │ +
    │ │ │ │ +			char msg[200];
    │ │ │ │ +			char* header = msg;
    │ │ │ │ +			char* p = &msg[6];
    │ │ │ │ +			int const len = bencode(p, e);
    │ │ │ │ +			int const total_size = 2 + len + metadata_piece_size;
    │ │ │ │ +			namespace io = aux;
    │ │ │ │ +			io::write_uint32(total_size, header);
    │ │ │ │ +			io::write_uint8(bt_peer_connection::msg_extended, header);
    │ │ │ │ +			io::write_uint8(m_message_index, header);
    │ │ │ │ +
    │ │ │ │ +			m_pc.send_buffer({msg, len + 6});
    │ │ │ │ +
    if (metadata_piece_size) │ │ │ │ +
    { │ │ │ │ + m_pc.append_const_send_buffer( │ │ │ │ + span<char>(const_cast<char*>(metadata), metadata_piece_size), metadata_piece_size); │ │ │ │ + } │ │ │ │ + │ │ │ │ + m_pc.stats_counters().inc_stats_counter(counters::num_outgoing_extended); │ │ │ │ + m_pc.stats_counters().inc_stats_counter(counters::num_outgoing_metadata); │ │ │ │ + } │ │ │ │ + │ │ │ │ + bool on_extended(int const length │ │ │ │ + , int const extended_msg, span<char const> body) override │ │ │ │ + { │ │ │ │ + if (extended_msg != 2) return false; │ │ │ │ + if (m_message_index == 0) return false; │ │ │ │ + │ │ │ │ + if (length > 17 * 1024) │ │ │ │ + { │ │ │ │ +#ifndef TORRENT_DISABLE_LOGGING │ │ │ │ + m_pc.peer_log(peer_log_alert::incoming_message, "UT_METADATA" │ │ │ │ + , "packet too big %d", length); │ │ │ │ +#endif │ │ │ │ + m_pc.disconnect(errors::invalid_metadata_message, operation_t::bittorrent, peer_connection_interface::peer_error); │ │ │ │ + return true; │ │ │ │ + } │ │ │ │ + │ │ │ │ + if (!m_pc.packet_finished()) return true; │ │ │ │ + │ │ │ │ + error_code ec; │ │ │ │ + bdecode_node msg = bdecode(body, ec); │ │ │ │ + if (msg.type() != bdecode_node::dict_t) │ │ │ │ +
    relevance 0../src/kademlia/node.cpp:1177keep the returned value to pass as a limit to write_nodes_entries when implemented

    keep the returned value to pass as a limit │ │ │ │ to write_nodes_entries when implemented

    ../src/kademlia/node.cpp:1177

    		}
    │ │ │ │  	}
    │ │ │ │  	else if (query == "sample_infohashes")
    │ │ │ │  	{
    │ │ │ │  		static key_desc_t const msg_desc[] = {
    │ │ │ │  			{"target", bdecode_node::string_t, 20, 0},
    │ │ │ │  			{"want", bdecode_node::list_t, 0, key_desc_t::optional},
    │ │ │ │ @@ -10147,15 +9946,15 @@
    │ │ │ │  
    │ │ │ │  		sha1_hash const target(target_ent.string_ptr());
    │ │ │ │  		// always return nodes as well as peers
    │ │ │ │  		write_nodes_entries(target, arg_ent.dict_find_list("want"), reply);
    │ │ │ │  	}
    │ │ │ │  }
    │ │ │ │  
    │ │ │ │ -
    relevance 0../src/kademlia/node.cpp:1205limit number of entries in the result

    limit number of entries in the result

    ../src/kademlia/node.cpp:1205

    		// if we don't recognize the message but there's a
    │ │ │ │ +
    relevance 0../src/kademlia/node.cpp:1205limit number of entries in the result

    limit number of entries in the result

    ../src/kademlia/node.cpp:1205

    		// if we don't recognize the message but there's a
    │ │ │ │  		// 'target' or 'info_hash' in the arguments, treat it
    │ │ │ │  		// as find_node to be future compatible
    │ │ │ │  		bdecode_node target_ent = arg_ent.dict_find_string("target");
    │ │ │ │  		if (!target_ent || target_ent.string_length() != 20)
    │ │ │ │  		{
    │ │ │ │  			target_ent = arg_ent.dict_find_string("info_hash");
    │ │ │ │  			if (!target_ent || target_ent.string_length() != 20)
    │ │ │ │ @@ -10198,15 +9997,15 @@
    │ │ │ │  		std::vector<node_entry> const n = wanted_node->m_table.find_node(info_hash, {});
    │ │ │ │  		r[wanted_node->protocol_nodes_key()] = write_nodes_entry(n);
    │ │ │ │  	}
    │ │ │ │  }
    │ │ │ │  
    │ │ │ │  node::protocol_descriptor const& node::map_protocol_to_descriptor(udp const protocol)
    │ │ │ │  {
    │ │ │ │ -
    relevance 0../src/kademlia/routing_table.cpp:289This is temporary. For now, only report the largest routing table (of potentially multiple ones, for multi-homed systems) in next major version, break the ABI and support reporting all of them in the dht_stats_alert

    This is temporary. For now, only report the largest routing table │ │ │ │ +relevance 0../src/kademlia/routing_table.cpp:289This is temporary. For now, only report the largest routing table (of potentially multiple ones, for multi-homed systems) in next major version, break the ABI and support reporting all of them in the dht_stats_alert

    This is temporary. For now, only report the largest routing table │ │ │ │ (of potentially multiple ones, for multi-homed systems) │ │ │ │ in next major version, break the ABI and support reporting all of them in │ │ │ │ the dht_stats_alert

    ../src/kademlia/routing_table.cpp:289

    	, m_bucket_size(bucket_size)
    │ │ │ │  {
    │ │ │ │  	// bucket sizes must be a power of 2
    │ │ │ │  	TORRENT_ASSERT_VAL(((bucket_size - 1) & bucket_size) == 0, bucket_size);
    │ │ │ │  	TORRENT_UNUSED(log);
    │ │ │ │ @@ -10233,15 +10032,15 @@
    │ │ │ │  		b.num_nodes = int(i.live_nodes.size());
    │ │ │ │  		b.num_replacements = int(i.replacements.size());
    │ │ │ │  		s.push_back(b);
    │ │ │ │  	}
    │ │ │ │  }
    │ │ │ │  
    │ │ │ │  #if TORRENT_ABI_VERSION == 1
    │ │ │ │ -
    relevance 0../src/kademlia/routing_table.cpp:314arvidn note when it's across IPv4 and IPv6, adding (dht_global_nodes) would make sense. in the future though, where we may have one DHT node per external interface (which may be multiple of the same address family), then it becomes a bit trickier

    arvidn note │ │ │ │ +relevance 0../src/kademlia/routing_table.cpp:314arvidn note when it's across IPv4 and IPv6, adding (dht_global_nodes) would make sense. in the future though, where we may have one DHT node per external interface (which may be multiple of the same address family), then it becomes a bit trickier

    arvidn note │ │ │ │ when it's across IPv4 and IPv6, adding (dht_global_nodes) would │ │ │ │ make sense. in the future though, where we may have one DHT node │ │ │ │ per external interface (which may be multiple of the same address │ │ │ │ family), then it becomes a bit trickier

    ../src/kademlia/routing_table.cpp:314

    	if (s.size() > m_buckets.size()) return;
    │ │ │ │  	s.clear();
    │ │ │ │  	for (auto const& i : m_buckets)
    │ │ │ │  	{
    │ │ │ │ @@ -10288,15 +10087,15 @@
    │ │ │ │  			, [](node_entry const& k) { return k.confirmed(); } ));
    │ │ │ │  
    │ │ │ │  		replacements += int(i.replacements.size());
    │ │ │ │  	}
    │ │ │ │  	return std::make_tuple(nodes, replacements, confirmed);
    │ │ │ │  }
    │ │ │ │  
    │ │ │ │ -
    relevance 0../src/kademlia/routing_table.cpp:518this need to take bucket "prefix" into account. It should be unified with add_node_impl()

    this need to take bucket "prefix" into account. It should be unified │ │ │ │ +relevance 0../src/kademlia/routing_table.cpp:518this need to take bucket "prefix" into account. It should be unified with add_node_impl()

    this need to take bucket "prefix" into account. It should be unified │ │ │ │ with add_node_impl()

    ../src/kademlia/routing_table.cpp:518

    {
    │ │ │ │  	for (auto i = m_buckets.begin() , end(m_buckets.end()); i != end; ++i)
    │ │ │ │  	{
    │ │ │ │  		for (auto j = i->replacements.begin(); j != i->replacements.end(); ++j)
    │ │ │ │  		{
    │ │ │ │  			if (j->addr() != ep.address()) continue;
    │ │ │ │  			if (j->port() != ep.port()) continue;
    │ │ │ │ @@ -10340,299 +10139,216 @@
    │ │ │ │  		&& m_buckets.back().replacements.empty())
    │ │ │ │  	{
    │ │ │ │  		m_buckets.erase(m_buckets.end() - 1);
    │ │ │ │  	}
    │ │ │ │  }
    │ │ │ │  
    │ │ │ │  void routing_table::remove_node(node_entry* n, bucket_t* b)
    │ │ │ │ -
    relevance 0../include/libtorrent/i2p_stream.hpp:539make this a string_view

    make this a string_view

    ../include/libtorrent/i2p_stream.hpp:539

    │ │ │ │ -		char tmp[20];
    │ │ │ │ -		aux::random_bytes(tmp);
    │ │ │ │ -		m_session_id.resize(sizeof(tmp)*2);
    │ │ │ │ -		aux::to_hex(tmp, &m_session_id[0]);
    │ │ │ │ +
    relevance 0../src/kademlia/node_id.cpp:66it's a little bit weird to return 159 - leading zeroes. It should probably be 160 - leading zeroes, but all other code in here is tuned to this expectation now, and it doesn't really matter (other than complexity)

    it's a little bit weird to return 159 - leading zeroes. It should │ │ │ │ +probably be 160 - leading zeroes, but all other code in here is tuned to │ │ │ │ +this expectation now, and it doesn't really matter (other than complexity)

    ../src/kademlia/node_id.cpp:66

    │ │ │ │ +// returns the distance between the two nodes
    │ │ │ │ +// using the kademlia XOR-metric
    │ │ │ │ +node_id distance(node_id const& n1, node_id const& n2)
    │ │ │ │ +{
    │ │ │ │ +	return n1 ^ n2;
    │ │ │ │ +}
    │ │ │ │  
    │ │ │ │ -		m_sam_socket = std::make_shared<i2p_stream>(m_io_service);
    │ │ │ │ -		m_sam_socket->set_proxy(m_hostname, m_port);
    │ │ │ │ -		m_sam_socket->set_command(i2p_stream::cmd_create_session);
    │ │ │ │ -		m_sam_socket->set_session_id(m_session_id.c_str());
    │ │ │ │ -		m_sam_socket->set_session_options(session_options);
    │ │ │ │ +// returns true if: distance(n1, ref) < distance(n2, ref)
    │ │ │ │ +bool compare_ref(node_id const& n1, node_id const& n2, node_id const& ref)
    │ │ │ │ +{
    │ │ │ │ +	node_id const lhs = n1 ^ ref;
    │ │ │ │ +	node_id const rhs = n2 ^ ref;
    │ │ │ │ +	return lhs < rhs;
    │ │ │ │ +}
    │ │ │ │  
    │ │ │ │ -		ADD_OUTSTANDING_ASYNC("i2p_stream::on_sam_connect");
    │ │ │ │ -		m_sam_socket->async_connect(tcp::endpoint(), wrap_allocator(
    │ │ │ │ -			[this,s=m_sam_socket](error_code const& ec, Handler hn) {
    │ │ │ │ -				on_sam_connect(ec, s, std::move(hn));
    │ │ │ │ -			}, std::move(handler)));
    │ │ │ │ -	}
    │ │ │ │ -	void close(error_code&);
    │ │ │ │ +// returns n in: 2^n <= distance(n1, n2) < 2^(n+1)
    │ │ │ │ +// useful for finding out which bucket a node belongs to
    │ │ │ │ +int distance_exp(node_id const& n1, node_id const& n2)
    │ │ │ │ +{
    │ │ │ │ +
    return std::max(159 - distance(n1, n2).count_leading_zeroes(), 0); │ │ │ │ +
    } │ │ │ │ │ │ │ │ -
    char const* session_id() const { return m_session_id.c_str(); } │ │ │ │ -
    std::string const& local_endpoint() const { return m_i2p_local_endpoint; } │ │ │ │ +int min_distance_exp(node_id const& n1, std::vector<node_id> const& ids) │ │ │ │ +{ │ │ │ │ + TORRENT_ASSERT(ids.size() > 0); │ │ │ │ │ │ │ │ - template <typename Handler> │ │ │ │ - void async_name_lookup(char const* name, Handler handler) │ │ │ │ + int min = 160; // see distance_exp for the why of this constant │ │ │ │ + for (auto const& node_id : ids) │ │ │ │ { │ │ │ │ - if (m_state == sam_idle && m_name_lookup.empty() && is_open()) │ │ │ │ - do_name_lookup(name, std::move(handler)); │ │ │ │ - else │ │ │ │ - m_name_lookup.emplace_back(std::string(name) │ │ │ │ - , std::move(handler)); │ │ │ │ + min = std::min(min, distance_exp(n1, node_id)); │ │ │ │ } │ │ │ │ │ │ │ │ -private: │ │ │ │ - │ │ │ │ - template <typename Handler> │ │ │ │ - void on_sam_connect(error_code const& ec, std::shared_ptr<i2p_stream>, Handler h) │ │ │ │ - { │ │ │ │ - COMPLETE_ASYNC("i2p_stream::on_sam_connect"); │ │ │ │ - m_state = sam_idle; │ │ │ │ - │ │ │ │ - if (ec) │ │ │ │ - { │ │ │ │ - h(ec); │ │ │ │ - return; │ │ │ │ - } │ │ │ │ + return min; │ │ │ │ +} │ │ │ │ │ │ │ │ - do_name_lookup("ME", wrap_allocator( │ │ │ │ - [this](error_code const& e, char const* dst, Handler hn) { │ │ │ │ - set_local_endpoint(e, dst, std::move(hn)); │ │ │ │ - }, std::move(h))); │ │ │ │ -
    relevance 0../include/libtorrent/hash_picker.hpp:155support batched adding of block hashes for reduced overhead?

    support batched adding of block hashes for reduced overhead?

    ../include/libtorrent/hash_picker.hpp:155

    		// the number of hashes in the range
    │ │ │ │ -		int count = 0;
    │ │ │ │ -		int proof_layers = 0;
    │ │ │ │ -	};
    │ │ │ │ +node_id generate_id_impl(address const& ip_, std::uint32_t r)
    │ │ │ │ +{
    │ │ │ │ +	std::uint8_t* ip = nullptr;
    │ │ │ │  
    │ │ │ │ -	// validates the hash_request, to ensure its invariant as well as matching
    │ │ │ │ -	// the torrent's file_storage and the number of hashes accompanying the
    │ │ │ │ -	// request
    │ │ │ │ -	TORRENT_EXTRA_EXPORT
    │ │ │ │ -	bool validate_hash_request(hash_request const& hr, file_storage const& fs);
    │ │ │ │ +	static std::uint8_t const v4mask[] = { 0x03, 0x0f, 0x3f, 0xff };
    │ │ │ │ +	static std::uint8_t const v6mask[] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
    │ │ │ │ +	std::uint8_t const* mask = nullptr;
    │ │ │ │ +	int num_octets = 0;
    │ │ │ │  
    │ │ │ │ -	class TORRENT_EXTRA_EXPORT hash_picker
    │ │ │ │ +	address_v4::bytes_type b4{};
    │ │ │ │ +	address_v6::bytes_type b6{};
    │ │ │ │ +	if (ip_.is_v6())
    │ │ │ │  	{
    │ │ │ │ -	public:
    │ │ │ │ -		hash_picker(file_storage const& files
    │ │ │ │ -			, aux::vector<aux::merkle_tree, file_index_t>& trees);
    │ │ │ │ -
    │ │ │ │ -		hash_request pick_hashes(typed_bitfield<piece_index_t> const& pieces);
    │ │ │ │ -
    │ │ │ │ -		add_hashes_result add_hashes(hash_request const& req, span<sha256_hash const> hashes);
    │ │ │ │ -
    set_block_hash_result set_block_hash(piece_index_t piece, int offset, sha256_hash const& h); │ │ │ │ -
    void hashes_rejected(hash_request const& req); │ │ │ │ - void verify_block_hashes(piece_index_t index); │ │ │ │ - │ │ │ │ - // do we know the piece layer hash for a piece │ │ │ │ - bool have_hash(piece_index_t index) const; │ │ │ │ - // do we know all the block hashes for a file? │ │ │ │ - bool have_all(file_index_t file) const; │ │ │ │ - bool have_all() const; │ │ │ │ - bool piece_verified(piece_index_t piece) const; │ │ │ │ - │ │ │ │ - int piece_layer() const { return m_piece_layer; } │ │ │ │ + b6 = ip_.to_v6().to_bytes(); │ │ │ │ + ip = b6.data(); │ │ │ │ +
    relevance 0../src/kademlia/put_data.cpp:92what if o is not an instance of put_data_observer? This need to be redesigned for better type safety.

    what if o is not an instance of put_data_observer? This need to be │ │ │ │ +redesigned for better type safety.

    ../src/kademlia/put_data.cpp:92

    	}
    │ │ │ │ +}
    │ │ │ │  
    │ │ │ │ -	private:
    │ │ │ │ -		// returns the number of proof layers needed to verify the node's hash
    │ │ │ │ -		int layers_to_verify(node_index idx) const;
    │ │ │ │ -		int file_num_layers(file_index_t idx) const;
    │ │ │ │ +void put_data::done()
    │ │ │ │ +{
    │ │ │ │ +	m_done = true;
    │ │ │ │  
    │ │ │ │ -		struct piece_hash_request
    │ │ │ │ -		{
    │ │ │ │ -			time_point last_request = min_time();
    │ │ │ │ -			int num_requests = 0;
    │ │ │ │ -			bool have = false;
    │ │ │ │ -		};
    │ │ │ │ +#ifndef TORRENT_DISABLE_LOGGING
    │ │ │ │ +	get_node().observer()->log(dht_logger::traversal, "[%u] %s DONE, response %d, timeout %d"
    │ │ │ │ +		, id(), name(), num_responses(), num_timeouts());
    │ │ │ │ +#endif
    │ │ │ │  
    │ │ │ │ -		struct priority_block_request
    │ │ │ │ -		{
    │ │ │ │ -			priority_block_request(file_index_t const f, int const b)
    │ │ │ │ -				: file(f), block(b) {}
    │ │ │ │ -			file_index_t file;
    │ │ │ │ -			int block;
    │ │ │ │ -
    relevance 0../include/libtorrent/socks5_stream.hpp:197we could bind the socket here, since we know what the target endpoint is of the proxy

    we could bind the socket here, since we know what the │ │ │ │ -target endpoint is of the proxy

    ../include/libtorrent/socks5_stream.hpp:197

    			}, std::move(handler)));
    │ │ │ │ -	}
    │ │ │ │ +	m_put_callback(m_data, num_responses());
    │ │ │ │ +	traversal_algorithm::done();
    │ │ │ │ +}
    │ │ │ │  
    │ │ │ │ -private:
    │ │ │ │ +bool put_data::invoke(observer_ptr o)
    │ │ │ │ +{
    │ │ │ │ +	if (m_done) return false;
    │ │ │ │  
    │ │ │ │ -	template <typename Handler>
    │ │ │ │ -	void name_lookup(error_code const& e, tcp::resolver::results_type ips
    │ │ │ │ -		, Handler h)
    │ │ │ │ +
    auto* po = static_cast<put_data_observer*>(o.get()); │ │ │ │ +
    │ │ │ │ + entry e; │ │ │ │ + e["y"] = "q"; │ │ │ │ + e["q"] = "put"; │ │ │ │ + entry& a = e["a"]; │ │ │ │ + a["v"] = m_data.value(); │ │ │ │ + a["token"] = po->m_token; │ │ │ │ + if (m_data.is_mutable()) │ │ │ │ { │ │ │ │ - COMPLETE_ASYNC("socks5_stream::name_lookup"); │ │ │ │ - if (handle_error(e, std::move(h))) return; │ │ │ │ - │ │ │ │ - auto i = ips.begin(); │ │ │ │ - if (!m_sock.is_open()) │ │ │ │ + a["k"] = m_data.pk().bytes; │ │ │ │ + a["seq"] = m_data.seq().value; │ │ │ │ + a["sig"] = m_data.sig().bytes; │ │ │ │ + if (!m_data.salt().empty()) │ │ │ │ { │ │ │ │ - error_code ec; │ │ │ │ - m_sock.open(i->endpoint().protocol(), ec); │ │ │ │ - if (handle_error(ec, std::move(h))) return; │ │ │ │ + a["salt"] = m_data.salt(); │ │ │ │ } │ │ │ │ - │ │ │ │ -
    ADD_OUTSTANDING_ASYNC("socks5_stream::connected"); │ │ │ │ -
    m_sock.async_connect(i->endpoint(), wrap_allocator( │ │ │ │ - [this](error_code const& ec, Handler hn) │ │ │ │ - { connected(ec, std::move(hn)); }, std::move(h))); │ │ │ │ } │ │ │ │ │ │ │ │ - template <typename Handler> │ │ │ │ - void connected(error_code const& e, Handler h) │ │ │ │ - { │ │ │ │ - COMPLETE_ASYNC("socks5_stream::connected"); │ │ │ │ - if (handle_error(e, std::move(h))) return; │ │ │ │ - │ │ │ │ - using namespace libtorrent::aux; │ │ │ │ - if (m_version == 5) │ │ │ │ - { │ │ │ │ - // send SOCKS5 authentication methods │ │ │ │ - m_buffer.resize(m_user.empty()?3:4); │ │ │ │ - char* p = &m_buffer[0]; │ │ │ │ - write_uint8(5, p); // SOCKS VERSION 5 │ │ │ │ - if (m_user.empty()) │ │ │ │ - { │ │ │ │ - write_uint8(1, p); // 1 authentication method (no auth) │ │ │ │ - write_uint8(0, p); // no authentication │ │ │ │ - } │ │ │ │ - else │ │ │ │ - { │ │ │ │ - write_uint8(2, p); // 2 authentication methods │ │ │ │ - write_uint8(0, p); // no authentication │ │ │ │ - write_uint8(2, p); // username/password │ │ │ │ - } │ │ │ │ - ADD_OUTSTANDING_ASYNC("socks5_stream::handshake1"); │ │ │ │ -
    relevance 0../include/libtorrent/socket_type.hpp:60move to aux

    move to aux

    ../include/libtorrent/socket_type.hpp:60

    namespace libtorrent {
    │ │ │ │ -
    │ │ │ │ -// A type describing kinds of sockets involved in various operations or events.
    │ │ │ │ -enum class socket_type_t : std::uint8_t {
    │ │ │ │ -	tcp,
    │ │ │ │ -	socks5,
    │ │ │ │ -	http,
    │ │ │ │ -	utp,
    │ │ │ │ -	i2p,
    │ │ │ │ -	tcp_ssl,
    │ │ │ │ -	socks5_ssl,
    │ │ │ │ -	http_ssl,
    │ │ │ │ -	utp_ssl,
    │ │ │ │ -
    │ │ │ │ -#if TORRENT_ABI_VERSION <= 2
    │ │ │ │ -	udp TORRENT_DEPRECATED_ENUM = utp,
    │ │ │ │ -#endif
    │ │ │ │ -};
    │ │ │ │ +	m_node.stats_counters().inc_stats_counter(counters::dht_put_out);
    │ │ │ │  
    │ │ │ │ -// return a short human readable name for types of socket
    │ │ │ │ -
    char const* socket_type_name(socket_type_t); │ │ │ │ -
    │ │ │ │ + return m_node.m_rpc.invoke(e, o->target_ep(), o); │ │ │ │ } │ │ │ │ │ │ │ │ +} } // namespace libtorrent::dht │ │ │ │ +
    relevance 0../src/kademlia/dht_tracker.cpp:317pick the closest node rather than the first

    pick the closest node rather than the first

    ../src/kademlia/dht_tracker.cpp:317

    │ │ │ │ +#ifndef TORRENT_DISABLE_LOGGING
    │ │ │ │ +		m_log->log(dht_logger::tracker, "*** new write key*** %d nodes"
    │ │ │ │ +			, int(m_nodes.size()));
    │ │ │ │  #endif
    │ │ │ │ -
    relevance 0../include/libtorrent/torrent_info.hpp:729change the type to std::shared_ptr in C++17 it is used as if immutable, it cannot be const for technical reasons right now.

    change the type to std::shared_ptr in C++17 │ │ │ │ -it is used as if immutable, it cannot be const for technical reasons │ │ │ │ -right now.

    ../include/libtorrent/torrent_info.hpp:729

    │ │ │ │ -		// these are the collections from outside of the info-dict. These are
    │ │ │ │ -		// owning strings, since we only keep the info-section around, these
    │ │ │ │ -		// cannot be pointers into that buffer.
    │ │ │ │ -		std::vector<std::string> m_owned_collections;
    │ │ │ │ -
    │ │ │ │ -#if TORRENT_ABI_VERSION <= 2
    │ │ │ │ -		// if this is a merkle torrent, this is the merkle
    │ │ │ │ -		// tree. It has space for merkle_num_nodes(merkle_num_leafs(num_pieces))
    │ │ │ │ -		// hashes
    │ │ │ │ -		aux::vector<sha1_hash> m_merkle_tree;
    │ │ │ │ -#endif
    │ │ │ │ -
    │ │ │ │ -		// v2 merkle tree for each file
    │ │ │ │ -		// the actual hash buffers are always divisible by 32 (sha256_hash::size())
    │ │ │ │ -		aux::vector<aux::vector<char>, file_index_t> m_piece_layers;
    │ │ │ │ -
    │ │ │ │ -		// this is a copy of the info section from the torrent.
    │ │ │ │ -		// it use maintained in this flat format in order to
    │ │ │ │ -		// make it available through the metadata extension
    │ │ │ │ -
    boost::shared_array<char> m_info_section; │ │ │ │ -
    │ │ │ │ - // if a comment is found in the torrent file │ │ │ │ - // this will be set to that comment │ │ │ │ - std::string m_comment; │ │ │ │ - │ │ │ │ - // an optional string naming the software used │ │ │ │ - // to create the torrent file │ │ │ │ - std::string m_created_by; │ │ │ │ - │ │ │ │ - // the info section parsed. points into m_info_section │ │ │ │ - // parsed lazily │ │ │ │ - mutable bdecode_node m_info_dict; │ │ │ │ - │ │ │ │ - // if a creation date is found in the torrent file │ │ │ │ - // this will be set to that, otherwise it'll be │ │ │ │ - // 1970, Jan 1 │ │ │ │ - std::time_t m_creation_date = 0; │ │ │ │ + } │ │ │ │ │ │ │ │ - // the hash(es) that identify this torrent │ │ │ │ - info_hash_t m_info_hash; │ │ │ │ + void dht_tracker::update_storage_node_ids() │ │ │ │ + { │ │ │ │ + std::vector<sha1_hash> ids; │ │ │ │ + for (auto& n : m_nodes) │ │ │ │ + ids.push_back(n.second.dht.nid()); │ │ │ │ + m_storage.update_node_ids(ids); │ │ │ │ + } │ │ │ │ │ │ │ │ - // this is the offset into the m_info_section buffer to the first byte of │ │ │ │ - // the first SHA-1 hash │ │ │ │ - std::int32_t m_piece_hashes = 0; │ │ │ │ + node* dht_tracker::get_node(node_id const& id, std::string const& family_name) │ │ │ │ + { │ │ │ │ + TORRENT_UNUSED(id); │ │ │ │ + for (auto& n : m_nodes) │ │ │ │ + { │ │ │ │ +
    if (n.second.dht.protocol_family_name() == family_name) │ │ │ │ +
    return &n.second.dht; │ │ │ │ + } │ │ │ │ │ │ │ │ - // the number of bytes in m_info_section │ │ │ │ - std::int32_t m_info_section_size = 0; │ │ │ │ + return nullptr; │ │ │ │ + } │ │ │ │ │ │ │ │ - // this is used when creating a torrent. If there's │ │ │ │ - // only one file there are cases where it's impossible │ │ │ │ -
    relevance 0../include/libtorrent/announce_entry.hpp:76include the number of peers received from this tracker, at last announce

    include the number of peers received from this tracker, at last │ │ │ │ -announce

    ../include/libtorrent/announce_entry.hpp:76

    │ │ │ │ -	struct TORRENT_EXPORT announce_infohash
    │ │ │ │ +	void dht_tracker::get_peers(sha1_hash const& ih
    │ │ │ │ +		, std::function<void(std::vector<tcp::endpoint> const&)> f)
    │ │ │ │  	{
    │ │ │ │ -		// internal
    │ │ │ │ -		TORRENT_UNEXPORT announce_infohash();
    │ │ │ │ +		for (auto& n : m_nodes)
    │ │ │ │ +			n.second.dht.get_peers(ih, f, {}, {});
    │ │ │ │ +	}
    │ │ │ │  
    │ │ │ │ -		// if this tracker has returned an error or warning message
    │ │ │ │ -		// that message is stored here
    │ │ │ │ -		std::string message;
    │ │ │ │ +	void dht_tracker::announce(sha1_hash const& ih, int listen_port
    │ │ │ │ +		, announce_flags_t const flags
    │ │ │ │ +		, std::function<void(std::vector<tcp::endpoint> const&)> f)
    │ │ │ │ +	{
    │ │ │ │ +		for (auto& n : m_nodes)
    │ │ │ │ +			n.second.dht.announce(ih, listen_port, flags, f);
    │ │ │ │ +	}
    │ │ │ │  
    │ │ │ │ -		// if this tracker failed the last time it was contacted
    │ │ │ │ -		// this error code specifies what error occurred
    │ │ │ │ -		error_code last_error;
    │ │ │ │ +	void dht_tracker::sample_infohashes(udp::endpoint const& ep, sha1_hash const& target
    │ │ │ │ +		, std::function<void(node_id
    │ │ │ │ +			, time_duration
    │ │ │ │ +			, int, std::vector<sha1_hash>
    │ │ │ │ +			, std::vector<std::pair<sha1_hash, udp::endpoint>>)> f)
    │ │ │ │ +	{
    │ │ │ │ +		for (auto& n : m_nodes)
    │ │ │ │ +		{
    │ │ │ │ +			if (ep.protocol() != (n.first.get_external_address().is_v4() ? udp::v4() : udp::v6()))
    │ │ │ │ +
    relevance 0../src/kademlia/item.cpp:143implement ctor for entry from bdecode_node?

    implement ctor for entry from bdecode_node?

    ../src/kademlia/item.cpp:143

    	, secret_key const& sk)
    │ │ │ │ +{
    │ │ │ │ +	char str[1200];
    │ │ │ │ +	int const len = canonical_string(v, seq, salt, str);
    │ │ │ │  
    │ │ │ │ -		// the time of next tracker announce
    │ │ │ │ -		time_point32 next_announce = (time_point32::min)();
    │ │ │ │ +	return ed25519_sign({str, len}, pk, sk);
    │ │ │ │ +}
    │ │ │ │  
    │ │ │ │ -		// no announces before this time
    │ │ │ │ -		time_point32 min_announce = (time_point32::min)();
    │ │ │ │ +item::item(public_key const& pk, span<char const> salt)
    │ │ │ │ +	: m_salt(salt.data(), static_cast<std::size_t>(salt.size()))
    │ │ │ │ +	, m_pk(pk)
    │ │ │ │ +	, m_mutable(true)
    │ │ │ │ +{}
    │ │ │ │  
    │ │ │ │ -
    │ │ │ │ -
    // these are either -1 or the scrape information this tracker last │ │ │ │ - // responded with. *incomplete* is the current number of downloaders in │ │ │ │ - // the swarm, *complete* is the current number of seeds in the swarm and │ │ │ │ - // *downloaded* is the cumulative number of completed downloads of this │ │ │ │ - // torrent, since the beginning of time (from this tracker's point of │ │ │ │ - // view). │ │ │ │ +item::item(entry v) │ │ │ │ + : m_value(std::move(v)) │ │ │ │ +{} │ │ │ │ │ │ │ │ - // if this tracker has returned scrape data, these fields are filled in │ │ │ │ - // with valid numbers. Otherwise they are set to -1. ``incomplete`` counts │ │ │ │ - // the number of current downloaders. ``complete`` counts the number of │ │ │ │ - // current peers completed the download, or "seeds". ``downloaded`` is the │ │ │ │ - // cumulative number of completed downloads. │ │ │ │ - int scrape_incomplete = -1; │ │ │ │ - int scrape_complete = -1; │ │ │ │ - int scrape_downloaded = -1; │ │ │ │ +item::item(bdecode_node const& v) │ │ │ │ +{ │ │ │ │ +
    m_value = v; │ │ │ │ +
    } │ │ │ │ │ │ │ │ - // the number of times in a row we have failed to announce to this │ │ │ │ - // tracker. │ │ │ │ - std::uint8_t fails : 7; │ │ │ │ +item::item(entry v, span<char const> salt │ │ │ │ + , sequence_number const seq, public_key const& pk, secret_key const& sk) │ │ │ │ +{ │ │ │ │ + assign(std::move(v), salt, seq, pk, sk); │ │ │ │ +} │ │ │ │ │ │ │ │ - // true while we're waiting for a response from the tracker. │ │ │ │ - bool updating : 1; │ │ │ │ +void item::assign(entry v) │ │ │ │ +{ │ │ │ │ + m_mutable = false; │ │ │ │ + m_value = std::move(v); │ │ │ │ +} │ │ │ │ │ │ │ │ - // set to true when we get a valid response from an announce │ │ │ │ - // with event=started. If it is set, we won't send start in the subsequent │ │ │ │ - // announces. │ │ │ │ - bool start_sent : 1; │ │ │ │ +void item::assign(entry v, span<char const> salt │ │ │ │ + , sequence_number const seq, public_key const& pk, secret_key const& sk) │ │ │ │ +{ │ │ │ │ + std::array<char, 1000> buffer; │ │ │ │ + int const bsize = bencode(buffer.begin(), v); │ │ │ │ + TORRENT_ASSERT(bsize <= 1000); │ │ │ │ + m_sig = sign_mutable_item(span<char const>(buffer).first(bsize) │ │ │ │ + , salt, seq, pk, sk); │ │ │ │ + m_salt.assign(salt.data(), static_cast<std::size_t>(salt.size())); │ │ │ │ + m_pk = pk; │ │ │ │ + m_seq = seq; │ │ │ │ + m_mutable = true; │ │ │ │ + m_value = std::move(v); │ │ │ │ +} │ │ │ │ │ │ │ │ - // set to true when we send a event=completed. │ │ │ │ - bool complete_sent : 1; │ │ │ │ -
    relevance 0../include/libtorrent/torrent.hpp:280make this a raw pointer. perhaps keep the shared_ptr around further down the object to maintain an owner

    make this a raw pointer. perhaps keep the shared_ptr │ │ │ │ +void item::assign(bdecode_node const& v) │ │ │ │ +relevance 0../include/libtorrent/torrent.hpp:280make this a raw pointer. perhaps keep the shared_ptr around further down the object to maintain an owner

    make this a raw pointer. perhaps keep the shared_ptr │ │ │ │ around further down the object to maintain an owner

    ../include/libtorrent/torrent.hpp:280

    #endif
    │ │ │ │  	};
    │ │ │ │  
    │ │ │ │  	struct TORRENT_EXTRA_EXPORT torrent_hot_members
    │ │ │ │  	{
    │ │ │ │  		torrent_hot_members(aux::session_interface& ses
    │ │ │ │  			, add_torrent_params const& p, bool session_paused);
    │ │ │ │ @@ -10676,15 +10392,15 @@
    │ │ │ │  		// this is set to false as long as the connections
    │ │ │ │  		// of this torrent haven't been initialized. If we
    │ │ │ │  		// have metadata from the start, connections are
    │ │ │ │  		// initialized immediately, if we didn't have metadata,
    │ │ │ │  		// they are initialized right after files_checked().
    │ │ │ │  		// valid_resume_data() will return false as long as
    │ │ │ │  		// the connections aren't initialized, to avoid
    │ │ │ │ -
    relevance 0../include/libtorrent/torrent.hpp:463make graceful pause also finish all sending blocks before disconnecting

    make graceful pause also finish all sending blocks │ │ │ │ +relevance 0../include/libtorrent/torrent.hpp:463make graceful pause also finish all sending blocks before disconnecting

    make graceful pause also finish all sending blocks │ │ │ │ before disconnecting

    ../include/libtorrent/torrent.hpp:463

    │ │ │ │  		void on_resume_data_checked(status_t status, storage_error const& error);
    │ │ │ │  		void on_force_recheck(status_t status, storage_error const& error);
    │ │ │ │  		void on_piece_hashed(aux::vector<sha256_hash> block_hashes
    │ │ │ │  			, piece_index_t piece, sha1_hash const& piece_hash
    │ │ │ │  			, storage_error const& error);
    │ │ │ │  		void files_checked();
    │ │ │ │ @@ -10728,15 +10444,15 @@
    │ │ │ │  		void read_piece(piece_index_t);
    │ │ │ │  		void on_disk_read_complete(disk_buffer_holder, storage_error const&
    │ │ │ │  			, peer_request const&, std::shared_ptr<read_piece_struct>);
    │ │ │ │  
    │ │ │ │  		storage_mode_t storage_mode() const;
    │ │ │ │  
    │ │ │ │  		// this will flag the torrent as aborted. The main
    │ │ │ │ -
    relevance 0../include/libtorrent/torrent.hpp:600make this flag a combination of the other ones

    make this flag a combination │ │ │ │ +relevance 0../include/libtorrent/torrent.hpp:600make this flag a combination of the other ones

    make this flag a combination │ │ │ │ of the other ones

    ../include/libtorrent/torrent.hpp:600

    		void do_pause(bool was_paused = false);
    │ │ │ │  		void do_resume();
    │ │ │ │  
    │ │ │ │  		seconds32 finished_time() const;
    │ │ │ │  		seconds32 active_time() const;
    │ │ │ │  		seconds32 seeding_time() const;
    │ │ │ │  		seconds32 upload_mode_time() const;
    │ │ │ │ @@ -10780,15 +10496,15 @@
    │ │ │ │  		void set_piece_priority(piece_index_t index, download_priority_t priority);
    │ │ │ │  		download_priority_t piece_priority(piece_index_t index) const;
    │ │ │ │  
    │ │ │ │  		void prioritize_pieces(aux::vector<download_priority_t, piece_index_t> const& pieces);
    │ │ │ │  		void prioritize_piece_list(std::vector<std::pair<piece_index_t, download_priority_t>> const& pieces);
    │ │ │ │  		void piece_priorities(aux::vector<download_priority_t, piece_index_t>*) const;
    │ │ │ │  
    │ │ │ │ -
    relevance 0../include/libtorrent/torrent.hpp:1396this wastes 5 bits per file

    this wastes 5 bits per file

    ../include/libtorrent/torrent.hpp:1396

    #ifndef TORRENT_DISABLE_EXTENSIONS
    │ │ │ │ +
    relevance 0../include/libtorrent/torrent.hpp:1396this wastes 5 bits per file

    this wastes 5 bits per file

    ../include/libtorrent/torrent.hpp:1396

    #ifndef TORRENT_DISABLE_EXTENSIONS
    │ │ │ │  		std::list<std::shared_ptr<torrent_plugin>> m_extensions;
    │ │ │ │  #endif
    │ │ │ │  
    │ │ │ │  		// used for tracker announces
    │ │ │ │  		deadline_timer m_tracker_timer;
    │ │ │ │  
    │ │ │ │  		// used to detect when we are active or inactive for long enough
    │ │ │ │ @@ -10831,15 +10547,15 @@
    │ │ │ │  #if TORRENT_ABI_VERSION == 1
    │ │ │ │  		// deprecated in 1.1
    │ │ │ │  		std::string m_username;
    │ │ │ │  		std::string m_password;
    │ │ │ │  #endif
    │ │ │ │  
    │ │ │ │  		std::string m_save_path;
    │ │ │ │ -
    relevance 0../include/libtorrent/torrent.hpp:1711this member can probably be removed

    this member can probably be removed

    ../include/libtorrent/torrent.hpp:1711

    		unsigned int m_num_uploads:24;
    │ │ │ │ +
    relevance 0../include/libtorrent/torrent.hpp:1711this member can probably be removed

    this member can probably be removed

    ../include/libtorrent/torrent.hpp:1711

    		unsigned int m_num_uploads:24;
    │ │ │ │  
    │ │ │ │  		// 4 unused bits
    │ │ │ │  
    │ │ │ │  		// when this is true, this torrent supports peer exchange
    │ │ │ │  		bool m_enable_pex:1;
    │ │ │ │  
    │ │ │ │  		// set to true if the session IP filter applies to this
    │ │ │ │ @@ -10882,15 +10598,68 @@
    │ │ │ │  		// remember that this is an SSL torrent, so that we don't
    │ │ │ │  		// accidentally start seeding it without any authentication.
    │ │ │ │  		bool m_ssl_torrent:1;
    │ │ │ │  
    │ │ │ │  		// this is set to true if we're trying to delete the
    │ │ │ │  		// files belonging to it. When set, don't write any
    │ │ │ │  		// more blocks to disk!
    │ │ │ │ -
    relevance 0../include/libtorrent/proxy_base.hpp:207it would be nice to remember the bind port and bind once we know where the proxy is m_sock.bind(endpoint, ec);

    it would be nice to remember the bind port and bind once we know where the proxy is │ │ │ │ +relevance 0../include/libtorrent/torrent_info.hpp:729change the type to std::shared_ptr in C++17 it is used as if immutable, it cannot be const for technical reasons right now.

    change the type to std::shared_ptr in C++17 │ │ │ │ +it is used as if immutable, it cannot be const for technical reasons │ │ │ │ +right now.

    ../include/libtorrent/torrent_info.hpp:729

    │ │ │ │ +		// these are the collections from outside of the info-dict. These are
    │ │ │ │ +		// owning strings, since we only keep the info-section around, these
    │ │ │ │ +		// cannot be pointers into that buffer.
    │ │ │ │ +		std::vector<std::string> m_owned_collections;
    │ │ │ │ +
    │ │ │ │ +#if TORRENT_ABI_VERSION <= 2
    │ │ │ │ +		// if this is a merkle torrent, this is the merkle
    │ │ │ │ +		// tree. It has space for merkle_num_nodes(merkle_num_leafs(num_pieces))
    │ │ │ │ +		// hashes
    │ │ │ │ +		aux::vector<sha1_hash> m_merkle_tree;
    │ │ │ │ +#endif
    │ │ │ │ +
    │ │ │ │ +		// v2 merkle tree for each file
    │ │ │ │ +		// the actual hash buffers are always divisible by 32 (sha256_hash::size())
    │ │ │ │ +		aux::vector<aux::vector<char>, file_index_t> m_piece_layers;
    │ │ │ │ +
    │ │ │ │ +		// this is a copy of the info section from the torrent.
    │ │ │ │ +		// it use maintained in this flat format in order to
    │ │ │ │ +		// make it available through the metadata extension
    │ │ │ │ +
    boost::shared_array<char> m_info_section; │ │ │ │ +
    │ │ │ │ + // if a comment is found in the torrent file │ │ │ │ + // this will be set to that comment │ │ │ │ + std::string m_comment; │ │ │ │ + │ │ │ │ + // an optional string naming the software used │ │ │ │ + // to create the torrent file │ │ │ │ + std::string m_created_by; │ │ │ │ + │ │ │ │ + // the info section parsed. points into m_info_section │ │ │ │ + // parsed lazily │ │ │ │ + mutable bdecode_node m_info_dict; │ │ │ │ + │ │ │ │ + // if a creation date is found in the torrent file │ │ │ │ + // this will be set to that, otherwise it'll be │ │ │ │ + // 1970, Jan 1 │ │ │ │ + std::time_t m_creation_date = 0; │ │ │ │ + │ │ │ │ + // the hash(es) that identify this torrent │ │ │ │ + info_hash_t m_info_hash; │ │ │ │ + │ │ │ │ + // this is the offset into the m_info_section buffer to the first byte of │ │ │ │ + // the first SHA-1 hash │ │ │ │ + std::int32_t m_piece_hashes = 0; │ │ │ │ + │ │ │ │ + // the number of bytes in m_info_section │ │ │ │ + std::int32_t m_info_section_size = 0; │ │ │ │ + │ │ │ │ + // this is used when creating a torrent. If there's │ │ │ │ + // only one file there are cases where it's impossible │ │ │ │ +
    relevance 0../include/libtorrent/proxy_base.hpp:207it would be nice to remember the bind port and bind once we know where the proxy is m_sock.bind(endpoint, ec);

    it would be nice to remember the bind port and bind once we know where the proxy is │ │ │ │ m_sock.bind(endpoint, ec);

    ../include/libtorrent/proxy_base.hpp:207

    │ │ │ │  	void cancel()
    │ │ │ │  	{
    │ │ │ │  		m_sock.cancel();
    │ │ │ │  	}
    │ │ │ │  
    │ │ │ │  	void cancel(error_code& ec)
    │ │ │ │ @@ -10934,15 +10703,49 @@
    │ │ │ │  
    │ │ │ │  	void close(error_code& ec)
    │ │ │ │  	{
    │ │ │ │  		m_remote_endpoint = endpoint_type();
    │ │ │ │  		m_sock.close(ec);
    │ │ │ │  		m_resolver.cancel();
    │ │ │ │  	}
    │ │ │ │ -
    relevance 0../include/libtorrent/peer_connection_interface.hpp:51make this interface smaller!

    make this interface smaller!

    ../include/libtorrent/peer_connection_interface.hpp:51

    │ │ │ │ +
    relevance 0../include/libtorrent/performance_counters.hpp:485some space could be saved here by making gauges 32 bits

    some space could be saved here by making gauges 32 bits

    ../include/libtorrent/performance_counters.hpp:485

    relevance 0../include/libtorrent/performance_counters.hpp:486restore these to regular integers. Instead have one copy of the counters per thread and collect them at convenient synchronization points

    restore these to regular integers. Instead have one copy │ │ │ │ +of the counters per thread and collect them at convenient │ │ │ │ +synchronization points

    ../include/libtorrent/performance_counters.hpp:486

    #ifdef ATOMIC_LLONG_LOCK_FREE
    │ │ │ │ +#define TORRENT_COUNTER_NOEXCEPT noexcept
    │ │ │ │ +#else
    │ │ │ │ +#define TORRENT_COUNTER_NOEXCEPT
    │ │ │ │ +#endif
    │ │ │ │ +
    │ │ │ │ +		counters() TORRENT_COUNTER_NOEXCEPT;
    │ │ │ │ +
    │ │ │ │ +		counters(counters const&) TORRENT_COUNTER_NOEXCEPT;
    │ │ │ │ +		counters& operator=(counters const&) & TORRENT_COUNTER_NOEXCEPT;
    │ │ │ │ +
    │ │ │ │ +		// returns the new value
    │ │ │ │ +		std::int64_t inc_stats_counter(int c, std::int64_t value = 1) TORRENT_COUNTER_NOEXCEPT;
    │ │ │ │ +		std::int64_t operator[](int i) const TORRENT_COUNTER_NOEXCEPT;
    │ │ │ │ +
    │ │ │ │ +		void set_value(int c, std::int64_t value) TORRENT_COUNTER_NOEXCEPT;
    │ │ │ │ +		void blend_stats_counter(int c, std::int64_t value, int ratio) TORRENT_COUNTER_NOEXCEPT;
    │ │ │ │ +
    │ │ │ │ +	private:
    │ │ │ │ +
    │ │ │ │ +
    #ifdef ATOMIC_LLONG_LOCK_FREE │ │ │ │ +
    aux::array<std::atomic<std::int64_t>, num_counters> m_stats_counter; │ │ │ │ +#else │ │ │ │ + // if the atomic type isn't lock-free, use a single lock instead, for │ │ │ │ + // the whole array │ │ │ │ + mutable std::mutex m_mutex; │ │ │ │ + aux::array<std::int64_t, num_counters> m_stats_counter; │ │ │ │ +#endif │ │ │ │ + }; │ │ │ │ +} │ │ │ │ + │ │ │ │ +#endif │ │ │ │ +
    relevance 0../include/libtorrent/peer_connection_interface.hpp:51make this interface smaller!

    make this interface smaller!

    ../include/libtorrent/peer_connection_interface.hpp:51

    │ │ │ │  */
    │ │ │ │  
    │ │ │ │  #ifndef TORRENT_PEER_CONNECTION_INTERFACE_HPP
    │ │ │ │  #define TORRENT_PEER_CONNECTION_INTERFACE_HPP
    │ │ │ │  
    │ │ │ │  #include "libtorrent/fwd.hpp"
    │ │ │ │  #include "libtorrent/socket.hpp"
    │ │ │ │ @@ -10985,15 +10788,116 @@
    │ │ │ │  		virtual stat const& statistics() const = 0;
    │ │ │ │  		virtual void get_peer_info(peer_info& p) const = 0;
    │ │ │ │  #ifndef TORRENT_DISABLE_LOGGING
    │ │ │ │  		virtual bool should_log(peer_log_alert::direction_t direction) const = 0;
    │ │ │ │  		virtual void peer_log(peer_log_alert::direction_t direction
    │ │ │ │  			, char const* event, char const* fmt = "", ...) const noexcept TORRENT_FORMAT(4,5) = 0;
    │ │ │ │  #endif
    │ │ │ │ -
    relevance 0../include/libtorrent/upnp.hpp:162support using the windows API for UPnP operations as well

    support using the windows API for UPnP operations as well

    ../include/libtorrent/upnp.hpp:162

    {
    │ │ │ │ +
    relevance 0../include/libtorrent/piece_picker.hpp:802should this be allocated lazily?

    should this be allocated lazily?

    ../include/libtorrent/piece_picker.hpp:802

    		// download list it may live in now
    │ │ │ │ +		std::vector<downloading_piece>::iterator update_piece_state(
    │ │ │ │ +			std::vector<downloading_piece>::iterator dp);
    │ │ │ │ +
    │ │ │ │ +	private:
    │ │ │ │ +
    │ │ │ │ +#if TORRENT_USE_ASSERTS || TORRENT_USE_INVARIANT_CHECKS
    │ │ │ │ +		index_range<download_queue_t> categories() const
    │ │ │ │ +		{ return {{}, piece_picker::piece_pos::num_download_categories}; }
    │ │ │ │ +#endif
    │ │ │ │ +
    │ │ │ │ +		// the following vectors are mutable because they sometimes may
    │ │ │ │ +		// be updated lazily, triggered by const functions
    │ │ │ │ +
    │ │ │ │ +		// this maps indices to number of peers that has this piece and
    │ │ │ │ +		// index into the m_piece_info vectors.
    │ │ │ │ +		// piece_pos::we_have_index means that we have the piece, so it
    │ │ │ │ +		// doesn't exist in the piece_info buckets
    │ │ │ │ +		// pieces with the filtered flag set doesn't have entries in
    │ │ │ │ +		// the m_piece_info buckets either
    │ │ │ │ +
    mutable aux::vector<piece_pos, piece_index_t> m_piece_map; │ │ │ │ +
    │ │ │ │ + // tracks the number of bytes in a specific piece that are part of a pad │ │ │ │ + // file. The padding is assumed to be at the end of the piece, and the │ │ │ │ + // blocks covered by the pad bytes are not picked by the piece picker │ │ │ │ + std::unordered_map<piece_index_t, int> m_pads_in_piece; │ │ │ │ + │ │ │ │ + // when the adjacent_piece affinity is enabled, this contains the most │ │ │ │ + // recent "extents" of adjacent pieces that have been requested from │ │ │ │ + // this is mutable because it's updated by functions to pick pieces, which │ │ │ │ + // are const. That's an efficient place to update it, since it's being │ │ │ │ + // traversed already. │ │ │ │ + mutable std::vector<piece_extent_t> m_recent_extents; │ │ │ │ + │ │ │ │ + // the number of bytes of pad file set in this piece picker │ │ │ │ + int m_num_pad_bytes = 0; │ │ │ │ + │ │ │ │ + // the number of pad blocks that we already have │ │ │ │ + int m_have_pad_bytes = 0; │ │ │ │ + │ │ │ │ + // the number of pad blocks part of filtered pieces we don't have │ │ │ │ + int m_filtered_pad_bytes = 0; │ │ │ │ + │ │ │ │ + // the number of pad blocks we have that are also filtered │ │ │ │ + int m_have_filtered_pad_bytes = 0; │ │ │ │ + │ │ │ │ + // the number of seeds. These are not added to │ │ │ │ + // the availability counters of the pieces │ │ │ │ + int m_seeds = 0; │ │ │ │ + │ │ │ │ + // the number of pieces that have passed the hash check │ │ │ │ +
    relevance 0../include/libtorrent/piece_picker.hpp:877it would be more intuitive to account "wanted" pieces instead of filtered

    it would be more intuitive to account "wanted" pieces │ │ │ │ +instead of filtered

    ../include/libtorrent/piece_picker.hpp:877

    │ │ │ │ +		// this holds the information of the blocks in partially downloaded
    │ │ │ │ +		// pieces. the downloading_piece::info index point into this vector for
    │ │ │ │ +		// its storage
    │ │ │ │ +		aux::vector<block_info> m_block_info;
    │ │ │ │ +
    │ │ │ │ +		// these are block ranges in m_block_info that are free. The numbers
    │ │ │ │ +		// in here, when multiplied by blocks_per_piece is the index to the
    │ │ │ │ +		// first block in the range that's free to use by a new downloading_piece.
    │ │ │ │ +		// this is a free-list.
    │ │ │ │ +		std::vector<std::uint16_t> m_free_block_infos;
    │ │ │ │ +
    │ │ │ │ +		std::uint16_t m_blocks_in_last_piece = 0;
    │ │ │ │ +		int m_piece_size = 0;
    │ │ │ │ +		std::int64_t m_total_size = 0;
    │ │ │ │ +
    │ │ │ │ +		// the number of filtered pieces that we don't already
    │ │ │ │ +		// have. total_number_of_pieces - number_of_pieces_we_have
    │ │ │ │ +		// - num_filtered is supposed to the number of pieces
    │ │ │ │ +		// we still want to download
    │ │ │ │ +
    int m_num_filtered = 0; │ │ │ │ +
    │ │ │ │ + // the number of pieces we have that also are filtered │ │ │ │ + int m_num_have_filtered = 0; │ │ │ │ + │ │ │ │ + // we have all pieces in the range [0, m_cursor) │ │ │ │ + // m_cursor is the first piece we don't have │ │ │ │ + piece_index_t m_cursor{0}; │ │ │ │ + │ │ │ │ + // we have all pieces in the range [m_reverse_cursor, end) │ │ │ │ + // m_reverse_cursor is the first piece where we also have │ │ │ │ + // all the subsequent pieces │ │ │ │ + piece_index_t m_reverse_cursor{0}; │ │ │ │ + │ │ │ │ + // the number of pieces we have (i.e. passed + flushed). │ │ │ │ + // This includes pieces that we have filtered but still have │ │ │ │ + int m_num_have = 0; │ │ │ │ + │ │ │ │ + // if this is set to true, it means update_pieces() │ │ │ │ + // has to be called before accessing m_pieces. │ │ │ │ + mutable bool m_dirty = false; │ │ │ │ + public: │ │ │ │ + │ │ │ │ + enum { max_pieces = (std::numeric_limits<int>::max)() - 1 }; │ │ │ │ + │ │ │ │ + }; │ │ │ │ +} │ │ │ │ + │ │ │ │ +#endif // TORRENT_PIECE_PICKER_HPP_INCLUDED │ │ │ │ +
    relevance 0../include/libtorrent/upnp.hpp:162support using the windows API for UPnP operations as well

    support using the windows API for UPnP operations as well

    ../include/libtorrent/upnp.hpp:162

    {
    │ │ │ │  	bool in_error_code = false;
    │ │ │ │  	bool exit = false;
    │ │ │ │  	int error_code = -1;
    │ │ │ │  };
    │ │ │ │  
    │ │ │ │  struct ip_address_parse_state: error_code_parse_state
    │ │ │ │  {
    │ │ │ │ @@ -11036,49 +10940,272 @@
    │ │ │ │  	// ``local_port`` is the port in the local machine that the mapping should forward
    │ │ │ │  	// to.
    │ │ │ │  	//
    │ │ │ │  	// The return value is an index that identifies this port mapping. This is used
    │ │ │ │  	// to refer to mappings that fails or succeeds in the portmap_error_alert_ and
    │ │ │ │  	// portmap_alert_ respectively. If The mapping fails immediately, the return value
    │ │ │ │  	// is -1, which means failure. There will not be any error alert notification for
    │ │ │ │ -
    relevance 0../include/libtorrent/performance_counters.hpp:485some space could be saved here by making gauges 32 bits

    some space could be saved here by making gauges 32 bits

    ../include/libtorrent/performance_counters.hpp:485

    relevance 0../include/libtorrent/performance_counters.hpp:486restore these to regular integers. Instead have one copy of the counters per thread and collect them at convenient synchronization points

    restore these to regular integers. Instead have one copy │ │ │ │ -of the counters per thread and collect them at convenient │ │ │ │ -synchronization points

    ../include/libtorrent/performance_counters.hpp:486

    #ifdef ATOMIC_LLONG_LOCK_FREE
    │ │ │ │ -#define TORRENT_COUNTER_NOEXCEPT noexcept
    │ │ │ │ -#else
    │ │ │ │ -#define TORRENT_COUNTER_NOEXCEPT
    │ │ │ │ -#endif
    │ │ │ │ +
    relevance 0../include/libtorrent/socks5_stream.hpp:197we could bind the socket here, since we know what the target endpoint is of the proxy

    we could bind the socket here, since we know what the │ │ │ │ +target endpoint is of the proxy

    ../include/libtorrent/socks5_stream.hpp:197

    			}, std::move(handler)));
    │ │ │ │ +	}
    │ │ │ │  
    │ │ │ │ -		counters() TORRENT_COUNTER_NOEXCEPT;
    │ │ │ │ +private:
    │ │ │ │  
    │ │ │ │ -		counters(counters const&) TORRENT_COUNTER_NOEXCEPT;
    │ │ │ │ -		counters& operator=(counters const&) & TORRENT_COUNTER_NOEXCEPT;
    │ │ │ │ +	template <typename Handler>
    │ │ │ │ +	void name_lookup(error_code const& e, tcp::resolver::results_type ips
    │ │ │ │ +		, Handler h)
    │ │ │ │ +	{
    │ │ │ │ +		COMPLETE_ASYNC("socks5_stream::name_lookup");
    │ │ │ │ +		if (handle_error(e, std::move(h))) return;
    │ │ │ │  
    │ │ │ │ -		// returns the new value
    │ │ │ │ -		std::int64_t inc_stats_counter(int c, std::int64_t value = 1) TORRENT_COUNTER_NOEXCEPT;
    │ │ │ │ -		std::int64_t operator[](int i) const TORRENT_COUNTER_NOEXCEPT;
    │ │ │ │ +		auto i = ips.begin();
    │ │ │ │ +		if (!m_sock.is_open())
    │ │ │ │ +		{
    │ │ │ │ +			error_code ec;
    │ │ │ │ +			m_sock.open(i->endpoint().protocol(), ec);
    │ │ │ │ +			if (handle_error(ec, std::move(h))) return;
    │ │ │ │ +		}
    │ │ │ │  
    │ │ │ │ -		void set_value(int c, std::int64_t value) TORRENT_COUNTER_NOEXCEPT;
    │ │ │ │ -		void blend_stats_counter(int c, std::int64_t value, int ratio) TORRENT_COUNTER_NOEXCEPT;
    │ │ │ │ +
    ADD_OUTSTANDING_ASYNC("socks5_stream::connected"); │ │ │ │ +
    m_sock.async_connect(i->endpoint(), wrap_allocator( │ │ │ │ + [this](error_code const& ec, Handler hn) │ │ │ │ + { connected(ec, std::move(hn)); }, std::move(h))); │ │ │ │ + } │ │ │ │ │ │ │ │ - private: │ │ │ │ + template <typename Handler> │ │ │ │ + void connected(error_code const& e, Handler h) │ │ │ │ + { │ │ │ │ + COMPLETE_ASYNC("socks5_stream::connected"); │ │ │ │ + if (handle_error(e, std::move(h))) return; │ │ │ │ │ │ │ │ -
    #ifdef ATOMIC_LLONG_LOCK_FREE │ │ │ │ -
    aux::array<std::atomic<std::int64_t>, num_counters> m_stats_counter; │ │ │ │ -#else │ │ │ │ - // if the atomic type isn't lock-free, use a single lock instead, for │ │ │ │ - // the whole array │ │ │ │ - mutable std::mutex m_mutex; │ │ │ │ - aux::array<std::int64_t, num_counters> m_stats_counter; │ │ │ │ -#endif │ │ │ │ - }; │ │ │ │ + using namespace libtorrent::aux; │ │ │ │ + if (m_version == 5) │ │ │ │ + { │ │ │ │ + // send SOCKS5 authentication methods │ │ │ │ + m_buffer.resize(m_user.empty()?3:4); │ │ │ │ + char* p = &m_buffer[0]; │ │ │ │ + write_uint8(5, p); // SOCKS VERSION 5 │ │ │ │ + if (m_user.empty()) │ │ │ │ + { │ │ │ │ + write_uint8(1, p); // 1 authentication method (no auth) │ │ │ │ + write_uint8(0, p); // no authentication │ │ │ │ + } │ │ │ │ + else │ │ │ │ + { │ │ │ │ + write_uint8(2, p); // 2 authentication methods │ │ │ │ + write_uint8(0, p); // no authentication │ │ │ │ + write_uint8(2, p); // username/password │ │ │ │ + } │ │ │ │ + ADD_OUTSTANDING_ASYNC("socks5_stream::handshake1"); │ │ │ │ +
    relevance 0../include/libtorrent/string_view.hpp:40replace this by the standard string_view in C++17

    replace this by the standard string_view in C++17

    ../include/libtorrent/string_view.hpp:40

    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    │ │ │ │ +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    │ │ │ │ +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
    │ │ │ │ +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    │ │ │ │ +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    │ │ │ │ +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    │ │ │ │ +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    │ │ │ │ +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    │ │ │ │ +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    │ │ │ │ +POSSIBILITY OF SUCH DAMAGE.
    │ │ │ │ +
    │ │ │ │ +*/
    │ │ │ │ +
    │ │ │ │ +#ifndef TORRENT_STRING_VIEW_HPP_INCLUDED
    │ │ │ │ +#define TORRENT_STRING_VIEW_HPP_INCLUDED
    │ │ │ │ +
    │ │ │ │ +#include <boost/version.hpp>
    │ │ │ │ +
    │ │ │ │ +#include "libtorrent/aux_/disable_warnings_push.hpp"
    │ │ │ │ +
    │ │ │ │ +
    │ │ │ │ +
    #if BOOST_VERSION < 106100 │ │ │ │ +#include <boost/utility/string_ref.hpp> │ │ │ │ +#include <cstring> // for strchr │ │ │ │ +namespace libtorrent { │ │ │ │ + │ │ │ │ +using string_view = boost::string_ref; │ │ │ │ +using wstring_view = boost::wstring_ref; │ │ │ │ + │ │ │ │ +// internal │ │ │ │ +inline string_view::size_type find_first_of(string_view const v, char const c │ │ │ │ + , string_view::size_type pos) │ │ │ │ +{ │ │ │ │ + while (pos < v.size()) │ │ │ │ + { │ │ │ │ + if (v[pos] == c) return pos; │ │ │ │ + ++pos; │ │ │ │ + } │ │ │ │ + return string_view::npos; │ │ │ │ } │ │ │ │ │ │ │ │ +// internal │ │ │ │ +inline string_view::size_type find_first_of(string_view const v, char const* c │ │ │ │ + , string_view::size_type pos) │ │ │ │ +{ │ │ │ │ + while (pos < v.size()) │ │ │ │ + { │ │ │ │ + if (std::strchr(c, v[pos]) != nullptr) return pos; │ │ │ │ + ++pos; │ │ │ │ + } │ │ │ │ + return string_view::npos; │ │ │ │ +
    relevance 0../include/libtorrent/identify_client.hpp:48hide this declaration when deprecated functions are disabled, and remove its internal use

    hide this declaration when deprecated functions are disabled, and │ │ │ │ +remove its internal use

    ../include/libtorrent/identify_client.hpp:48

    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    │ │ │ │ +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    │ │ │ │ +POSSIBILITY OF SUCH DAMAGE.
    │ │ │ │ +
    │ │ │ │ +*/
    │ │ │ │ +
    │ │ │ │ +#ifndef TORRENT_IDENTIFY_CLIENT_HPP_INCLUDED
    │ │ │ │ +#define TORRENT_IDENTIFY_CLIENT_HPP_INCLUDED
    │ │ │ │ +
    │ │ │ │ +#include "libtorrent/config.hpp"
    │ │ │ │ +
    │ │ │ │ +#if TORRENT_ABI_VERSION == 1
    │ │ │ │ +#include "libtorrent/aux_/disable_warnings_push.hpp"
    │ │ │ │ +#include <boost/optional.hpp>
    │ │ │ │ +#include "libtorrent/aux_/disable_warnings_pop.hpp"
    │ │ │ │  #endif
    │ │ │ │ -
    relevance 0../include/libtorrent/peer_connection.hpp:218make this a raw pointer (to save size in the first cache line) and make the constructor take a raw pointer. torrent objects should always outlive their peers

    make this a raw pointer (to save size in │ │ │ │ + │ │ │ │ +#include "libtorrent/peer_id.hpp" │ │ │ │ +#include "libtorrent/fingerprint.hpp" │ │ │ │ + │ │ │ │ +
    namespace libtorrent { │ │ │ │ +
    │ │ │ │ +namespace aux { │ │ │ │ + │ │ │ │ + TORRENT_EXTRA_EXPORT │ │ │ │ + std::string identify_client_impl(const peer_id& p); │ │ │ │ + │ │ │ │ +} │ │ │ │ + │ │ │ │ + // these functions don't really need to be public. This mechanism of │ │ │ │ + // advertising client software and version is also out-dated. │ │ │ │ + │ │ │ │ + // This function can can be used 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. │ │ │ │ + TORRENT_DEPRECATED_EXPORT │ │ │ │ + std::string identify_client(const peer_id& p); │ │ │ │ + │ │ │ │ +#if TORRENT_ABI_VERSION == 1 │ │ │ │ + │ │ │ │ +#include "libtorrent/aux_/disable_deprecation_warnings_push.hpp" │ │ │ │ + │ │ │ │ + // Returns an optional fingerprint if any can be identified from the peer │ │ │ │ + // id. This can be used to automate the identification of clients. It will │ │ │ │ + // not be able to identify peers with non- standard encodings. Only Azureus │ │ │ │ + // style, Shadow's style and Mainline style. │ │ │ │ + TORRENT_DEPRECATED_EXPORT │ │ │ │ + boost::optional<fingerprint> │ │ │ │ + client_fingerprint(peer_id const& p); │ │ │ │ + │ │ │ │ +#include "libtorrent/aux_/disable_warnings_pop.hpp" │ │ │ │ +relevance 0../include/libtorrent/i2p_stream.hpp:539make this a string_view

    make this a string_view

    ../include/libtorrent/i2p_stream.hpp:539

    │ │ │ │ +		char tmp[20];
    │ │ │ │ +		aux::random_bytes(tmp);
    │ │ │ │ +		m_session_id.resize(sizeof(tmp)*2);
    │ │ │ │ +		aux::to_hex(tmp, &m_session_id[0]);
    │ │ │ │ +
    │ │ │ │ +		m_sam_socket = std::make_shared<i2p_stream>(m_io_service);
    │ │ │ │ +		m_sam_socket->set_proxy(m_hostname, m_port);
    │ │ │ │ +		m_sam_socket->set_command(i2p_stream::cmd_create_session);
    │ │ │ │ +		m_sam_socket->set_session_id(m_session_id.c_str());
    │ │ │ │ +		m_sam_socket->set_session_options(session_options);
    │ │ │ │ +
    │ │ │ │ +		ADD_OUTSTANDING_ASYNC("i2p_stream::on_sam_connect");
    │ │ │ │ +		m_sam_socket->async_connect(tcp::endpoint(), wrap_allocator(
    │ │ │ │ +			[this,s=m_sam_socket](error_code const& ec, Handler hn) {
    │ │ │ │ +				on_sam_connect(ec, s, std::move(hn));
    │ │ │ │ +			}, std::move(handler)));
    │ │ │ │ +	}
    │ │ │ │ +	void close(error_code&);
    │ │ │ │ +
    │ │ │ │ +
    char const* session_id() const { return m_session_id.c_str(); } │ │ │ │ +
    std::string const& local_endpoint() const { return m_i2p_local_endpoint; } │ │ │ │ + │ │ │ │ + template <typename Handler> │ │ │ │ + void async_name_lookup(char const* name, Handler handler) │ │ │ │ + { │ │ │ │ + if (m_state == sam_idle && m_name_lookup.empty() && is_open()) │ │ │ │ + do_name_lookup(name, std::move(handler)); │ │ │ │ + else │ │ │ │ + m_name_lookup.emplace_back(std::string(name) │ │ │ │ + , std::move(handler)); │ │ │ │ + } │ │ │ │ + │ │ │ │ +private: │ │ │ │ + │ │ │ │ + template <typename Handler> │ │ │ │ + void on_sam_connect(error_code const& ec, std::shared_ptr<i2p_stream>, Handler h) │ │ │ │ + { │ │ │ │ + COMPLETE_ASYNC("i2p_stream::on_sam_connect"); │ │ │ │ + m_state = sam_idle; │ │ │ │ + │ │ │ │ + if (ec) │ │ │ │ + { │ │ │ │ + h(ec); │ │ │ │ + return; │ │ │ │ + } │ │ │ │ + │ │ │ │ + do_name_lookup("ME", wrap_allocator( │ │ │ │ + [this](error_code const& e, char const* dst, Handler hn) { │ │ │ │ + set_local_endpoint(e, dst, std::move(hn)); │ │ │ │ + }, std::move(h))); │ │ │ │ +
    relevance 0../include/libtorrent/hash_picker.hpp:155support batched adding of block hashes for reduced overhead?

    support batched adding of block hashes for reduced overhead?

    ../include/libtorrent/hash_picker.hpp:155

    		// the number of hashes in the range
    │ │ │ │ +		int count = 0;
    │ │ │ │ +		int proof_layers = 0;
    │ │ │ │ +	};
    │ │ │ │ +
    │ │ │ │ +	// validates the hash_request, to ensure its invariant as well as matching
    │ │ │ │ +	// the torrent's file_storage and the number of hashes accompanying the
    │ │ │ │ +	// request
    │ │ │ │ +	TORRENT_EXTRA_EXPORT
    │ │ │ │ +	bool validate_hash_request(hash_request const& hr, file_storage const& fs);
    │ │ │ │ +
    │ │ │ │ +	class TORRENT_EXTRA_EXPORT hash_picker
    │ │ │ │ +	{
    │ │ │ │ +	public:
    │ │ │ │ +		hash_picker(file_storage const& files
    │ │ │ │ +			, aux::vector<aux::merkle_tree, file_index_t>& trees);
    │ │ │ │ +
    │ │ │ │ +		hash_request pick_hashes(typed_bitfield<piece_index_t> const& pieces);
    │ │ │ │ +
    │ │ │ │ +		add_hashes_result add_hashes(hash_request const& req, span<sha256_hash const> hashes);
    │ │ │ │ +
    set_block_hash_result set_block_hash(piece_index_t piece, int offset, sha256_hash const& h); │ │ │ │ +
    void hashes_rejected(hash_request const& req); │ │ │ │ + void verify_block_hashes(piece_index_t index); │ │ │ │ + │ │ │ │ + // do we know the piece layer hash for a piece │ │ │ │ + bool have_hash(piece_index_t index) const; │ │ │ │ + // do we know all the block hashes for a file? │ │ │ │ + bool have_all(file_index_t file) const; │ │ │ │ + bool have_all() const; │ │ │ │ + bool piece_verified(piece_index_t piece) const; │ │ │ │ + │ │ │ │ + int piece_layer() const { return m_piece_layer; } │ │ │ │ + │ │ │ │ + private: │ │ │ │ + // returns the number of proof layers needed to verify the node's hash │ │ │ │ + int layers_to_verify(node_index idx) const; │ │ │ │ + int file_num_layers(file_index_t idx) const; │ │ │ │ + │ │ │ │ + struct piece_hash_request │ │ │ │ + { │ │ │ │ + time_point last_request = min_time(); │ │ │ │ + int num_requests = 0; │ │ │ │ + bool have = false; │ │ │ │ + }; │ │ │ │ + │ │ │ │ + struct priority_block_request │ │ │ │ + { │ │ │ │ + priority_block_request(file_index_t const f, int const b) │ │ │ │ + : file(f), block(b) {} │ │ │ │ + file_index_t file; │ │ │ │ + int block; │ │ │ │ +
    relevance 0../include/libtorrent/peer_connection.hpp:218make this a raw pointer (to save size in the first cache line) and make the constructor take a raw pointer. torrent objects should always outlive their peers

    make this a raw pointer (to save size in │ │ │ │ the first cache line) and make the constructor │ │ │ │ take a raw pointer. torrent objects should always │ │ │ │ outlive their peers

    ../include/libtorrent/peer_connection.hpp:218

    			, m_snubbed(false)
    │ │ │ │  			, m_interesting(false)
    │ │ │ │  			, m_choked(true)
    │ │ │ │  			, m_ignore_stats(false)
    │ │ │ │  		{}
    │ │ │ │ @@ -11124,15 +11251,15 @@
    │ │ │ │  		// time out is reached.
    │ │ │ │  		bool m_connecting:1;
    │ │ │ │  
    │ │ │ │  		// this is set to true if the last time we tried to
    │ │ │ │  		// pick a piece to download, we could only find
    │ │ │ │  		// blocks that were already requested from other
    │ │ │ │  		// peers. In this case, we should not try to pick
    │ │ │ │ -
    relevance 0../include/libtorrent/peer_connection.hpp:1026factor this out into its own class with a virtual interface torrent and session should implement this interface

    factor this out into its own class with a virtual interface │ │ │ │ +relevance 0../include/libtorrent/peer_connection.hpp:1026factor this out into its own class with a virtual interface torrent and session should implement this interface

    factor this out into its own class with a virtual interface │ │ │ │ torrent and session should implement this interface

    ../include/libtorrent/peer_connection.hpp:1026

    │ │ │ │  		// the local endpoint for this peer, i.e. our address
    │ │ │ │  		// and our port. If this is set for outgoing connections
    │ │ │ │  		// before the connection completes, it means we want to
    │ │ │ │  		// force the connection to be bound to the specified interface.
    │ │ │ │  		// if it ends up being bound to a different local IP, the connection
    │ │ │ │  		// is closed.
    │ │ │ │ @@ -11176,255 +11303,92 @@
    │ │ │ │  		// let plugins control flags that should always be set
    │ │ │ │  		picker_options_t m_picker_options{};
    │ │ │ │  
    │ │ │ │  		// the number of invalid piece-requests
    │ │ │ │  		// we have got from this peer. If the request
    │ │ │ │  		// queue gets empty, and there have been
    │ │ │ │  		// invalid requests, we can assume the
    │ │ │ │ -
    relevance 0../include/libtorrent/identify_client.hpp:48hide this declaration when deprecated functions are disabled, and remove its internal use

    hide this declaration when deprecated functions are disabled, and │ │ │ │ -remove its internal use

    ../include/libtorrent/identify_client.hpp:48

    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    │ │ │ │ -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    │ │ │ │ -POSSIBILITY OF SUCH DAMAGE.
    │ │ │ │ +
    relevance 0../include/libtorrent/socket_type.hpp:60move to aux

    move to aux

    ../include/libtorrent/socket_type.hpp:60

    namespace libtorrent {
    │ │ │ │  
    │ │ │ │ -*/
    │ │ │ │ -
    │ │ │ │ -#ifndef TORRENT_IDENTIFY_CLIENT_HPP_INCLUDED
    │ │ │ │ -#define TORRENT_IDENTIFY_CLIENT_HPP_INCLUDED
    │ │ │ │ -
    │ │ │ │ -#include "libtorrent/config.hpp"
    │ │ │ │ +// A type describing kinds of sockets involved in various operations or events.
    │ │ │ │ +enum class socket_type_t : std::uint8_t {
    │ │ │ │ +	tcp,
    │ │ │ │ +	socks5,
    │ │ │ │ +	http,
    │ │ │ │ +	utp,
    │ │ │ │ +	i2p,
    │ │ │ │ +	tcp_ssl,
    │ │ │ │ +	socks5_ssl,
    │ │ │ │ +	http_ssl,
    │ │ │ │ +	utp_ssl,
    │ │ │ │  
    │ │ │ │ -#if TORRENT_ABI_VERSION == 1
    │ │ │ │ -#include "libtorrent/aux_/disable_warnings_push.hpp"
    │ │ │ │ -#include <boost/optional.hpp>
    │ │ │ │ -#include "libtorrent/aux_/disable_warnings_pop.hpp"
    │ │ │ │ +#if TORRENT_ABI_VERSION <= 2
    │ │ │ │ +	udp TORRENT_DEPRECATED_ENUM = utp,
    │ │ │ │  #endif
    │ │ │ │ +};
    │ │ │ │  
    │ │ │ │ -#include "libtorrent/peer_id.hpp"
    │ │ │ │ -#include "libtorrent/fingerprint.hpp"
    │ │ │ │ -
    │ │ │ │ -
    namespace libtorrent { │ │ │ │ +// return a short human readable name for types of socket │ │ │ │ +
    char const* socket_type_name(socket_type_t); │ │ │ │
    │ │ │ │ -namespace aux { │ │ │ │ - │ │ │ │ - TORRENT_EXTRA_EXPORT │ │ │ │ - std::string identify_client_impl(const peer_id& p); │ │ │ │ - │ │ │ │ } │ │ │ │ │ │ │ │ - // these functions don't really need to be public. This mechanism of │ │ │ │ - // advertising client software and version is also out-dated. │ │ │ │ - │ │ │ │ - // This function can can be used 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. │ │ │ │ - TORRENT_DEPRECATED_EXPORT │ │ │ │ - std::string identify_client(const peer_id& p); │ │ │ │ - │ │ │ │ -#if TORRENT_ABI_VERSION == 1 │ │ │ │ - │ │ │ │ -#include "libtorrent/aux_/disable_deprecation_warnings_push.hpp" │ │ │ │ - │ │ │ │ - // Returns an optional fingerprint if any can be identified from the peer │ │ │ │ - // id. This can be used to automate the identification of clients. It will │ │ │ │ - // not be able to identify peers with non- standard encodings. Only Azureus │ │ │ │ - // style, Shadow's style and Mainline style. │ │ │ │ - TORRENT_DEPRECATED_EXPORT │ │ │ │ - boost::optional<fingerprint> │ │ │ │ - client_fingerprint(peer_id const& p); │ │ │ │ - │ │ │ │ -#include "libtorrent/aux_/disable_warnings_pop.hpp" │ │ │ │ -
    relevance 0../include/libtorrent/string_view.hpp:40replace this by the standard string_view in C++17

    replace this by the standard string_view in C++17

    ../include/libtorrent/string_view.hpp:40

    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    │ │ │ │ -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    │ │ │ │ -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
    │ │ │ │ -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    │ │ │ │ -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    │ │ │ │ -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    │ │ │ │ -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    │ │ │ │ -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    │ │ │ │ -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    │ │ │ │ -POSSIBILITY OF SUCH DAMAGE.
    │ │ │ │ -
    │ │ │ │ -*/
    │ │ │ │ -
    │ │ │ │ -#ifndef TORRENT_STRING_VIEW_HPP_INCLUDED
    │ │ │ │ -#define TORRENT_STRING_VIEW_HPP_INCLUDED
    │ │ │ │ -
    │ │ │ │ -#include <boost/version.hpp>
    │ │ │ │ -
    │ │ │ │ -#include "libtorrent/aux_/disable_warnings_push.hpp"
    │ │ │ │ -
    │ │ │ │ -
    │ │ │ │ -
    #if BOOST_VERSION < 106100 │ │ │ │ -#include <boost/utility/string_ref.hpp> │ │ │ │ -#include <cstring> // for strchr │ │ │ │ -namespace libtorrent { │ │ │ │ - │ │ │ │ -using string_view = boost::string_ref; │ │ │ │ -using wstring_view = boost::wstring_ref; │ │ │ │ - │ │ │ │ -// internal │ │ │ │ -inline string_view::size_type find_first_of(string_view const v, char const c │ │ │ │ - , string_view::size_type pos) │ │ │ │ -{ │ │ │ │ - while (pos < v.size()) │ │ │ │ - { │ │ │ │ - if (v[pos] == c) return pos; │ │ │ │ - ++pos; │ │ │ │ - } │ │ │ │ - return string_view::npos; │ │ │ │ -} │ │ │ │ - │ │ │ │ -// internal │ │ │ │ -inline string_view::size_type find_first_of(string_view const v, char const* c │ │ │ │ - , string_view::size_type pos) │ │ │ │ -{ │ │ │ │ - while (pos < v.size()) │ │ │ │ - { │ │ │ │ - if (std::strchr(c, v[pos]) != nullptr) return pos; │ │ │ │ - ++pos; │ │ │ │ - } │ │ │ │ - return string_view::npos; │ │ │ │ -
    relevance 0../include/libtorrent/piece_picker.hpp:802should this be allocated lazily?

    should this be allocated lazily?

    ../include/libtorrent/piece_picker.hpp:802

    		// download list it may live in now
    │ │ │ │ -		std::vector<downloading_piece>::iterator update_piece_state(
    │ │ │ │ -			std::vector<downloading_piece>::iterator dp);
    │ │ │ │ -
    │ │ │ │ -	private:
    │ │ │ │ -
    │ │ │ │ -#if TORRENT_USE_ASSERTS || TORRENT_USE_INVARIANT_CHECKS
    │ │ │ │ -		index_range<download_queue_t> categories() const
    │ │ │ │ -		{ return {{}, piece_picker::piece_pos::num_download_categories}; }
    │ │ │ │  #endif
    │ │ │ │ +
    relevance 0../include/libtorrent/announce_entry.hpp:76include the number of peers received from this tracker, at last announce

    include the number of peers received from this tracker, at last │ │ │ │ +announce

    ../include/libtorrent/announce_entry.hpp:76

    │ │ │ │ +	struct TORRENT_EXPORT announce_infohash
    │ │ │ │ +	{
    │ │ │ │ +		// internal
    │ │ │ │ +		TORRENT_UNEXPORT announce_infohash();
    │ │ │ │  
    │ │ │ │ -		// the following vectors are mutable because they sometimes may
    │ │ │ │ -		// be updated lazily, triggered by const functions
    │ │ │ │ -
    │ │ │ │ -		// this maps indices to number of peers that has this piece and
    │ │ │ │ -		// index into the m_piece_info vectors.
    │ │ │ │ -		// piece_pos::we_have_index means that we have the piece, so it
    │ │ │ │ -		// doesn't exist in the piece_info buckets
    │ │ │ │ -		// pieces with the filtered flag set doesn't have entries in
    │ │ │ │ -		// the m_piece_info buckets either
    │ │ │ │ -
    mutable aux::vector<piece_pos, piece_index_t> m_piece_map; │ │ │ │ -
    │ │ │ │ - // tracks the number of bytes in a specific piece that are part of a pad │ │ │ │ - // file. The padding is assumed to be at the end of the piece, and the │ │ │ │ - // blocks covered by the pad bytes are not picked by the piece picker │ │ │ │ - std::unordered_map<piece_index_t, int> m_pads_in_piece; │ │ │ │ - │ │ │ │ - // when the adjacent_piece affinity is enabled, this contains the most │ │ │ │ - // recent "extents" of adjacent pieces that have been requested from │ │ │ │ - // this is mutable because it's updated by functions to pick pieces, which │ │ │ │ - // are const. That's an efficient place to update it, since it's being │ │ │ │ - // traversed already. │ │ │ │ - mutable std::vector<piece_extent_t> m_recent_extents; │ │ │ │ - │ │ │ │ - // the number of bytes of pad file set in this piece picker │ │ │ │ - int m_num_pad_bytes = 0; │ │ │ │ - │ │ │ │ - // the number of pad blocks that we already have │ │ │ │ - int m_have_pad_bytes = 0; │ │ │ │ - │ │ │ │ - // the number of pad blocks part of filtered pieces we don't have │ │ │ │ - int m_filtered_pad_bytes = 0; │ │ │ │ - │ │ │ │ - // the number of pad blocks we have that are also filtered │ │ │ │ - int m_have_filtered_pad_bytes = 0; │ │ │ │ - │ │ │ │ - // the number of seeds. These are not added to │ │ │ │ - // the availability counters of the pieces │ │ │ │ - int m_seeds = 0; │ │ │ │ - │ │ │ │ - // the number of pieces that have passed the hash check │ │ │ │ -
    relevance 0../include/libtorrent/piece_picker.hpp:877it would be more intuitive to account "wanted" pieces instead of filtered

    it would be more intuitive to account "wanted" pieces │ │ │ │ -instead of filtered

    ../include/libtorrent/piece_picker.hpp:877

    │ │ │ │ -		// this holds the information of the blocks in partially downloaded
    │ │ │ │ -		// pieces. the downloading_piece::info index point into this vector for
    │ │ │ │ -		// its storage
    │ │ │ │ -		aux::vector<block_info> m_block_info;
    │ │ │ │ -
    │ │ │ │ -		// these are block ranges in m_block_info that are free. The numbers
    │ │ │ │ -		// in here, when multiplied by blocks_per_piece is the index to the
    │ │ │ │ -		// first block in the range that's free to use by a new downloading_piece.
    │ │ │ │ -		// this is a free-list.
    │ │ │ │ -		std::vector<std::uint16_t> m_free_block_infos;
    │ │ │ │ -
    │ │ │ │ -		std::uint16_t m_blocks_in_last_piece = 0;
    │ │ │ │ -		int m_piece_size = 0;
    │ │ │ │ -		std::int64_t m_total_size = 0;
    │ │ │ │ -
    │ │ │ │ -		// the number of filtered pieces that we don't already
    │ │ │ │ -		// have. total_number_of_pieces - number_of_pieces_we_have
    │ │ │ │ -		// - num_filtered is supposed to the number of pieces
    │ │ │ │ -		// we still want to download
    │ │ │ │ -
    int m_num_filtered = 0; │ │ │ │ -
    │ │ │ │ - // the number of pieces we have that also are filtered │ │ │ │ - int m_num_have_filtered = 0; │ │ │ │ - │ │ │ │ - // we have all pieces in the range [0, m_cursor) │ │ │ │ - // m_cursor is the first piece we don't have │ │ │ │ - piece_index_t m_cursor{0}; │ │ │ │ - │ │ │ │ - // we have all pieces in the range [m_reverse_cursor, end) │ │ │ │ - // m_reverse_cursor is the first piece where we also have │ │ │ │ - // all the subsequent pieces │ │ │ │ - piece_index_t m_reverse_cursor{0}; │ │ │ │ - │ │ │ │ - // the number of pieces we have (i.e. passed + flushed). │ │ │ │ - // This includes pieces that we have filtered but still have │ │ │ │ - int m_num_have = 0; │ │ │ │ + // if this tracker has returned an error or warning message │ │ │ │ + // that message is stored here │ │ │ │ + std::string message; │ │ │ │ │ │ │ │ - // if this is set to true, it means update_pieces() │ │ │ │ - // has to be called before accessing m_pieces. │ │ │ │ - mutable bool m_dirty = false; │ │ │ │ - public: │ │ │ │ + // if this tracker failed the last time it was contacted │ │ │ │ + // this error code specifies what error occurred │ │ │ │ + error_code last_error; │ │ │ │ │ │ │ │ - enum { max_pieces = (std::numeric_limits<int>::max)() - 1 }; │ │ │ │ + // the time of next tracker announce │ │ │ │ + time_point32 next_announce = (time_point32::min)(); │ │ │ │ │ │ │ │ - }; │ │ │ │ -} │ │ │ │ + // no announces before this time │ │ │ │ + time_point32 min_announce = (time_point32::min)(); │ │ │ │ │ │ │ │ -#endif // TORRENT_PIECE_PICKER_HPP_INCLUDED │ │ │ │ -
    relevance 0../include/libtorrent/kademlia/msg.hpp:87move this to its own .hpp/.cpp pair?

    move this to its own .hpp/.cpp pair?

    ../include/libtorrent/kademlia/msg.hpp:87

    	int flags;
    │ │ │ │ +
    │ │ │ │ +
    // these are either -1 or the scrape information this tracker last │ │ │ │ + // responded with. *incomplete* is the current number of downloaders in │ │ │ │ + // the swarm, *complete* is the current number of seeds in the swarm and │ │ │ │ + // *downloaded* is the cumulative number of completed downloads of this │ │ │ │ + // torrent, since the beginning of time (from this tracker's point of │ │ │ │ + // view). │ │ │ │ │ │ │ │ - enum { │ │ │ │ - // this argument is optional, parsing will not │ │ │ │ - // fail if it's not present │ │ │ │ - optional = 1, │ │ │ │ - // for dictionaries, the following entries refer │ │ │ │ - // to child nodes to this node, up until and including │ │ │ │ - // the next item that has the last_child flag set. │ │ │ │ - // these flags are nestable │ │ │ │ - parse_children = 2, │ │ │ │ - // this is the last item in a child dictionary │ │ │ │ - last_child = 4, │ │ │ │ - // the size argument refers to that the size │ │ │ │ - // has to be divisible by the number, instead │ │ │ │ - // of having that exact size │ │ │ │ - size_divisible = 8 │ │ │ │ - }; │ │ │ │ -}; │ │ │ │ + // if this tracker has returned scrape data, these fields are filled in │ │ │ │ + // with valid numbers. Otherwise they are set to -1. ``incomplete`` counts │ │ │ │ + // the number of current downloaders. ``complete`` counts the number of │ │ │ │ + // current peers completed the download, or "seeds". ``downloaded`` is the │ │ │ │ + // cumulative number of completed downloads. │ │ │ │ + int scrape_incomplete = -1; │ │ │ │ + int scrape_complete = -1; │ │ │ │ + int scrape_downloaded = -1; │ │ │ │ │ │ │ │ -
    TORRENT_EXTRA_EXPORT bool verify_message_impl(bdecode_node const& message, span<key_desc_t const> desc │ │ │ │ -
    , span<bdecode_node> ret, span<char> error); │ │ │ │ + // the number of times in a row we have failed to announce to this │ │ │ │ + // tracker. │ │ │ │ + std::uint8_t fails : 7; │ │ │ │ │ │ │ │ -// verifies that a message has all the required │ │ │ │ -// entries and returns them in ret │ │ │ │ -template <int Size> │ │ │ │ -bool verify_message(bdecode_node const& msg, key_desc_t const (&desc)[Size] │ │ │ │ - , bdecode_node (&ret)[Size], span<char> error) │ │ │ │ -{ │ │ │ │ - return verify_message_impl(msg, desc, ret, error); │ │ │ │ -} │ │ │ │ + // true while we're waiting for a response from the tracker. │ │ │ │ + bool updating : 1; │ │ │ │ │ │ │ │ -} │ │ │ │ -} │ │ │ │ + // set to true when we get a valid response from an announce │ │ │ │ + // with event=started. If it is set, we won't send start in the subsequent │ │ │ │ + // announces. │ │ │ │ + bool start_sent : 1; │ │ │ │ │ │ │ │ -#endif │ │ │ │ -
    relevance 0../include/libtorrent/kademlia/item.hpp:61since this is a public function, it should probably be moved out of this header and into one with other public functions.

    since this is a public function, it should probably be moved │ │ │ │ + // set to true when we send a event=completed. │ │ │ │ + bool complete_sent : 1; │ │ │ │ +relevance 0../include/libtorrent/kademlia/item.hpp:61since this is a public function, it should probably be moved out of this header and into one with other public functions.

    since this is a public function, it should probably be moved │ │ │ │ out of this header and into one with other public functions.

    ../include/libtorrent/kademlia/item.hpp:61

    #include <libtorrent/span.hpp>
    │ │ │ │  #include <libtorrent/kademlia/types.hpp>
    │ │ │ │  
    │ │ │ │  namespace libtorrent {
    │ │ │ │  namespace dht {
    │ │ │ │  
    │ │ │ │  // calculate the target hash for an immutable item.
    │ │ │ │ @@ -11468,50 +11432,257 @@
    │ │ │ │  		, secret_key const& sk);
    │ │ │ │  	explicit item(bdecode_node const& v);
    │ │ │ │  
    │ │ │ │  	void assign(entry v);
    │ │ │ │  	void assign(entry v, span<char const> salt
    │ │ │ │  		, sequence_number seq
    │ │ │ │  		, public_key const& pk
    │ │ │ │ -
    relevance 0../include/libtorrent/aux_/pool.hpp:49ensure the alignment is good here

    ensure the alignment is good here

    ../include/libtorrent/aux_/pool.hpp:49

    POSSIBILITY OF SUCH DAMAGE.
    │ │ │ │ +
    relevance 0../include/libtorrent/kademlia/msg.hpp:87move this to its own .hpp/.cpp pair?

    move this to its own .hpp/.cpp pair?

    ../include/libtorrent/kademlia/msg.hpp:87

    	int flags;
    │ │ │ │  
    │ │ │ │ -*/
    │ │ │ │ +	enum {
    │ │ │ │ +		// this argument is optional, parsing will not
    │ │ │ │ +		// fail if it's not present
    │ │ │ │ +		optional = 1,
    │ │ │ │ +		// for dictionaries, the following entries refer
    │ │ │ │ +		// to child nodes to this node, up until and including
    │ │ │ │ +		// the next item that has the last_child flag set.
    │ │ │ │ +		// these flags are nestable
    │ │ │ │ +		parse_children = 2,
    │ │ │ │ +		// this is the last item in a child dictionary
    │ │ │ │ +		last_child = 4,
    │ │ │ │ +		// the size argument refers to that the size
    │ │ │ │ +		// has to be divisible by the number, instead
    │ │ │ │ +		// of having that exact size
    │ │ │ │ +		size_divisible = 8
    │ │ │ │ +	};
    │ │ │ │ +};
    │ │ │ │  
    │ │ │ │ -#ifndef TORRENT_POOL_HPP
    │ │ │ │ -#define TORRENT_POOL_HPP
    │ │ │ │ +
    TORRENT_EXTRA_EXPORT bool verify_message_impl(bdecode_node const& message, span<key_desc_t const> desc │ │ │ │ +
    , span<bdecode_node> ret, span<char> error); │ │ │ │ │ │ │ │ -#include "libtorrent/aux_/disable_warnings_push.hpp" │ │ │ │ -#include <boost/pool/pool.hpp> │ │ │ │ -#include <boost/pool/object_pool.hpp> │ │ │ │ -#include "libtorrent/aux_/disable_warnings_pop.hpp" │ │ │ │ +// verifies that a message has all the required │ │ │ │ +// entries and returns them in ret │ │ │ │ +template <int Size> │ │ │ │ +bool verify_message(bdecode_node const& msg, key_desc_t const (&desc)[Size] │ │ │ │ + , bdecode_node (&ret)[Size], span<char> error) │ │ │ │ +{ │ │ │ │ + return verify_message_impl(msg, desc, ret, error); │ │ │ │ +} │ │ │ │ │ │ │ │ -namespace libtorrent { │ │ │ │ -namespace aux { │ │ │ │ +} │ │ │ │ +} │ │ │ │ │ │ │ │ -struct allocator_new_delete │ │ │ │ +#endif │ │ │ │ +
    relevance 0../include/libtorrent/aux_/merkle_tree.hpp:85remove this constructor. Don't support "uninitialized" trees. This also requires not constructing these for pad-files and small files as well. So, a sparse hash list in torrent_info

    remove this constructor. Don't support "uninitialized" trees. This │ │ │ │ +also requires not constructing these for pad-files and small files as │ │ │ │ +well. So, a sparse hash list in torrent_info

    ../include/libtorrent/aux_/merkle_tree.hpp:85

    // The invariant of the tree is that all interior nodes (i.e. all but the very
    │ │ │ │ +// bottom leaf nodes, representing block hashes) are either set and valid, or
    │ │ │ │ +// clear. No invalid hashes are allowed, and they can only be added by also
    │ │ │ │ +// providing proof of being valid.
    │ │ │ │ +
    │ │ │ │ +// The leaf blocks on the other hand, MAY be invalid. For instance, when adding
    │ │ │ │ +// a magnet link for a torrent that we already have files for. Once we have the
    │ │ │ │ +// metadata, we have files on disk but no hashes. We won't know whether the data
    │ │ │ │ +// on disk is valid or not, until we've downloaded the hashes to validate them.
    │ │ │ │ +
    │ │ │ │ +// Idea for future space optimization:
    │ │ │ │ +// while downloading, we need to store interior nodes of this tree. However, we
    │ │ │ │ +// don't need to store the padding. a SHA-256 is 32 bytes. Instead of storing
    │ │ │ │ +// the full (padded) tree of SHA-256 hashes, store the full tree of 32 bit
    │ │ │ │ +// signed integers, being indices into the actual storage for the tree. We could
    │ │ │ │ +// even grow the storage lazily. Instead of storing the padding hashes, use
    │ │ │ │ +// negative indices to refer to fixed SHA-256(0), and SHA-256(SHA-256(0)) and so
    │ │ │ │ +// on
    │ │ │ │ +struct TORRENT_EXTRA_EXPORT merkle_tree
    │ │ │ │  {
    │ │ │ │ -	using size_type = std::size_t;
    │ │ │ │ -	using difference_type = std::ptrdiff_t;
    │ │ │ │ +
    merkle_tree() = default; │ │ │ │ +
    merkle_tree(int num_blocks, int blocks_per_piece, char const* r); │ │ │ │ │ │ │ │ -
    static char* malloc(size_type const bytes) │ │ │ │ -
    { return new char[bytes]; } │ │ │ │ - static void free(char* const block) │ │ │ │ - { delete [] block; } │ │ │ │ -}; │ │ │ │ + sha256_hash root() const; │ │ │ │ │ │ │ │ -using pool = boost::pool<allocator_new_delete>; │ │ │ │ + void load_tree(span<sha256_hash const> t, std::vector<bool> const& verified); │ │ │ │ + void load_sparse_tree(span<sha256_hash const> t, std::vector<bool> const& mask │ │ │ │ + , std::vector<bool> const& verified); │ │ │ │ + void load_verified_bits(std::vector<bool> const& verified); │ │ │ │ │ │ │ │ -template <typename T> │ │ │ │ -using object_pool = boost::object_pool<T, allocator_new_delete>; │ │ │ │ + std::size_t size() const; │ │ │ │ + int end_index() const { return int(size()); } │ │ │ │ │ │ │ │ -} │ │ │ │ -} │ │ │ │ + bool has_node(int idx) const; │ │ │ │ + │ │ │ │ + bool compare_node(int idx, sha256_hash const& h) const; │ │ │ │ + │ │ │ │ + sha256_hash operator[](int idx) const; │ │ │ │ + │ │ │ │ + std::vector<sha256_hash> build_vector() const; │ │ │ │ + std::pair<std::vector<sha256_hash>, aux::vector<bool>> build_sparse_vector() const; │ │ │ │ + │ │ │ │ + // get bits indicating if each leaf hash is verified │ │ │ │ + std::vector<bool> verified_leafs() const; │ │ │ │ + │ │ │ │ + // returns true if the entire tree is known and verified │ │ │ │ + bool is_complete() const; │ │ │ │ + │ │ │ │ + // returns true if all block hashes in the specified range have been verified │ │ │ │ + bool blocks_verified(int block_idx, int num_blocks) const; │ │ │ │ + │ │ │ │ +
    relevance 0../include/libtorrent/aux_/merkle_tree.hpp:175make this a std::unique_ptr

    make this a std::unique_ptr

    ../include/libtorrent/aux_/merkle_tree.hpp:175

    │ │ │ │ +	int blocks_per_piece() const { return 1 << m_blocks_per_piece_log; }
    │ │ │ │ +	// the number tree levels per piece. This is 0 if the block layer is also
    │ │ │ │ +	// the piece layer.
    │ │ │ │ +	int piece_levels() const { return m_blocks_per_piece_log; }
    │ │ │ │ +
    │ │ │ │ +	int block_layer_start() const;
    │ │ │ │ +	int piece_layer_start() const;
    │ │ │ │ +	int num_pieces() const;
    │ │ │ │ +	int num_leafs() const;
    │ │ │ │ +
    │ │ │ │ +	void optimize_storage();
    │ │ │ │ +	void optimize_storage_piece_layer();
    │ │ │ │ +	void allocate_full();
    │ │ │ │ +
    │ │ │ │ +	// a pointer to the root hash for this file.
    │ │ │ │ +	char const* m_root = nullptr;
    │ │ │ │ +
    │ │ │ │ +	// this is either the full tree, or some sparse representation of it,
    │ │ │ │ +	// depending on m_mode
    │ │ │ │ +
    aux::vector<sha256_hash> m_tree; │ │ │ │ +
    │ │ │ │ + // when the full tree is allocated, this has one bit for each block hash. a │ │ │ │ + // 1 means we have verified the block hash to be correct, otherwise the block │ │ │ │ + // hash may represent what's on disk, but we haven't been able to verify it │ │ │ │ + // yet │ │ │ │ + bitfield m_block_verified; │ │ │ │ + │ │ │ │ + // number of blocks in the file this tree represents. The number of leafs in │ │ │ │ + // the tree is rounded up to an even power of 2. │ │ │ │ + int m_num_blocks = 0; │ │ │ │ + │ │ │ │ + // the number of blocks per piece, specified as how many steps to shift │ │ │ │ + // right 1 to get the number of blocks in one piece. This is a compact │ │ │ │ + // representation that's valid because pieces are always powers of 2. │ │ │ │ + // this is necessary to know which layer in the tree the piece layer is. │ │ │ │ + std::uint8_t m_blocks_per_piece_log = 0; │ │ │ │ + │ │ │ │ + enum class mode_t : std::uint8_t │ │ │ │ + { │ │ │ │ + // a default constructed tree is truly empty. It does not even have a │ │ │ │ + // root hash │ │ │ │ + uninitialized_tree, │ │ │ │ + │ │ │ │ + // we don't have any hashes in this tree. m_tree should be empty │ │ │ │ + // an empty tree still always have the root hash (available as root()) │ │ │ │ + empty_tree, │ │ │ │ + │ │ │ │ + // in this mode, m_tree represents the full tree, including padding. │ │ │ │ + full_tree, │ │ │ │ + │ │ │ │ +
    relevance 0../include/libtorrent/aux_/allocating_handler.hpp:317in C++17, Handler and Storage could just use "auto"

    in C++17, Handler and Storage could just use "auto"

    ../include/libtorrent/aux_/allocating_handler.hpp:317

    │ │ │ │ +	private:
    │ │ │ │ +
    │ │ │ │ +		Handler handler;
    │ │ │ │ +		handler_storage<Size, Name>* storage;
    │ │ │ │ +#ifndef BOOST_NO_EXCEPTIONS
    │ │ │ │ +		error_handler_interface* error_handler;
    │ │ │ │ +#endif
    │ │ │ │ +	};
    │ │ │ │ +
    │ │ │ │ +	template <class Handler, size_t Size, HandlerName Name>
    │ │ │ │ +	aux::allocating_handler<Handler, Size, Name>
    │ │ │ │ +	make_handler(Handler handler
    │ │ │ │ +		, handler_storage<Size, Name>& storage
    │ │ │ │ +		, error_handler_interface& err_handler)
    │ │ │ │ +	{
    │ │ │ │ +		return aux::allocating_handler<Handler, Size, Name>(
    │ │ │ │ +			std::forward<Handler>(handler), &storage, &err_handler);
    │ │ │ │ +	}
    │ │ │ │ +
    │ │ │ │ +
    template <typename T │ │ │ │ +
    , typename HandlerType │ │ │ │ + , HandlerType Handler │ │ │ │ + , void (T::*ErrorHandler)(error_code const&) │ │ │ │ + , void (T::*ExceptHandler)(std::exception const&) │ │ │ │ + , typename StorageType │ │ │ │ + , StorageType T::* Storage> │ │ │ │ + struct handler │ │ │ │ + { │ │ │ │ + explicit handler(std::shared_ptr<T> p) : ptr_(std::move(p)) {} │ │ │ │ │ │ │ │ + std::shared_ptr<T> ptr_; │ │ │ │ + │ │ │ │ + template <class... A> │ │ │ │ + void operator()(A&&... a) │ │ │ │ + { │ │ │ │ +#ifdef BOOST_NO_EXCEPTIONS │ │ │ │ + (ptr_.get()->*Handler)(std::forward<A>(a)...); │ │ │ │ +#else │ │ │ │ + try │ │ │ │ + { │ │ │ │ + (ptr_.get()->*Handler)(std::forward<A>(a)...); │ │ │ │ + } │ │ │ │ + catch (system_error const& e) │ │ │ │ + { │ │ │ │ + (ptr_.get()->*ErrorHandler)(e.code()); │ │ │ │ + } │ │ │ │ + catch (std::exception const& e) │ │ │ │ + { │ │ │ │ + (ptr_.get()->*ExceptHandler)(e); │ │ │ │ + } │ │ │ │ +
    relevance 0../include/libtorrent/aux_/session_interface.hpp:212it would be nice to not have this be part of session_interface

    it would be nice to not have this be part of session_interface

    ../include/libtorrent/aux_/session_interface.hpp:212

    		virtual void deferred_submit_jobs() = 0;
    │ │ │ │ +
    │ │ │ │ +		virtual std::uint16_t listen_port() const = 0;
    │ │ │ │ +		virtual std::uint16_t ssl_listen_port() const = 0;
    │ │ │ │ +
    │ │ │ │ +		virtual int listen_port(aux::transport ssl, address const& local_addr) = 0;
    │ │ │ │ +
    │ │ │ │ +		virtual void for_each_listen_socket(std::function<void(aux::listen_socket_handle const&)> f) = 0;
    │ │ │ │ +
    │ │ │ │ +		// ask for which interface and port to bind outgoing peer connections on
    │ │ │ │ +		virtual tcp::endpoint bind_outgoing_socket(socket_type& s, address const&
    │ │ │ │ +			remote_address, error_code& ec) const = 0;
    │ │ │ │ +		virtual bool verify_bound_address(address const& addr, bool utp
    │ │ │ │ +			, error_code& ec) = 0;
    │ │ │ │ +
    │ │ │ │ +#ifndef TORRENT_DISABLE_MUTABLE_TORRENTS
    │ │ │ │ +		virtual std::vector<std::shared_ptr<torrent>> find_collection(
    │ │ │ │ +			std::string const& collection) const = 0;
    │ │ │ │  #endif
    │ │ │ │ -
    relevance 0../include/libtorrent/aux_/session_impl.hpp:265make these direct members and generate shared_ptrs to them which alias the listen_socket_t shared_ptr

    make these direct members and generate shared_ptrs to them │ │ │ │ + │ │ │ │ +
    virtual proxy_settings proxy() const = 0; │ │ │ │ +
    │ │ │ │ +#if TORRENT_USE_I2P │ │ │ │ + virtual char const* i2p_session() const = 0; │ │ │ │ + virtual std::string const& local_i2p_endpoint() const = 0; │ │ │ │ +#endif │ │ │ │ + │ │ │ │ + virtual void prioritize_connections(std::weak_ptr<torrent> t) = 0; │ │ │ │ + │ │ │ │ + virtual void trigger_auto_manage() = 0; │ │ │ │ + │ │ │ │ + virtual void apply_settings_pack(std::shared_ptr<settings_pack> pack) = 0; │ │ │ │ + virtual session_settings const& settings() const = 0; │ │ │ │ + │ │ │ │ + virtual void queue_tracker_request(tracker_request req │ │ │ │ + , std::weak_ptr<request_callback> c) = 0; │ │ │ │ + │ │ │ │ + // peer-classes │ │ │ │ + virtual void set_peer_classes(peer_class_set* s, address const& a, socket_type_t st) = 0; │ │ │ │ + virtual peer_class_pool const& peer_classes() const = 0; │ │ │ │ + virtual peer_class_pool& peer_classes() = 0; │ │ │ │ + virtual bool ignore_unchoke_slots_set(peer_class_set const& set) const = 0; │ │ │ │ + virtual int copy_pertinent_channels(peer_class_set const& set │ │ │ │ + , int channel, bandwidth_channel** dst, int m) = 0; │ │ │ │ + virtual int use_quota_overhead(peer_class_set& set, int amount_down, int amount_up) = 0; │ │ │ │ + │ │ │ │ + virtual bandwidth_manager* get_bandwidth_manager(int channel) = 0; │ │ │ │ + │ │ │ │ + virtual void sent_bytes(int bytes_payload, int bytes_protocol) = 0; │ │ │ │ + virtual void received_bytes(int bytes_payload, int bytes_protocol) = 0; │ │ │ │ + virtual void trancieve_ip_packet(int bytes, bool ipv6) = 0; │ │ │ │ +relevance 0../include/libtorrent/aux_/session_impl.hpp:265make these direct members and generate shared_ptrs to them which alias the listen_socket_t shared_ptr

    make these direct members and generate shared_ptrs to them │ │ │ │ which alias the listen_socket_t shared_ptr

    ../include/libtorrent/aux_/session_impl.hpp:265

    			if (udp_sock) return udp_sock->sock.local_port();
    │ │ │ │  			return 0;
    │ │ │ │  		}
    │ │ │ │  
    │ │ │ │  		// 0 is natpmp 1 is upnp
    │ │ │ │  		// the order of these arrays determines the priority in
    │ │ │ │  		// which their ports will be announced to peers
    │ │ │ │ @@ -11555,15 +11726,15 @@
    │ │ │ │  			{
    │ │ │ │  				return addr == o.addr
    │ │ │ │  					&& port == o.port
    │ │ │ │  					&& device == o.device
    │ │ │ │  					&& ssl == o.ssl
    │ │ │ │  					&& flags == o.flags;
    │ │ │ │  			}
    │ │ │ │ -
    relevance 0../include/libtorrent/aux_/session_impl.hpp:1068replace this by a proper asio timer

    replace this by a proper asio timer

    ../include/libtorrent/aux_/session_impl.hpp:1068

    #ifdef TORRENT_SSL_PEERS
    │ │ │ │ +
    relevance 0../include/libtorrent/aux_/session_impl.hpp:1068replace this by a proper asio timer

    replace this by a proper asio timer

    ../include/libtorrent/aux_/session_impl.hpp:1068

    #ifdef TORRENT_SSL_PEERS
    │ │ │ │  			void on_incoming_utp_ssl(socket_type s);
    │ │ │ │  			void ssl_handshake(error_code const& ec, socket_type* s);
    │ │ │ │  #endif
    │ │ │ │  
    │ │ │ │  			// round-robin index into m_outgoing_interfaces
    │ │ │ │  			mutable std::uint8_t m_interface_index = 0;
    │ │ │ │  
    │ │ │ │ @@ -11579,15 +11750,15 @@
    │ │ │ │  			// when it reaches zero, it is reset to the
    │ │ │ │  			// unchoke_interval and the unchoke set is
    │ │ │ │  			// recomputed.
    │ │ │ │  
    int m_unchoke_time_scaler = 0; │ │ │ │
    │ │ │ │ // this is used to decide when to recalculate which │ │ │ │ // torrents to keep queued and which to activate │ │ │ │ -
    relevance 0../include/libtorrent/aux_/session_impl.hpp:1073replace this by a proper asio timer

    replace this by a proper asio timer

    ../include/libtorrent/aux_/session_impl.hpp:1073

    │ │ │ │ +
    relevance 0../include/libtorrent/aux_/session_impl.hpp:1073replace this by a proper asio timer

    replace this by a proper asio timer

    ../include/libtorrent/aux_/session_impl.hpp:1073

    │ │ │ │  			// round-robin index into m_outgoing_interfaces
    │ │ │ │  			mutable std::uint8_t m_interface_index = 0;
    │ │ │ │  
    │ │ │ │  			std::shared_ptr<listen_socket_t> setup_listener(
    │ │ │ │  				listen_endpoint_t const& lep, error_code& ec);
    │ │ │ │  
    │ │ │ │  #ifndef TORRENT_DISABLE_DHT
    │ │ │ │ @@ -11605,15 +11776,15 @@
    │ │ │ │  			// torrents to keep queued and which to activate
    │ │ │ │  
    int m_auto_manage_time_scaler = 0; │ │ │ │
    │ │ │ │ // works like unchoke_time_scaler but it │ │ │ │ // is only decreased when the unchoke set │ │ │ │ // is recomputed, and when it reaches zero, │ │ │ │ // the optimistic unchoke is moved to another peer. │ │ │ │ -
    relevance 0../include/libtorrent/aux_/session_impl.hpp:1080replace this by a proper asio timer

    replace this by a proper asio timer

    ../include/libtorrent/aux_/session_impl.hpp:1080

    │ │ │ │ +
    relevance 0../include/libtorrent/aux_/session_impl.hpp:1080replace this by a proper asio timer

    replace this by a proper asio timer

    ../include/libtorrent/aux_/session_impl.hpp:1080

    │ │ │ │  #ifndef TORRENT_DISABLE_DHT
    │ │ │ │  			dht::dht_state m_dht_state;
    │ │ │ │  #endif
    │ │ │ │  
    │ │ │ │  			// this is initialized to the unchoke_interval
    │ │ │ │  			// session_setting and decreased every second.
    │ │ │ │  			// when it reaches zero, it is reset to the
    │ │ │ │ @@ -11656,15 +11827,15 @@
    │ │ │ │  			int m_peak_up_rate = 0;
    │ │ │ │  #endif
    │ │ │ │  
    │ │ │ │  			void on_tick(error_code const& e);
    │ │ │ │  
    │ │ │ │  			void try_connect_more_peers();
    │ │ │ │  			void auto_manage_checking_torrents(std::vector<torrent*>& list
    │ │ │ │ -
    relevance 0../include/libtorrent/aux_/utp_stream.hpp:693it would be nice to make this private

    it would be nice to make this private

    ../include/libtorrent/aux_/utp_stream.hpp:693

    	bool consume_incoming_data(
    │ │ │ │ +
    relevance 0../include/libtorrent/aux_/utp_stream.hpp:693it would be nice to make this private

    it would be nice to make this private

    ../include/libtorrent/aux_/utp_stream.hpp:693

    	bool consume_incoming_data(
    │ │ │ │  		utp_header const* ph, std::uint8_t const* ptr, int payload_size, time_point now);
    │ │ │ │  	void update_mtu_limits();
    │ │ │ │  	void experienced_loss(std::uint32_t seq_nr, time_point now);
    │ │ │ │  
    │ │ │ │  	void send_deferred_ack();
    │ │ │ │  	void socket_drained();
    │ │ │ │  
    │ │ │ │ @@ -11707,15 +11878,15 @@
    │ │ │ │  	// it's important that these match the enums in performance_counters for
    │ │ │ │  	// num_utp_idle etc.
    │ │ │ │  	enum class state_t {
    │ │ │ │  		// not yet connected
    │ │ │ │  		none,
    │ │ │ │  		// sent a syn packet, not received any acks
    │ │ │ │  		syn_sent,
    │ │ │ │ -
    relevance 0../include/libtorrent/aux_/announce_entry.hpp:74include the number of peers received from this tracker, at last announce

    include the number of peers received from this tracker, at last │ │ │ │ +relevance 0../include/libtorrent/aux_/announce_entry.hpp:74include the number of peers received from this tracker, at last announce

    include the number of peers received from this tracker, at last │ │ │ │ announce

    ../include/libtorrent/aux_/announce_entry.hpp:74

    namespace aux {
    │ │ │ │  
    │ │ │ │  	struct TORRENT_EXTRA_EXPORT announce_infohash
    │ │ │ │  	{
    │ │ │ │  		announce_infohash();
    │ │ │ │  
    │ │ │ │  		// if this tracker has returned an error or warning message
    │ │ │ │ @@ -11759,221 +11930,15 @@
    │ │ │ │  		// set to true when we get a valid response from an announce
    │ │ │ │  		// with event=started. If it is set, we won't send start in the subsequent
    │ │ │ │  		// announces.
    │ │ │ │  		bool start_sent : 1;
    │ │ │ │  
    │ │ │ │  		// set to true when we send a event=completed.
    │ │ │ │  		bool complete_sent : 1;
    │ │ │ │ -
    relevance 0../include/libtorrent/aux_/session_interface.hpp:212it would be nice to not have this be part of session_interface

    it would be nice to not have this be part of session_interface

    ../include/libtorrent/aux_/session_interface.hpp:212

    		virtual void deferred_submit_jobs() = 0;
    │ │ │ │ -
    │ │ │ │ -		virtual std::uint16_t listen_port() const = 0;
    │ │ │ │ -		virtual std::uint16_t ssl_listen_port() const = 0;
    │ │ │ │ -
    │ │ │ │ -		virtual int listen_port(aux::transport ssl, address const& local_addr) = 0;
    │ │ │ │ -
    │ │ │ │ -		virtual void for_each_listen_socket(std::function<void(aux::listen_socket_handle const&)> f) = 0;
    │ │ │ │ -
    │ │ │ │ -		// ask for which interface and port to bind outgoing peer connections on
    │ │ │ │ -		virtual tcp::endpoint bind_outgoing_socket(socket_type& s, address const&
    │ │ │ │ -			remote_address, error_code& ec) const = 0;
    │ │ │ │ -		virtual bool verify_bound_address(address const& addr, bool utp
    │ │ │ │ -			, error_code& ec) = 0;
    │ │ │ │ -
    │ │ │ │ -#ifndef TORRENT_DISABLE_MUTABLE_TORRENTS
    │ │ │ │ -		virtual std::vector<std::shared_ptr<torrent>> find_collection(
    │ │ │ │ -			std::string const& collection) const = 0;
    │ │ │ │ -#endif
    │ │ │ │ -
    │ │ │ │ -
    virtual proxy_settings proxy() const = 0; │ │ │ │ -
    │ │ │ │ -#if TORRENT_USE_I2P │ │ │ │ - virtual char const* i2p_session() const = 0; │ │ │ │ - virtual std::string const& local_i2p_endpoint() const = 0; │ │ │ │ -#endif │ │ │ │ - │ │ │ │ - virtual void prioritize_connections(std::weak_ptr<torrent> t) = 0; │ │ │ │ - │ │ │ │ - virtual void trigger_auto_manage() = 0; │ │ │ │ - │ │ │ │ - virtual void apply_settings_pack(std::shared_ptr<settings_pack> pack) = 0; │ │ │ │ - virtual session_settings const& settings() const = 0; │ │ │ │ - │ │ │ │ - virtual void queue_tracker_request(tracker_request req │ │ │ │ - , std::weak_ptr<request_callback> c) = 0; │ │ │ │ - │ │ │ │ - // peer-classes │ │ │ │ - virtual void set_peer_classes(peer_class_set* s, address const& a, socket_type_t st) = 0; │ │ │ │ - virtual peer_class_pool const& peer_classes() const = 0; │ │ │ │ - virtual peer_class_pool& peer_classes() = 0; │ │ │ │ - virtual bool ignore_unchoke_slots_set(peer_class_set const& set) const = 0; │ │ │ │ - virtual int copy_pertinent_channels(peer_class_set const& set │ │ │ │ - , int channel, bandwidth_channel** dst, int m) = 0; │ │ │ │ - virtual int use_quota_overhead(peer_class_set& set, int amount_down, int amount_up) = 0; │ │ │ │ - │ │ │ │ - virtual bandwidth_manager* get_bandwidth_manager(int channel) = 0; │ │ │ │ - │ │ │ │ - virtual void sent_bytes(int bytes_payload, int bytes_protocol) = 0; │ │ │ │ - virtual void received_bytes(int bytes_payload, int bytes_protocol) = 0; │ │ │ │ - virtual void trancieve_ip_packet(int bytes, bool ipv6) = 0; │ │ │ │ -
    relevance 0../include/libtorrent/aux_/merkle_tree.hpp:85remove this constructor. Don't support "uninitialized" trees. This also requires not constructing these for pad-files and small files as well. So, a sparse hash list in torrent_info

    remove this constructor. Don't support "uninitialized" trees. This │ │ │ │ -also requires not constructing these for pad-files and small files as │ │ │ │ -well. So, a sparse hash list in torrent_info

    ../include/libtorrent/aux_/merkle_tree.hpp:85

    // The invariant of the tree is that all interior nodes (i.e. all but the very
    │ │ │ │ -// bottom leaf nodes, representing block hashes) are either set and valid, or
    │ │ │ │ -// clear. No invalid hashes are allowed, and they can only be added by also
    │ │ │ │ -// providing proof of being valid.
    │ │ │ │ -
    │ │ │ │ -// The leaf blocks on the other hand, MAY be invalid. For instance, when adding
    │ │ │ │ -// a magnet link for a torrent that we already have files for. Once we have the
    │ │ │ │ -// metadata, we have files on disk but no hashes. We won't know whether the data
    │ │ │ │ -// on disk is valid or not, until we've downloaded the hashes to validate them.
    │ │ │ │ -
    │ │ │ │ -// Idea for future space optimization:
    │ │ │ │ -// while downloading, we need to store interior nodes of this tree. However, we
    │ │ │ │ -// don't need to store the padding. a SHA-256 is 32 bytes. Instead of storing
    │ │ │ │ -// the full (padded) tree of SHA-256 hashes, store the full tree of 32 bit
    │ │ │ │ -// signed integers, being indices into the actual storage for the tree. We could
    │ │ │ │ -// even grow the storage lazily. Instead of storing the padding hashes, use
    │ │ │ │ -// negative indices to refer to fixed SHA-256(0), and SHA-256(SHA-256(0)) and so
    │ │ │ │ -// on
    │ │ │ │ -struct TORRENT_EXTRA_EXPORT merkle_tree
    │ │ │ │ -{
    │ │ │ │ -
    merkle_tree() = default; │ │ │ │ -
    merkle_tree(int num_blocks, int blocks_per_piece, char const* r); │ │ │ │ - │ │ │ │ - sha256_hash root() const; │ │ │ │ - │ │ │ │ - void load_tree(span<sha256_hash const> t, std::vector<bool> const& verified); │ │ │ │ - void load_sparse_tree(span<sha256_hash const> t, std::vector<bool> const& mask │ │ │ │ - , std::vector<bool> const& verified); │ │ │ │ - void load_verified_bits(std::vector<bool> const& verified); │ │ │ │ - │ │ │ │ - std::size_t size() const; │ │ │ │ - int end_index() const { return int(size()); } │ │ │ │ - │ │ │ │ - bool has_node(int idx) const; │ │ │ │ - │ │ │ │ - bool compare_node(int idx, sha256_hash const& h) const; │ │ │ │ - │ │ │ │ - sha256_hash operator[](int idx) const; │ │ │ │ - │ │ │ │ - std::vector<sha256_hash> build_vector() const; │ │ │ │ - std::pair<std::vector<sha256_hash>, aux::vector<bool>> build_sparse_vector() const; │ │ │ │ - │ │ │ │ - // get bits indicating if each leaf hash is verified │ │ │ │ - std::vector<bool> verified_leafs() const; │ │ │ │ - │ │ │ │ - // returns true if the entire tree is known and verified │ │ │ │ - bool is_complete() const; │ │ │ │ - │ │ │ │ - // returns true if all block hashes in the specified range have been verified │ │ │ │ - bool blocks_verified(int block_idx, int num_blocks) const; │ │ │ │ - │ │ │ │ -
    relevance 0../include/libtorrent/aux_/merkle_tree.hpp:175make this a std::unique_ptr

    make this a std::unique_ptr

    ../include/libtorrent/aux_/merkle_tree.hpp:175

    │ │ │ │ -	int blocks_per_piece() const { return 1 << m_blocks_per_piece_log; }
    │ │ │ │ -	// the number tree levels per piece. This is 0 if the block layer is also
    │ │ │ │ -	// the piece layer.
    │ │ │ │ -	int piece_levels() const { return m_blocks_per_piece_log; }
    │ │ │ │ -
    │ │ │ │ -	int block_layer_start() const;
    │ │ │ │ -	int piece_layer_start() const;
    │ │ │ │ -	int num_pieces() const;
    │ │ │ │ -	int num_leafs() const;
    │ │ │ │ -
    │ │ │ │ -	void optimize_storage();
    │ │ │ │ -	void optimize_storage_piece_layer();
    │ │ │ │ -	void allocate_full();
    │ │ │ │ -
    │ │ │ │ -	// a pointer to the root hash for this file.
    │ │ │ │ -	char const* m_root = nullptr;
    │ │ │ │ -
    │ │ │ │ -	// this is either the full tree, or some sparse representation of it,
    │ │ │ │ -	// depending on m_mode
    │ │ │ │ -
    aux::vector<sha256_hash> m_tree; │ │ │ │ -
    │ │ │ │ - // when the full tree is allocated, this has one bit for each block hash. a │ │ │ │ - // 1 means we have verified the block hash to be correct, otherwise the block │ │ │ │ - // hash may represent what's on disk, but we haven't been able to verify it │ │ │ │ - // yet │ │ │ │ - bitfield m_block_verified; │ │ │ │ - │ │ │ │ - // number of blocks in the file this tree represents. The number of leafs in │ │ │ │ - // the tree is rounded up to an even power of 2. │ │ │ │ - int m_num_blocks = 0; │ │ │ │ - │ │ │ │ - // the number of blocks per piece, specified as how many steps to shift │ │ │ │ - // right 1 to get the number of blocks in one piece. This is a compact │ │ │ │ - // representation that's valid because pieces are always powers of 2. │ │ │ │ - // this is necessary to know which layer in the tree the piece layer is. │ │ │ │ - std::uint8_t m_blocks_per_piece_log = 0; │ │ │ │ - │ │ │ │ - enum class mode_t : std::uint8_t │ │ │ │ - { │ │ │ │ - // a default constructed tree is truly empty. It does not even have a │ │ │ │ - // root hash │ │ │ │ - uninitialized_tree, │ │ │ │ - │ │ │ │ - // we don't have any hashes in this tree. m_tree should be empty │ │ │ │ - // an empty tree still always have the root hash (available as root()) │ │ │ │ - empty_tree, │ │ │ │ - │ │ │ │ - // in this mode, m_tree represents the full tree, including padding. │ │ │ │ - full_tree, │ │ │ │ - │ │ │ │ -
    relevance 0../include/libtorrent/aux_/allocating_handler.hpp:317in C++17, Handler and Storage could just use "auto"

    in C++17, Handler and Storage could just use "auto"

    ../include/libtorrent/aux_/allocating_handler.hpp:317

    │ │ │ │ -	private:
    │ │ │ │ -
    │ │ │ │ -		Handler handler;
    │ │ │ │ -		handler_storage<Size, Name>* storage;
    │ │ │ │ -#ifndef BOOST_NO_EXCEPTIONS
    │ │ │ │ -		error_handler_interface* error_handler;
    │ │ │ │ -#endif
    │ │ │ │ -	};
    │ │ │ │ -
    │ │ │ │ -	template <class Handler, size_t Size, HandlerName Name>
    │ │ │ │ -	aux::allocating_handler<Handler, Size, Name>
    │ │ │ │ -	make_handler(Handler handler
    │ │ │ │ -		, handler_storage<Size, Name>& storage
    │ │ │ │ -		, error_handler_interface& err_handler)
    │ │ │ │ -	{
    │ │ │ │ -		return aux::allocating_handler<Handler, Size, Name>(
    │ │ │ │ -			std::forward<Handler>(handler), &storage, &err_handler);
    │ │ │ │ -	}
    │ │ │ │ -
    │ │ │ │ -
    template <typename T │ │ │ │ -
    , typename HandlerType │ │ │ │ - , HandlerType Handler │ │ │ │ - , void (T::*ErrorHandler)(error_code const&) │ │ │ │ - , void (T::*ExceptHandler)(std::exception const&) │ │ │ │ - , typename StorageType │ │ │ │ - , StorageType T::* Storage> │ │ │ │ - struct handler │ │ │ │ - { │ │ │ │ - explicit handler(std::shared_ptr<T> p) : ptr_(std::move(p)) {} │ │ │ │ - │ │ │ │ - std::shared_ptr<T> ptr_; │ │ │ │ - │ │ │ │ - template <class... A> │ │ │ │ - void operator()(A&&... a) │ │ │ │ - { │ │ │ │ -#ifdef BOOST_NO_EXCEPTIONS │ │ │ │ - (ptr_.get()->*Handler)(std::forward<A>(a)...); │ │ │ │ -#else │ │ │ │ - try │ │ │ │ - { │ │ │ │ - (ptr_.get()->*Handler)(std::forward<A>(a)...); │ │ │ │ - } │ │ │ │ - catch (system_error const& e) │ │ │ │ - { │ │ │ │ - (ptr_.get()->*ErrorHandler)(e.code()); │ │ │ │ - } │ │ │ │ - catch (std::exception const& e) │ │ │ │ - { │ │ │ │ - (ptr_.get()->*ExceptHandler)(e); │ │ │ │ - } │ │ │ │ -
    relevance 0../include/libtorrent/aux_/deprecated.hpp:47figure out which version of clang this is supported in

    figure out which version of clang this is supported in

    ../include/libtorrent/aux_/deprecated.hpp:47

    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    │ │ │ │ +
    relevance 0../include/libtorrent/aux_/deprecated.hpp:47figure out which version of clang this is supported in

    figure out which version of clang this is supported in

    ../include/libtorrent/aux_/deprecated.hpp:47

    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    │ │ │ │  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    │ │ │ │  POSSIBILITY OF SUCH DAMAGE.
    │ │ │ │  
    │ │ │ │  */
    │ │ │ │  
    │ │ │ │  #ifndef TORRENT_DEPRECATED_HPP_INCLUDED
    │ │ │ │  #define TORRENT_DEPRECATED_HPP_INCLUDED
    │ │ │ │ @@ -12006,8 +11971,43 @@
    │ │ │ │  #endif
    │ │ │ │  
    │ │ │ │  #ifndef TORRENT_DEPRECATED_ENUM
    │ │ │ │  #define TORRENT_DEPRECATED_ENUM
    │ │ │ │  #endif
    │ │ │ │  
    │ │ │ │  #endif
    │ │ │ │ +
    relevance 0../include/libtorrent/aux_/pool.hpp:49ensure the alignment is good here

    ensure the alignment is good here

    ../include/libtorrent/aux_/pool.hpp:49

    POSSIBILITY OF SUCH DAMAGE.
    │ │ │ │ +
    │ │ │ │ +*/
    │ │ │ │ +
    │ │ │ │ +#ifndef TORRENT_POOL_HPP
    │ │ │ │ +#define TORRENT_POOL_HPP
    │ │ │ │ +
    │ │ │ │ +#include "libtorrent/aux_/disable_warnings_push.hpp"
    │ │ │ │ +#include <boost/pool/pool.hpp>
    │ │ │ │ +#include <boost/pool/object_pool.hpp>
    │ │ │ │ +#include "libtorrent/aux_/disable_warnings_pop.hpp"
    │ │ │ │ +
    │ │ │ │ +namespace libtorrent {
    │ │ │ │ +namespace aux {
    │ │ │ │ +
    │ │ │ │ +struct allocator_new_delete
    │ │ │ │ +{
    │ │ │ │ +	using size_type = std::size_t;
    │ │ │ │ +	using difference_type = std::ptrdiff_t;
    │ │ │ │ +
    │ │ │ │ +
    static char* malloc(size_type const bytes) │ │ │ │ +
    { return new char[bytes]; } │ │ │ │ + static void free(char* const block) │ │ │ │ + { delete [] block; } │ │ │ │ +}; │ │ │ │ + │ │ │ │ +using pool = boost::pool<allocator_new_delete>; │ │ │ │ + │ │ │ │ +template <typename T> │ │ │ │ +using object_pool = boost::object_pool<T, allocator_new_delete>; │ │ │ │ + │ │ │ │ +} │ │ │ │ +} │ │ │ │ + │ │ │ │ +#endif │ │ │ │
    │ │ │ │ ├── html2text {} │ │ │ │ │ @@ -454,179 +454,14 @@ │ │ │ │ │ | | │ │ │ │ │ | auto o = rpc.allocate_observer(std::move(algo), source, node_id()); | │ │ │ │ │ |#if TORRENT_USE_ASSERTS | │ │ │ │ │ | o->m_in_constructor = false; | │ │ │ │ │ |#endif | │ │ │ │ │ | o->flags |= observer::flag_queried; | │ │ │ │ │ |_ _r_p_c_._i_n_v_o_k_e_(_r_e_q_,_ _s_o_u_r_c_e_,_ _o_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -| |_._._/_s_r_c_/_p_e_e_r___c_o_n_n_e_c_t_i_o_n_._c_p_p_: |instead of having to ask the torrent whether it's in graceful pause mode or not, the peers should keep that state (and the torrent | │ │ │ │ │ -|relevance 3|_3_1_1_9 |should update them when it enters graceful pause). When a peer enters graceful pause mode, it should cancel all outstanding requests| │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_a_n_d_ _c_l_e_a_r_ _i_t_s_ _r_e_q_u_e_s_t_ _q_u_e_u_e_._ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** iinnsstteeaadd ooff hhaavviinngg ttoo aasskk tthhee ttoorrrreenntt wwhheetthheerr iitt''ss iinn ggrraacceeffuull ppaauussee mmooddee oorr nnoott,, tthhee ppeeeerrss sshhoouulldd kkeeeepp tthhaatt ssttaattee ((aanndd tthhee ttoorrrreenntt sshhoouulldd uuppddaattee tthheemm wwhheenn iitt eenntteerrss | │ │ │ │ │ -|ggrraacceeffuull ppaauussee)).. WWhheenn aa ppeeeerr eenntteerrss ggrraacceeffuull ppaauussee mmooddee,, iitt sshhoouulldd ccaanncceell aallll oouuttssttaannddiinngg rreeqquueessttss aanndd cclleeaarr iittss rreeqquueesstt qquueeuuee.. ********** | │ │ │ │ │ -|****** ....//ssrrcc//ppeeeerr__ccoonnnneeccttiioonn..ccpppp::33111199 ****** | │ │ │ │ │ -|// to disk or are in the disk write cache | │ │ │ │ │ -| if (picker.is_piece_finished(p.piece) && !was_finished) | │ │ │ │ │ -| { | │ │ │ │ │ -|#if TORRENT_USE_INVARIANT_CHECKS | │ │ │ │ │ -| check_postcondition post_checker2_(t, false); | │ │ │ │ │ -|#endif | │ │ │ │ │ -| t->verify_piece(p.piece); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| check_graceful_pause(); | │ │ │ │ │ -| | │ │ │ │ │ -| if (is_disconnecting()) return; | │ │ │ │ │ -| | │ │ │ │ │ -| if (request_a_block(*t, *this)) | │ │ │ │ │ -| m_counters.inc_stats_counter(counters::incoming_piece_picks); | │ │ │ │ │ -| send_block_requests(); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| void peer_connection::check_graceful_pause() | │ │ │ │ │ -| { | │ │ │ │ │ -|std::shared_ptr t = m_torrent.lock(); | │ │ │ │ │ -|if (!t || !t->graceful_pause()) return; | │ │ │ │ │ -| | │ │ │ │ │ -| if (m_outstanding_bytes > 0) return; | │ │ │ │ │ -| | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ -| peer_log(peer_log_alert::info, "GRACEFUL_PAUSE", "NO MORE DOWNLOAD"); | │ │ │ │ │ -|#endif | │ │ │ │ │ -| disconnect(errors::torrent_paused, operation_t::bittorrent); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| void peer_connection::on_disk_write_complete(storage_error const& error | │ │ │ │ │ -| , peer_request const& p, std::shared_ptr t) | │ │ │ │ │ -| { | │ │ │ │ │ -| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ -| if (should_log(peer_log_alert::info)) | │ │ │ │ │ -| { | │ │ │ │ │ -| peer_log(peer_log_alert::info, "FILE_ASYNC_WRITE_COMPLETE", "piece: %d s: %x l: %x e: %s" | │ │ │ │ │ -| , static_cast(p.piece), p.start, p.length, error.ec.message().c_str()); | │ │ │ │ │ -| } | │ │ │ │ │ -|#endif | │ │ │ │ │ -| | │ │ │ │ │ -| m_counters.inc_stats_counter(counters::queued_write_bytes, -p.length); | │ │ │ │ │ -| m_outstanding_writing_bytes -= p.length; | │ │ │ │ │ -| | │ │ │ │ │ -| TORRENT_ASSERT(m_outstanding_writing_bytes >= 0); | │ │ │ │ │ -| | │ │ │ │ │ -| // every peer is entitled to allocate a disk buffer if it has no writes outstanding | │ │ │ │ │ -| // see the comment in incoming_piece | │ │ │ │ │ -|_ _ _i_f_ _(_m___o_u_t_s_t_a_n_d_i_n_g___w_r_i_t_i_n_g___b_y_t_e_s_ _=_=_ _0_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 3|_._._/_s_r_c_/_p_e_e_r___c_o_n_n_e_c_t_i_o_n_._c_p_p_: |once peers are properly put in graceful pause mode, they can cancel all outstanding requests and this test can be removed. | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_4_0_2_7_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** oonnccee ppeeeerrss aarree pprrooppeerrllyy ppuutt iinn ggrraacceeffuull ppaauussee mmooddee,, tthheeyy ccaann ccaanncceell aallll oouuttssttaannddiinngg rreeqquueessttss aanndd tthhiiss tteesstt ccaann bbee rreemmoovveedd.. ********** | │ │ │ │ │ -|****** ....//ssrrcc//ppeeeerr__ccoonnnneeccttiioonn..ccpppp::44002277 ****** | │ │ │ │ │ -| if (!p->m_deferred_send_block_requests) | │ │ │ │ │ -| return; | │ │ │ │ │ -| | │ │ │ │ │ -| p->m_deferred_send_block_requests = false; | │ │ │ │ │ -| p->send_block_requests_impl(); | │ │ │ │ │ -| }); | │ │ │ │ │ -| m_deferred_send_block_requests = true; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| void peer_connection::send_block_requests_impl() | │ │ │ │ │ -| { | │ │ │ │ │ -| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ -| INVARIANT_CHECK; | │ │ │ │ │ -| | │ │ │ │ │ -| std::shared_ptr t = m_torrent.lock(); | │ │ │ │ │ -| TORRENT_ASSERT(t); | │ │ │ │ │ -| | │ │ │ │ │ -| if (m_disconnecting) return; | │ │ │ │ │ -| | │ │ │ │ │ -|if (t->graceful_pause()) return; | │ │ │ │ │ -| | │ │ │ │ │ -| // we can't download pieces in these states | │ │ │ │ │ -| if (t->state() == torrent_status::checking_files | │ │ │ │ │ -| || t->state() == torrent_status::checking_resume_data | │ │ │ │ │ -| || t->state() == torrent_status::downloading_metadata) | │ │ │ │ │ -| return; | │ │ │ │ │ -| | │ │ │ │ │ -| if (int(m_download_queue.size()) >= m_desired_queue_size | │ │ │ │ │ -| || t->upload_mode()) return; | │ │ │ │ │ -| | │ │ │ │ │ -| bool const empty_download_queue = m_download_queue.empty(); | │ │ │ │ │ -| | │ │ │ │ │ -| while (!m_request_queue.empty() | │ │ │ │ │ -| && (int(m_download_queue.size()) < m_desired_queue_size | │ │ │ │ │ -| || m_queued_time_critical > 0)) | │ │ │ │ │ -| { | │ │ │ │ │ -| pending_block block = m_request_queue.front(); | │ │ │ │ │ -| | │ │ │ │ │ -| m_request_queue.erase(m_request_queue.begin()); | │ │ │ │ │ -| if (m_queued_time_critical) --m_queued_time_critical; | │ │ │ │ │ -| | │ │ │ │ │ -| // if we're a seed, we don't have a piece picker | │ │ │ │ │ -| // so we don't have to worry about invariants getting | │ │ │ │ │ -| // out of sync with it | │ │ │ │ │ -| if (!t->has_picker()) continue; | │ │ │ │ │ -| | │ │ │ │ │ -| // this can happen if a block times out, is re-requested and | │ │ │ │ │ -| // then arrives "unexpectedly" | │ │ │ │ │ -| if (t->picker().is_downloaded(block.block)) | │ │ │ │ │ -|_ _ _ _{_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 3|_._._/_s_r_c_/_p_e_e_r___c_o_n_n_e_c_t_i_o_n_._c_p_p_: |new_piece should be an optional. piece index -1 should not be allowed | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_4_7_1_3_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** nneeww__ppiieeccee sshhoouulldd bbee aann ooppttiioonnaall.. ppiieeccee iinnddeexx --11 sshhoouulldd nnoott bbee aalllloowweedd ********** | │ │ │ │ │ -|****** ....//ssrrcc//ppeeeerr__ccoonnnneeccttiioonn..ccpppp::44771133 ****** | │ │ │ │ │ -| // pieces may be empty if we don't have metadata yet | │ │ │ │ │ -| if (p.pieces.empty()) | │ │ │ │ │ -| { | │ │ │ │ │ -| p.progress = 0.f; | │ │ │ │ │ -| p.progress_ppm = 0; | │ │ │ │ │ -| } | │ │ │ │ │ -| else | │ │ │ │ │ -| { | │ │ │ │ │ -|#if TORRENT_NO_FPU | │ │ │ │ │ -| p.progress = 0.f; | │ │ │ │ │ -|#else | │ │ │ │ │ -| p.progress = float(p.pieces.count()) / float(p.pieces.size()); | │ │ │ │ │ -|#endif | │ │ │ │ │ -| p.progress_ppm = int(std::int64_t(p.pieces.count()) * 1000000 / p.pieces.size()); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_SUPERSEEDING | │ │ │ │ │ -|void peer_connection::superseed_piece(piece_index_t const replace_piece | │ │ │ │ │ -|, piece_index_t const new_piece) | │ │ │ │ │ -| { | │ │ │ │ │ -| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ -| | │ │ │ │ │ -| if (is_connecting()) return; | │ │ │ │ │ -| if (in_handshake()) return; | │ │ │ │ │ -| | │ │ │ │ │ -| if (new_piece == piece_index_t(-1)) | │ │ │ │ │ -| { | │ │ │ │ │ -| if (m_superseed_piece[0] == piece_index_t(-1)) return; | │ │ │ │ │ -| m_superseed_piece[0] = piece_index_t(-1); | │ │ │ │ │ -| m_superseed_piece[1] = piece_index_t(-1); | │ │ │ │ │ -| | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ -| peer_log(peer_log_alert::info, "SUPER_SEEDING", "ending"); | │ │ │ │ │ -|#endif | │ │ │ │ │ -| std::shared_ptr t = m_torrent.lock(); | │ │ │ │ │ -| TORRENT_ASSERT(t); | │ │ │ │ │ -| | │ │ │ │ │ -| // this will either send a full bitfield or | │ │ │ │ │ -| // a have-all message, effectively terminating | │ │ │ │ │ -| // super-seeding, since the peer may pick any piece | │ │ │ │ │ -| write_bitfield(); | │ │ │ │ │ -| | │ │ │ │ │ -| return; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| TORRENT_ASSERT(!has_piece(new_piece)); | │ │ │ │ │ -| | │ │ │ │ │ -|_#_i_f_n_d_e_f_ _T_O_R_R_E_N_T___D_I_S_A_B_L_E___L_O_G_G_I_N_G_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |relevance 3|_._._/_s_r_c_/ |this should be an optional, piece index -1 should not be allowed | │ │ │ │ │ |_ _ _ _ _ _ _ _ _ _ _ _|_w_e_b___p_e_e_r___c_o_n_n_e_c_t_i_o_n_._c_p_p_:_1_9_9_ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** tthhiiss sshhoouulldd bbee aann ooppttiioonnaall,, ppiieeccee iinnddeexx --11 sshhoouulldd nnoott bbee aalllloowweedd ********** | │ │ │ │ │ |****** ....//ssrrcc//wweebb__ppeeeerr__ccoonnnneeccttiioonn..ccpppp::119999 ****** | │ │ │ │ │ | auto const range = aux::file_piece_range_inclusive(fs, i); | │ │ │ │ │ | for (piece_index_t k = std::get<0>(range); k < std::get<1>(range); ++k) | │ │ │ │ │ | have.clear_bit(k); | │ │ │ │ │ @@ -838,352 +673,14 @@ │ │ │ │ │ | web->have_files.resize(t->torrent_file().num_files(), false); | │ │ │ │ │ | | │ │ │ │ │ | // the new web seed we're adding only has this file for now | │ │ │ │ │ | // we may add more files later | │ │ │ │ │ | web->redirects[file_index] = redirect_path; | │ │ │ │ │ | if (web->have_files.get_bit(file_index) == false) | │ │ │ │ │ |_ _ _{_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _3_|_._._/_s_r_c_/_u_t___m_e_t_a_d_a_t_a_._c_p_p_:_2_6_8_ _ _ _ _|_u_s_e_ _t_h_e_ _a_u_x_:_:_w_r_i_t_e___*_ _f_u_n_c_t_i_o_n_s_ _a_n_d_ _t_h_e_ _s_p_a_n_ _h_e_r_e_ _i_n_s_t_e_a_d_,_ _i_t_ _w_i_l_l_ _f_i_t_ _b_e_t_t_e_r_ _w_i_t_h_ _s_e_n_d___b_u_f_f_e_r_(_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** uussee tthhee aauuxx::::wwrriittee__** ffuunnccttiioonnss aanndd tthhee ssppaann hheerree iinnsstteeaadd,, iitt wwiillll ffiitt bbeetttteerr wwiitthh sseenndd__bbuuffffeerr(()) ********** | │ │ │ │ │ -|****** ....//ssrrcc//uutt__mmeettaaddaattaa..ccpppp::226688 ****** | │ │ │ │ │ -|int metadata_piece_size = 0; | │ │ │ │ │ -| | │ │ │ │ │ -| if (m_torrent.valid_metadata()) | │ │ │ │ │ -| e["total_size"] = m_tp.metadata().size(); | │ │ │ │ │ -| | │ │ │ │ │ -| if (type == msg_t::piece) | │ │ │ │ │ -| { | │ │ │ │ │ -| TORRENT_ASSERT(piece >= 0 && piece < (m_tp.metadata().size() + 16 * 1024 - 1) / (16 * 1024)); | │ │ │ │ │ -| TORRENT_ASSERT(m_pc.associated_torrent().lock()->valid_metadata()); | │ │ │ │ │ -| TORRENT_ASSERT(m_torrent.valid_metadata()); | │ │ │ │ │ -| | │ │ │ │ │ -| int const offset = piece * 16 * 1024; | │ │ │ │ │ -| metadata = m_tp.metadata().data() + offset; | │ │ │ │ │ -| metadata_piece_size = std::min( | │ │ │ │ │ -| int(m_tp.metadata().size()) - offset, 16 * 1024); | │ │ │ │ │ -| TORRENT_ASSERT(metadata_piece_size > 0); | │ │ │ │ │ -| TORRENT_ASSERT(offset >= 0); | │ │ │ │ │ -| TORRENT_ASSERT(offset + metadata_piece_size <= m_tp.metadata().size()); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -|char msg[200]; | │ │ │ │ │ -|char* header = msg; | │ │ │ │ │ -| char* p = &msg[6]; | │ │ │ │ │ -| int const len = bencode(p, e); | │ │ │ │ │ -| int const total_size = 2 + len + metadata_piece_size; | │ │ │ │ │ -| namespace io = aux; | │ │ │ │ │ -| io::write_uint32(total_size, header); | │ │ │ │ │ -| io::write_uint8(bt_peer_connection::msg_extended, header); | │ │ │ │ │ -| io::write_uint8(m_message_index, header); | │ │ │ │ │ -| | │ │ │ │ │ -|_ _ _ _m___p_c_._s_e_n_d___b_u_f_f_e_r_(_{_m_s_g_,_ _l_e_n_ _+_ _6_}_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _3_|_._._/_s_r_c_/_t_o_r_r_e_n_t_._c_p_p_:_4_1_8_ _ _ _ _ _ _ _ _|_w_e_ _c_o_u_l_d_ _p_r_o_b_a_b_l_y_ _g_e_t_ _a_w_a_y_ _w_i_t_h_ _j_u_s_t_ _s_a_v_i_n_g_ _a_ _f_e_w_ _f_i_e_l_d_s_ _h_e_r_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** wwee ccoouulldd pprroobbaabbllyy ggeett aawwaayy wwiitthh jjuusstt ssaavviinngg aa ffeeww ffiieellddss hheerree ********** | │ │ │ │ │ -|****** ....//ssrrcc//ttoorrrreenntt..ccpppp::441188 ****** | │ │ │ │ │ -|// --- V2 HASHES --- | │ │ │ │ │ -| | │ │ │ │ │ -| if (m_torrent_file->is_valid() && m_torrent_file->info_hashes().has_v2()) | │ │ │ │ │ -| { | │ │ │ │ │ -| if (!p.merkle_trees.empty()) | │ │ │ │ │ -| load_merkle_trees( | │ │ │ │ │ -| std::move(p.merkle_trees) | │ │ │ │ │ -| , std::move(p.merkle_tree_mask) | │ │ │ │ │ -| , std::move(p.verified_leaf_hashes)); | │ │ │ │ │ -| | │ │ │ │ │ -| // we really don't want to store extra copies of the trees | │ │ │ │ │ -| TORRENT_ASSERT(p.merkle_trees.empty()); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| if (valid_metadata()) | │ │ │ │ │ -| { | │ │ │ │ │ -| inc_stats_counter(counters::num_total_pieces_added | │ │ │ │ │ -| , m_torrent_file->num_pieces()); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -|m_add_torrent_params = std::make_unique(std::move(p)); | │ │ │ │ │ -|} | │ │ │ │ │ -| | │ │ │ │ │ -| void torrent::load_merkle_trees( | │ │ │ │ │ -| aux::vector, file_index_t> trees_import | │ │ │ │ │ -| , aux::vector, file_index_t> mask | │ │ │ │ │ -| , aux::vector, file_index_t> verified) | │ │ │ │ │ -| { | │ │ │ │ │ -| auto const& fs = m_torrent_file->orig_files(); | │ │ │ │ │ -| | │ │ │ │ │ -| std::vector const empty_verified; | │ │ │ │ │ -| for (file_index_t i{0}; i < fs.end_file(); ++i) | │ │ │ │ │ -| { | │ │ │ │ │ -| if (fs.pad_file_at(i) || fs.file_size(i) == 0) | │ │ │ │ │ -| continue; | │ │ │ │ │ -| | │ │ │ │ │ -| if (i >= trees_import.end_index()) break; | │ │ │ │ │ -| std::vector const& verified_bitmask = (i >= verified.end_index()) ? empty_verified : verified[i]; | │ │ │ │ │ -| if (i < mask.end_index() && !mask[i].empty()) | │ │ │ │ │ -| { | │ │ │ │ │ -| mask[i].resize(m_merkle_trees[i].size(), false); | │ │ │ │ │ -| m_merkle_trees[i].load_sparse_tree(trees_import[i], mask[i], verified_bitmask); | │ │ │ │ │ -| } | │ │ │ │ │ -| else | │ │ │ │ │ -| { | │ │ │ │ │ -| m_merkle_trees[i].load_tree(trees_import[i], verified_bitmask); | │ │ │ │ │ -| } | │ │ │ │ │ -| } | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -|_ _v_o_i_d_ _t_o_r_r_e_n_t_:_:_i_n_c___s_t_a_t_s___c_o_u_n_t_e_r_(_i_n_t_ _c_,_ _i_n_t_ _v_a_l_u_e_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _3_|_._._/_s_r_c_/_t_o_r_r_e_n_t_._c_p_p_:_7_1_4_ _ _ _ _ _ _ _ _|_a_s_s_e_r_t_ _t_h_e_r_e_ _a_r_e_ _n_o_ _o_u_t_s_t_a_n_d_i_n_g_ _a_s_y_n_c_ _o_p_e_r_a_t_i_o_n_s_ _o_n_ _t_h_i_s_ _t_o_r_r_e_n_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** aasssseerrtt tthheerree aarree nnoo oouuttssttaannddiinngg aassyynncc ooppeerraattiioonnss oonn tthhiiss ttoorrrreenntt ********** | │ │ │ │ │ -|****** ....//ssrrcc//ttoorrrreenntt..ccpppp::771144 ****** | │ │ │ │ │ -|#endif | │ │ │ │ │ -| | │ │ │ │ │ -| if (!m_ses.dht()) return false; | │ │ │ │ │ -| if (m_torrent_file->is_valid() && !m_files_checked) return false; | │ │ │ │ │ -| if (!m_announce_to_dht) return false; | │ │ │ │ │ -| if (m_paused) return false; | │ │ │ │ │ -| | │ │ │ │ │ -| // don't announce private torrents | │ │ │ │ │ -| if (m_torrent_file->is_valid() && m_torrent_file->priv()) return false; | │ │ │ │ │ -| if (m_trackers.empty()) return true; | │ │ │ │ │ -| if (!settings().get_bool(settings_pack::use_dht_as_fallback)) return true; | │ │ │ │ │ -| | │ │ │ │ │ -| return std::none_of(m_trackers.begin(), m_trackers.end() | │ │ │ │ │ -| , [](aux::announce_entry const& tr) { return bool(tr.verified); }); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -|#endif | │ │ │ │ │ -| | │ │ │ │ │ -| torrent::~torrent() | │ │ │ │ │ -| { | │ │ │ │ │ -| | │ │ │ │ │ -|#if TORRENT_USE_ASSERTS | │ │ │ │ │ -| for (torrent_list_index_t i{}; i != m_links.end_index(); ++i) | │ │ │ │ │ -| { | │ │ │ │ │ -| if (!m_links[i].in_list()) continue; | │ │ │ │ │ -| m_links[i].unlink(m_ses.torrent_list(i), i); | │ │ │ │ │ -| } | │ │ │ │ │ -|#endif | │ │ │ │ │ -| | │ │ │ │ │ -| // The invariant can't be maintained here, since the torrent | │ │ │ │ │ -| // is being destructed, all weak references to it have been | │ │ │ │ │ -| // reset, which means that all its peers already have an | │ │ │ │ │ -| // invalidated torrent pointer (so it cannot be verified to be correct) | │ │ │ │ │ -| | │ │ │ │ │ -| // i.e. the invariant can only be maintained if all connections have | │ │ │ │ │ -| // been closed by the time the torrent is destructed. And they are | │ │ │ │ │ -| // supposed to be closed. So we can still do the invariant check. | │ │ │ │ │ -| | │ │ │ │ │ -| // however, the torrent object may be destructed from the main | │ │ │ │ │ -| // thread when shutting down, if the disk cache has references to it. | │ │ │ │ │ -| // this means that the invariant check that this is called from the | │ │ │ │ │ -| // network thread cannot be maintained | │ │ │ │ │ -| | │ │ │ │ │ -| TORRENT_ASSERT(m_peer_class == peer_class_t{0}); | │ │ │ │ │ -| TORRENT_ASSERT(m_connections.empty()); | │ │ │ │ │ -| // just in case, make sure the session accounting is kept right | │ │ │ │ │ -| for (auto p : m_connections) | │ │ │ │ │ -| m_ses.close_connection(p); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -|_ _v_o_i_d_ _t_o_r_r_e_n_t_:_:_r_e_a_d___p_i_e_c_e_(_p_i_e_c_e___i_n_d_e_x___t_ _c_o_n_s_t_ _p_i_e_c_e_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _3_|_._._/_s_r_c_/_t_o_r_r_e_n_t_._c_p_p_:_1_3_2_6_ _ _ _ _ _ _ _|_t_h_e_r_e_'_s_ _s_o_m_e_ _d_u_p_l_i_c_a_t_i_o_n_ _b_e_t_w_e_e_n_ _t_h_i_s_ _f_u_n_c_t_i_o_n_ _a_n_d_ _p_e_e_r___c_o_n_n_e_c_t_i_o_n_:_:_i_n_c_o_m_i_n_g___p_i_e_c_e_(_)_._ _i_s_ _t_h_e_r_e_ _a_ _w_a_y_ _t_o_ _m_e_r_g_e_ _s_o_m_e_t_h_i_n_g_?_ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tthheerree''ss ssoommee dduupplliiccaattiioonn bbeettwweeeenn tthhiiss ffuunnccttiioonn aanndd ppeeeerr__ccoonnnneeccttiioonn::::iinnccoommiinngg__ppiieeccee(()).. iiss tthheerree aa wwaayy ttoo mmeerrggee ssoommeetthhiinngg?? ********** | │ │ │ │ │ -|****** ....//ssrrcc//ttoorrrreenntt..ccpppp::11332266 ****** | │ │ │ │ │ -|piece_picker& m_picker; | │ │ │ │ │ -| piece_index_t m_piece; | │ │ │ │ │ -| }; | │ │ │ │ │ -| | │ │ │ │ │ -| void torrent::add_piece_async(piece_index_t const piece | │ │ │ │ │ -| , std::vector data, add_piece_flags_t const flags) | │ │ │ │ │ -| { | │ │ │ │ │ -| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ -| | │ │ │ │ │ -| // make sure the piece index is correct | │ │ │ │ │ -| if (piece >= torrent_file().end_piece()) | │ │ │ │ │ -| return; | │ │ │ │ │ -| | │ │ │ │ │ -| // make sure the piece size is correct | │ │ │ │ │ -| if (data.size() != std::size_t(m_torrent_file->piece_size(piece))) | │ │ │ │ │ -| return; | │ │ │ │ │ -| | │ │ │ │ │ -| add_piece(piece, data.data(), flags); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -|void torrent::add_piece(piece_index_t const piece, char const* data | │ │ │ │ │ -|, add_piece_flags_t const flags) | │ │ │ │ │ -| { | │ │ │ │ │ -| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ -| | │ │ │ │ │ -| // make sure the piece index is correct | │ │ │ │ │ -| if (piece >= torrent_file().end_piece()) | │ │ │ │ │ -| return; | │ │ │ │ │ -| | │ │ │ │ │ -| int const piece_size = m_torrent_file->piece_size(piece); | │ │ │ │ │ -| int const blocks_in_piece = (piece_size + block_size() - 1) / block_size(); | │ │ │ │ │ -| | │ │ │ │ │ -| if (m_deleted) return; | │ │ │ │ │ -| | │ │ │ │ │ -| // avoid crash trying to access the picker when there is none | │ │ │ │ │ -| if (m_have_all && !has_picker()) return; | │ │ │ │ │ -| | │ │ │ │ │ -| // we don't support clobbering the piece picker while checking the | │ │ │ │ │ -| // files. We may end up having the same piece multiple times | │ │ │ │ │ -| TORRENT_ASSERT_PRECOND(state() != torrent_status::checking_files | │ │ │ │ │ -| && state() != torrent_status::checking_resume_data); | │ │ │ │ │ -| if (state() == torrent_status::checking_files | │ │ │ │ │ -| || state() == torrent_status::checking_resume_data) | │ │ │ │ │ -| return; | │ │ │ │ │ -| | │ │ │ │ │ -| need_picker(); | │ │ │ │ │ -| | │ │ │ │ │ -| if (picker().have_piece(piece) | │ │ │ │ │ -| && !(flags & torrent_handle::overwrite_existing)) | │ │ │ │ │ -|_ _ _ _r_e_t_u_r_n_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _3_|_._._/_s_r_c_/_t_o_r_r_e_n_t_._c_p_p_:_3_9_5_1_ _ _ _ _ _ _ _|_t_h_i_s_ _c_o_u_l_d_ _p_r_o_b_a_b_l_y_ _b_e_ _p_u_l_l_e_d_ _o_u_t_ _i_n_t_o_ _a_ _f_r_e_e_ _f_u_n_c_t_i_o_n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tthhiiss ccoouulldd pprroobbaabbllyy bbee ppuulllleedd oouutt iinnttoo aa ffrreeee ffuunnccttiioonn ********** | │ │ │ │ │ -|****** ....//ssrrcc//ttoorrrreenntt..ccpppp::33995511 ****** | │ │ │ │ │ -|std::int64_t calc_bytes(file_storage const& fs, piece_count const& pc) | │ │ │ │ │ -| { | │ │ │ │ │ -| // it's an impossible combination to have 0 pieces, but still have one of them be the last piece | │ │ │ │ │ -| TORRENT_ASSERT(!(pc.num_pieces == 0 && pc.last_piece == true)); | │ │ │ │ │ -| | │ │ │ │ │ -| // if we have 0 pieces, we can't have any pad blocks either | │ │ │ │ │ -| TORRENT_ASSERT(!(pc.num_pieces == 0 && pc.pad_bytes > 0)); | │ │ │ │ │ -| | │ │ │ │ │ -| // if we have all pieces, we must also have the last one | │ │ │ │ │ -| TORRENT_ASSERT(!(pc.num_pieces == fs.num_pieces() && pc.last_piece == false)); | │ │ │ │ │ -| | │ │ │ │ │ -| // every block should not be a pad block | │ │ │ │ │ -| TORRENT_ASSERT(pc.pad_bytes <= std::int64_t(pc.num_pieces) * fs.piece_length()); | │ │ │ │ │ -| | │ │ │ │ │ -| return std::int64_t(pc.num_pieces) * fs.piece_length() | │ │ │ │ │ -| - (pc.last_piece ? fs.piece_length() - fs.piece_size(fs.last_piece()) : 0) | │ │ │ │ │ -| - std::int64_t(pc.pad_bytes); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| // fills in total_wanted, total_wanted_done and total_done | │ │ │ │ │ -|void torrent::bytes_done(torrent_status& st, status_flags_t const flags) const | │ │ │ │ │ -|{ | │ │ │ │ │ -| INVARIANT_CHECK; | │ │ │ │ │ -| | │ │ │ │ │ -| st.total_done = 0; | │ │ │ │ │ -| st.total_wanted_done = 0; | │ │ │ │ │ -| st.total_wanted = m_size_on_disk; | │ │ │ │ │ -| | │ │ │ │ │ -| TORRENT_ASSERT(st.total_wanted <= m_torrent_file->total_size()); | │ │ │ │ │ -| TORRENT_ASSERT(st.total_wanted >= 0); | │ │ │ │ │ -| | │ │ │ │ │ -| TORRENT_ASSERT(!valid_metadata() || m_torrent_file->num_pieces() > 0); | │ │ │ │ │ -| if (!valid_metadata()) return; | │ │ │ │ │ -| | │ │ │ │ │ -| if (m_seed_mode || is_seed()) | │ │ │ │ │ -| { | │ │ │ │ │ -| // once we're a seed and remove the piece picker, we stop tracking | │ │ │ │ │ -| // piece- and file priority. We consider everything as being | │ │ │ │ │ -| // "wanted" | │ │ │ │ │ -| st.total_done = m_torrent_file->total_size() - m_padding_bytes; | │ │ │ │ │ -| st.total_wanted_done = m_size_on_disk; | │ │ │ │ │ -| st.total_wanted = m_size_on_disk; | │ │ │ │ │ -| TORRENT_ASSERT(st.total_wanted <= st.total_done); | │ │ │ │ │ -| TORRENT_ASSERT(st.total_wanted_done <= st.total_wanted); | │ │ │ │ │ -| TORRENT_ASSERT(st.total_done <= m_torrent_file->total_size()); | │ │ │ │ │ -| return; | │ │ │ │ │ -| } | │ │ │ │ │ -| else if (!has_picker()) | │ │ │ │ │ -| { | │ │ │ │ │ -| st.total_done = 0; | │ │ │ │ │ -|_ _ _ _s_t_._t_o_t_a_l___w_a_n_t_e_d___d_o_n_e_ _=_ _0_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _3_|_._._/_s_r_c_/_t_o_r_r_e_n_t_._c_p_p_:_4_8_8_6_ _ _ _ _ _ _ _|_s_h_o_u_l_d_ _t_h_i_s_ _a_l_e_r_t_ _h_a_v_e_ _a_n_ _e_r_r_o_r_ _c_o_d_e_ _i_n_ _i_t_?_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** sshhoouulldd tthhiiss aalleerrtt hhaavvee aann eerrrroorr ccooddee iinn iitt?? ********** | │ │ │ │ │ -|****** ....//ssrrcc//ttoorrrreenntt..ccpppp::44888866 ****** | │ │ │ │ │ -|on_remove_peers(); | │ │ │ │ │ -| TORRENT_ASSERT(m_connections.empty()); | │ │ │ │ │ -| | │ │ │ │ │ -| // post a message to the main thread to destruct | │ │ │ │ │ -| // the torrent object from there | │ │ │ │ │ -| if (m_storage) | │ │ │ │ │ -| { | │ │ │ │ │ -| try { | │ │ │ │ │ -| m_ses.disk_thread().async_stop_torrent(m_storage | │ │ │ │ │ -| , std::bind(&torrent::on_torrent_aborted, shared_from_this())); | │ │ │ │ │ -| } | │ │ │ │ │ -| catch (std::exception const& e) | │ │ │ │ │ -| { | │ │ │ │ │ -| TORRENT_UNUSED(e); | │ │ │ │ │ -| m_storage.reset(); | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ -| debug_log("Failed to flush disk cache: %s", e.what()); | │ │ │ │ │ -|#endif | │ │ │ │ │ -| // clients may rely on this alert to be posted, so it's probably a | │ │ │ │ │ -| // good idea to post it here, even though we failed | │ │ │ │ │ -|if (alerts().should_post()) | │ │ │ │ │ -|alerts().emplace_alert(get_handle()); | │ │ │ │ │ -| } | │ │ │ │ │ -| m_ses.deferred_submit_jobs(); | │ │ │ │ │ -| } | │ │ │ │ │ -| else | │ │ │ │ │ -| { | │ │ │ │ │ -| if (alerts().should_post()) | │ │ │ │ │ -| alerts().emplace_alert(get_handle()); | │ │ │ │ │ -| alerts().emplace_alert(get_handle() | │ │ │ │ │ -| , info_hash(), get_userdata()); | │ │ │ │ │ -|_ _ _}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _3_|_._._/_s_r_c_/_t_o_r_r_e_n_t_._c_p_p_:_4_9_5_6_ _ _ _ _ _ _ _|_t_h_i_s_ _s_h_o_u_l_d_ _r_e_t_u_r_n_ _o_p_t_i_o_n_a_l_<_>_._ _p_i_e_c_e_ _i_n_d_e_x_ _-_1_ _s_h_o_u_l_d_ _n_o_t_ _b_e_ _a_l_l_o_w_e_d_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tthhiiss sshhoouulldd rreettuurrnn ooppttiioonnaall<<>>.. ppiieeccee iinnddeexx --11 sshhoouulldd nnoott bbee aalllloowweedd ********** | │ │ │ │ │ -|****** ....//ssrrcc//ttoorrrreenntt..ccpppp::44995566 ****** | │ │ │ │ │ -|} | │ │ │ │ │ -| | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_SUPERSEEDING | │ │ │ │ │ -| void torrent::set_super_seeding(bool const on) | │ │ │ │ │ -| { | │ │ │ │ │ -| if (on == m_super_seeding) return; | │ │ │ │ │ -| | │ │ │ │ │ -| m_super_seeding = on; | │ │ │ │ │ -| set_need_save_resume(torrent_handle::if_state_changed); | │ │ │ │ │ -| state_updated(); | │ │ │ │ │ -| | │ │ │ │ │ -| if (m_super_seeding) return; | │ │ │ │ │ -| | │ │ │ │ │ -| // disable super seeding for all peers | │ │ │ │ │ -| for (auto pc : *this) | │ │ │ │ │ -| { | │ │ │ │ │ -| pc->superseed_piece(piece_index_t(-1), piece_index_t(-1)); | │ │ │ │ │ -| } | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -|piece_index_t torrent::get_piece_to_super_seed(typed_bitfield const& bits) | │ │ │ │ │ -|{ | │ │ │ │ │ -| // return a piece with low availability that is not in | │ │ │ │ │ -| // the bitfield and that is not currently being super | │ │ │ │ │ -| // seeded by any peer | │ │ │ │ │ -| TORRENT_ASSERT(m_super_seeding); | │ │ │ │ │ -| | │ │ │ │ │ -| // do a linear search from the first piece | │ │ │ │ │ -| int min_availability = 9999; | │ │ │ │ │ -| std::vector avail_vec; | │ │ │ │ │ -| for (auto const i : m_torrent_file->piece_range()) | │ │ │ │ │ -| { | │ │ │ │ │ -| if (bits[i]) continue; | │ │ │ │ │ -| | │ │ │ │ │ -| int availability = 0; | │ │ │ │ │ -| for (auto pc : *this) | │ │ │ │ │ -| { | │ │ │ │ │ -| if (pc->super_seeded_piece(i)) | │ │ │ │ │ -| { | │ │ │ │ │ -| // avoid super-seeding the same piece to more than one | │ │ │ │ │ -| // peer if we can avoid it. Do this by artificially | │ │ │ │ │ -| // increase the availability | │ │ │ │ │ -| availability = 999; | │ │ │ │ │ -| break; | │ │ │ │ │ -| } | │ │ │ │ │ -| if (pc->has_piece(i)) ++availability; | │ │ │ │ │ -| } | │ │ │ │ │ -| if (availability > min_availability) continue; | │ │ │ │ │ -| if (availability == min_availability) | │ │ │ │ │ -| { | │ │ │ │ │ -|_ _ _ _ _a_v_a_i_l___v_e_c_._p_u_s_h___b_a_c_k_(_i_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |_r_e_l_e_v_a_n_c_e_ _3_|_._._/_s_r_c_/_s_e_s_s_i_o_n___i_m_p_l_._c_p_p_:_1_1_4_2_ _ _|_c_l_o_s_i_n_g_ _t_h_e_ _u_d_p_ _s_o_c_k_e_t_s_ _h_e_r_e_ _m_e_a_n_s_ _t_h_a_t_ _t_h_e_ _u_T_P_ _c_o_n_n_e_c_t_i_o_n_s_ _c_a_n_n_o_t_ _b_e_ _c_l_o_s_e_d_ _g_r_a_c_e_f_u_l_l_y_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** cclloossiinngg tthhee uuddpp ssoocckkeettss hheerree mmeeaannss tthhaatt tthhee uuTTPP ccoonnnneeccttiioonnss ccaannnnoott bbee cclloosseedd ggrraacceeffuullllyy ********** | │ │ │ │ │ |****** ....//ssrrcc//sseessssiioonn__iimmppll..ccpppp::11114422 ****** | │ │ │ │ │ |#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ | session_log(" aborting all connections (%d)", int(m_connections.size())); | │ │ │ │ │ |#endif | │ │ │ │ │ | // abort all connections | │ │ │ │ │ @@ -1541,14 +1038,483 @@ │ │ │ │ │ | alerts.emplace_alert(pk.bytes, sig.bytes | │ │ │ │ │ | , std::move(salt), seq.value, num); | │ │ │ │ │ | } | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ | void put_mutable_callback(dht::item& i | │ │ │ │ │ |_ _ _ _,_ _s_t_d_:_:_f_u_n_c_t_i_o_n_<_v_o_i_d_(_e_n_t_r_y_&_,_ _s_t_d_:_:_a_r_r_a_y_<_c_h_a_r_,_ _6_4_>_&_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _3_|_._._/_s_r_c_/_t_o_r_r_e_n_t_._c_p_p_:_4_1_8_ _ _ _ _ _ _ _ _|_w_e_ _c_o_u_l_d_ _p_r_o_b_a_b_l_y_ _g_e_t_ _a_w_a_y_ _w_i_t_h_ _j_u_s_t_ _s_a_v_i_n_g_ _a_ _f_e_w_ _f_i_e_l_d_s_ _h_e_r_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** wwee ccoouulldd pprroobbaabbllyy ggeett aawwaayy wwiitthh jjuusstt ssaavviinngg aa ffeeww ffiieellddss hheerree ********** | │ │ │ │ │ +|****** ....//ssrrcc//ttoorrrreenntt..ccpppp::441188 ****** | │ │ │ │ │ +|// --- V2 HASHES --- | │ │ │ │ │ +| | │ │ │ │ │ +| if (m_torrent_file->is_valid() && m_torrent_file->info_hashes().has_v2()) | │ │ │ │ │ +| { | │ │ │ │ │ +| if (!p.merkle_trees.empty()) | │ │ │ │ │ +| load_merkle_trees( | │ │ │ │ │ +| std::move(p.merkle_trees) | │ │ │ │ │ +| , std::move(p.merkle_tree_mask) | │ │ │ │ │ +| , std::move(p.verified_leaf_hashes)); | │ │ │ │ │ +| | │ │ │ │ │ +| // we really don't want to store extra copies of the trees | │ │ │ │ │ +| TORRENT_ASSERT(p.merkle_trees.empty()); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| if (valid_metadata()) | │ │ │ │ │ +| { | │ │ │ │ │ +| inc_stats_counter(counters::num_total_pieces_added | │ │ │ │ │ +| , m_torrent_file->num_pieces()); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +|m_add_torrent_params = std::make_unique(std::move(p)); | │ │ │ │ │ +|} | │ │ │ │ │ +| | │ │ │ │ │ +| void torrent::load_merkle_trees( | │ │ │ │ │ +| aux::vector, file_index_t> trees_import | │ │ │ │ │ +| , aux::vector, file_index_t> mask | │ │ │ │ │ +| , aux::vector, file_index_t> verified) | │ │ │ │ │ +| { | │ │ │ │ │ +| auto const& fs = m_torrent_file->orig_files(); | │ │ │ │ │ +| | │ │ │ │ │ +| std::vector const empty_verified; | │ │ │ │ │ +| for (file_index_t i{0}; i < fs.end_file(); ++i) | │ │ │ │ │ +| { | │ │ │ │ │ +| if (fs.pad_file_at(i) || fs.file_size(i) == 0) | │ │ │ │ │ +| continue; | │ │ │ │ │ +| | │ │ │ │ │ +| if (i >= trees_import.end_index()) break; | │ │ │ │ │ +| std::vector const& verified_bitmask = (i >= verified.end_index()) ? empty_verified : verified[i]; | │ │ │ │ │ +| if (i < mask.end_index() && !mask[i].empty()) | │ │ │ │ │ +| { | │ │ │ │ │ +| mask[i].resize(m_merkle_trees[i].size(), false); | │ │ │ │ │ +| m_merkle_trees[i].load_sparse_tree(trees_import[i], mask[i], verified_bitmask); | │ │ │ │ │ +| } | │ │ │ │ │ +| else | │ │ │ │ │ +| { | │ │ │ │ │ +| m_merkle_trees[i].load_tree(trees_import[i], verified_bitmask); | │ │ │ │ │ +| } | │ │ │ │ │ +| } | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +|_ _v_o_i_d_ _t_o_r_r_e_n_t_:_:_i_n_c___s_t_a_t_s___c_o_u_n_t_e_r_(_i_n_t_ _c_,_ _i_n_t_ _v_a_l_u_e_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _3_|_._._/_s_r_c_/_t_o_r_r_e_n_t_._c_p_p_:_7_1_4_ _ _ _ _ _ _ _ _|_a_s_s_e_r_t_ _t_h_e_r_e_ _a_r_e_ _n_o_ _o_u_t_s_t_a_n_d_i_n_g_ _a_s_y_n_c_ _o_p_e_r_a_t_i_o_n_s_ _o_n_ _t_h_i_s_ _t_o_r_r_e_n_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** aasssseerrtt tthheerree aarree nnoo oouuttssttaannddiinngg aassyynncc ooppeerraattiioonnss oonn tthhiiss ttoorrrreenntt ********** | │ │ │ │ │ +|****** ....//ssrrcc//ttoorrrreenntt..ccpppp::771144 ****** | │ │ │ │ │ +|#endif | │ │ │ │ │ +| | │ │ │ │ │ +| if (!m_ses.dht()) return false; | │ │ │ │ │ +| if (m_torrent_file->is_valid() && !m_files_checked) return false; | │ │ │ │ │ +| if (!m_announce_to_dht) return false; | │ │ │ │ │ +| if (m_paused) return false; | │ │ │ │ │ +| | │ │ │ │ │ +| // don't announce private torrents | │ │ │ │ │ +| if (m_torrent_file->is_valid() && m_torrent_file->priv()) return false; | │ │ │ │ │ +| if (m_trackers.empty()) return true; | │ │ │ │ │ +| if (!settings().get_bool(settings_pack::use_dht_as_fallback)) return true; | │ │ │ │ │ +| | │ │ │ │ │ +| return std::none_of(m_trackers.begin(), m_trackers.end() | │ │ │ │ │ +| , [](aux::announce_entry const& tr) { return bool(tr.verified); }); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +|#endif | │ │ │ │ │ +| | │ │ │ │ │ +| torrent::~torrent() | │ │ │ │ │ +| { | │ │ │ │ │ +| | │ │ │ │ │ +|#if TORRENT_USE_ASSERTS | │ │ │ │ │ +| for (torrent_list_index_t i{}; i != m_links.end_index(); ++i) | │ │ │ │ │ +| { | │ │ │ │ │ +| if (!m_links[i].in_list()) continue; | │ │ │ │ │ +| m_links[i].unlink(m_ses.torrent_list(i), i); | │ │ │ │ │ +| } | │ │ │ │ │ +|#endif | │ │ │ │ │ +| | │ │ │ │ │ +| // The invariant can't be maintained here, since the torrent | │ │ │ │ │ +| // is being destructed, all weak references to it have been | │ │ │ │ │ +| // reset, which means that all its peers already have an | │ │ │ │ │ +| // invalidated torrent pointer (so it cannot be verified to be correct) | │ │ │ │ │ +| | │ │ │ │ │ +| // i.e. the invariant can only be maintained if all connections have | │ │ │ │ │ +| // been closed by the time the torrent is destructed. And they are | │ │ │ │ │ +| // supposed to be closed. So we can still do the invariant check. | │ │ │ │ │ +| | │ │ │ │ │ +| // however, the torrent object may be destructed from the main | │ │ │ │ │ +| // thread when shutting down, if the disk cache has references to it. | │ │ │ │ │ +| // this means that the invariant check that this is called from the | │ │ │ │ │ +| // network thread cannot be maintained | │ │ │ │ │ +| | │ │ │ │ │ +| TORRENT_ASSERT(m_peer_class == peer_class_t{0}); | │ │ │ │ │ +| TORRENT_ASSERT(m_connections.empty()); | │ │ │ │ │ +| // just in case, make sure the session accounting is kept right | │ │ │ │ │ +| for (auto p : m_connections) | │ │ │ │ │ +| m_ses.close_connection(p); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +|_ _v_o_i_d_ _t_o_r_r_e_n_t_:_:_r_e_a_d___p_i_e_c_e_(_p_i_e_c_e___i_n_d_e_x___t_ _c_o_n_s_t_ _p_i_e_c_e_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _3_|_._._/_s_r_c_/_t_o_r_r_e_n_t_._c_p_p_:_1_3_2_6_ _ _ _ _ _ _ _|_t_h_e_r_e_'_s_ _s_o_m_e_ _d_u_p_l_i_c_a_t_i_o_n_ _b_e_t_w_e_e_n_ _t_h_i_s_ _f_u_n_c_t_i_o_n_ _a_n_d_ _p_e_e_r___c_o_n_n_e_c_t_i_o_n_:_:_i_n_c_o_m_i_n_g___p_i_e_c_e_(_)_._ _i_s_ _t_h_e_r_e_ _a_ _w_a_y_ _t_o_ _m_e_r_g_e_ _s_o_m_e_t_h_i_n_g_?_ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tthheerree''ss ssoommee dduupplliiccaattiioonn bbeettwweeeenn tthhiiss ffuunnccttiioonn aanndd ppeeeerr__ccoonnnneeccttiioonn::::iinnccoommiinngg__ppiieeccee(()).. iiss tthheerree aa wwaayy ttoo mmeerrggee ssoommeetthhiinngg?? ********** | │ │ │ │ │ +|****** ....//ssrrcc//ttoorrrreenntt..ccpppp::11332266 ****** | │ │ │ │ │ +|piece_picker& m_picker; | │ │ │ │ │ +| piece_index_t m_piece; | │ │ │ │ │ +| }; | │ │ │ │ │ +| | │ │ │ │ │ +| void torrent::add_piece_async(piece_index_t const piece | │ │ │ │ │ +| , std::vector data, add_piece_flags_t const flags) | │ │ │ │ │ +| { | │ │ │ │ │ +| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ +| | │ │ │ │ │ +| // make sure the piece index is correct | │ │ │ │ │ +| if (piece >= torrent_file().end_piece()) | │ │ │ │ │ +| return; | │ │ │ │ │ +| | │ │ │ │ │ +| // make sure the piece size is correct | │ │ │ │ │ +| if (data.size() != std::size_t(m_torrent_file->piece_size(piece))) | │ │ │ │ │ +| return; | │ │ │ │ │ +| | │ │ │ │ │ +| add_piece(piece, data.data(), flags); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +|void torrent::add_piece(piece_index_t const piece, char const* data | │ │ │ │ │ +|, add_piece_flags_t const flags) | │ │ │ │ │ +| { | │ │ │ │ │ +| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ +| | │ │ │ │ │ +| // make sure the piece index is correct | │ │ │ │ │ +| if (piece >= torrent_file().end_piece()) | │ │ │ │ │ +| return; | │ │ │ │ │ +| | │ │ │ │ │ +| int const piece_size = m_torrent_file->piece_size(piece); | │ │ │ │ │ +| int const blocks_in_piece = (piece_size + block_size() - 1) / block_size(); | │ │ │ │ │ +| | │ │ │ │ │ +| if (m_deleted) return; | │ │ │ │ │ +| | │ │ │ │ │ +| // avoid crash trying to access the picker when there is none | │ │ │ │ │ +| if (m_have_all && !has_picker()) return; | │ │ │ │ │ +| | │ │ │ │ │ +| // we don't support clobbering the piece picker while checking the | │ │ │ │ │ +| // files. We may end up having the same piece multiple times | │ │ │ │ │ +| TORRENT_ASSERT_PRECOND(state() != torrent_status::checking_files | │ │ │ │ │ +| && state() != torrent_status::checking_resume_data); | │ │ │ │ │ +| if (state() == torrent_status::checking_files | │ │ │ │ │ +| || state() == torrent_status::checking_resume_data) | │ │ │ │ │ +| return; | │ │ │ │ │ +| | │ │ │ │ │ +| need_picker(); | │ │ │ │ │ +| | │ │ │ │ │ +| if (picker().have_piece(piece) | │ │ │ │ │ +| && !(flags & torrent_handle::overwrite_existing)) | │ │ │ │ │ +|_ _ _ _r_e_t_u_r_n_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _3_|_._._/_s_r_c_/_t_o_r_r_e_n_t_._c_p_p_:_3_9_5_1_ _ _ _ _ _ _ _|_t_h_i_s_ _c_o_u_l_d_ _p_r_o_b_a_b_l_y_ _b_e_ _p_u_l_l_e_d_ _o_u_t_ _i_n_t_o_ _a_ _f_r_e_e_ _f_u_n_c_t_i_o_n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tthhiiss ccoouulldd pprroobbaabbllyy bbee ppuulllleedd oouutt iinnttoo aa ffrreeee ffuunnccttiioonn ********** | │ │ │ │ │ +|****** ....//ssrrcc//ttoorrrreenntt..ccpppp::33995511 ****** | │ │ │ │ │ +|std::int64_t calc_bytes(file_storage const& fs, piece_count const& pc) | │ │ │ │ │ +| { | │ │ │ │ │ +| // it's an impossible combination to have 0 pieces, but still have one of them be the last piece | │ │ │ │ │ +| TORRENT_ASSERT(!(pc.num_pieces == 0 && pc.last_piece == true)); | │ │ │ │ │ +| | │ │ │ │ │ +| // if we have 0 pieces, we can't have any pad blocks either | │ │ │ │ │ +| TORRENT_ASSERT(!(pc.num_pieces == 0 && pc.pad_bytes > 0)); | │ │ │ │ │ +| | │ │ │ │ │ +| // if we have all pieces, we must also have the last one | │ │ │ │ │ +| TORRENT_ASSERT(!(pc.num_pieces == fs.num_pieces() && pc.last_piece == false)); | │ │ │ │ │ +| | │ │ │ │ │ +| // every block should not be a pad block | │ │ │ │ │ +| TORRENT_ASSERT(pc.pad_bytes <= std::int64_t(pc.num_pieces) * fs.piece_length()); | │ │ │ │ │ +| | │ │ │ │ │ +| return std::int64_t(pc.num_pieces) * fs.piece_length() | │ │ │ │ │ +| - (pc.last_piece ? fs.piece_length() - fs.piece_size(fs.last_piece()) : 0) | │ │ │ │ │ +| - std::int64_t(pc.pad_bytes); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| // fills in total_wanted, total_wanted_done and total_done | │ │ │ │ │ +|void torrent::bytes_done(torrent_status& st, status_flags_t const flags) const | │ │ │ │ │ +|{ | │ │ │ │ │ +| INVARIANT_CHECK; | │ │ │ │ │ +| | │ │ │ │ │ +| st.total_done = 0; | │ │ │ │ │ +| st.total_wanted_done = 0; | │ │ │ │ │ +| st.total_wanted = m_size_on_disk; | │ │ │ │ │ +| | │ │ │ │ │ +| TORRENT_ASSERT(st.total_wanted <= m_torrent_file->total_size()); | │ │ │ │ │ +| TORRENT_ASSERT(st.total_wanted >= 0); | │ │ │ │ │ +| | │ │ │ │ │ +| TORRENT_ASSERT(!valid_metadata() || m_torrent_file->num_pieces() > 0); | │ │ │ │ │ +| if (!valid_metadata()) return; | │ │ │ │ │ +| | │ │ │ │ │ +| if (m_seed_mode || is_seed()) | │ │ │ │ │ +| { | │ │ │ │ │ +| // once we're a seed and remove the piece picker, we stop tracking | │ │ │ │ │ +| // piece- and file priority. We consider everything as being | │ │ │ │ │ +| // "wanted" | │ │ │ │ │ +| st.total_done = m_torrent_file->total_size() - m_padding_bytes; | │ │ │ │ │ +| st.total_wanted_done = m_size_on_disk; | │ │ │ │ │ +| st.total_wanted = m_size_on_disk; | │ │ │ │ │ +| TORRENT_ASSERT(st.total_wanted <= st.total_done); | │ │ │ │ │ +| TORRENT_ASSERT(st.total_wanted_done <= st.total_wanted); | │ │ │ │ │ +| TORRENT_ASSERT(st.total_done <= m_torrent_file->total_size()); | │ │ │ │ │ +| return; | │ │ │ │ │ +| } | │ │ │ │ │ +| else if (!has_picker()) | │ │ │ │ │ +| { | │ │ │ │ │ +| st.total_done = 0; | │ │ │ │ │ +|_ _ _ _s_t_._t_o_t_a_l___w_a_n_t_e_d___d_o_n_e_ _=_ _0_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _3_|_._._/_s_r_c_/_t_o_r_r_e_n_t_._c_p_p_:_4_8_8_6_ _ _ _ _ _ _ _|_s_h_o_u_l_d_ _t_h_i_s_ _a_l_e_r_t_ _h_a_v_e_ _a_n_ _e_r_r_o_r_ _c_o_d_e_ _i_n_ _i_t_?_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** sshhoouulldd tthhiiss aalleerrtt hhaavvee aann eerrrroorr ccooddee iinn iitt?? ********** | │ │ │ │ │ +|****** ....//ssrrcc//ttoorrrreenntt..ccpppp::44888866 ****** | │ │ │ │ │ +|on_remove_peers(); | │ │ │ │ │ +| TORRENT_ASSERT(m_connections.empty()); | │ │ │ │ │ +| | │ │ │ │ │ +| // post a message to the main thread to destruct | │ │ │ │ │ +| // the torrent object from there | │ │ │ │ │ +| if (m_storage) | │ │ │ │ │ +| { | │ │ │ │ │ +| try { | │ │ │ │ │ +| m_ses.disk_thread().async_stop_torrent(m_storage | │ │ │ │ │ +| , std::bind(&torrent::on_torrent_aborted, shared_from_this())); | │ │ │ │ │ +| } | │ │ │ │ │ +| catch (std::exception const& e) | │ │ │ │ │ +| { | │ │ │ │ │ +| TORRENT_UNUSED(e); | │ │ │ │ │ +| m_storage.reset(); | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ +| debug_log("Failed to flush disk cache: %s", e.what()); | │ │ │ │ │ +|#endif | │ │ │ │ │ +| // clients may rely on this alert to be posted, so it's probably a | │ │ │ │ │ +| // good idea to post it here, even though we failed | │ │ │ │ │ +|if (alerts().should_post()) | │ │ │ │ │ +|alerts().emplace_alert(get_handle()); | │ │ │ │ │ +| } | │ │ │ │ │ +| m_ses.deferred_submit_jobs(); | │ │ │ │ │ +| } | │ │ │ │ │ +| else | │ │ │ │ │ +| { | │ │ │ │ │ +| if (alerts().should_post()) | │ │ │ │ │ +| alerts().emplace_alert(get_handle()); | │ │ │ │ │ +| alerts().emplace_alert(get_handle() | │ │ │ │ │ +| , info_hash(), get_userdata()); | │ │ │ │ │ +|_ _ _}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _3_|_._._/_s_r_c_/_t_o_r_r_e_n_t_._c_p_p_:_4_9_5_6_ _ _ _ _ _ _ _|_t_h_i_s_ _s_h_o_u_l_d_ _r_e_t_u_r_n_ _o_p_t_i_o_n_a_l_<_>_._ _p_i_e_c_e_ _i_n_d_e_x_ _-_1_ _s_h_o_u_l_d_ _n_o_t_ _b_e_ _a_l_l_o_w_e_d_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tthhiiss sshhoouulldd rreettuurrnn ooppttiioonnaall<<>>.. ppiieeccee iinnddeexx --11 sshhoouulldd nnoott bbee aalllloowweedd ********** | │ │ │ │ │ +|****** ....//ssrrcc//ttoorrrreenntt..ccpppp::44995566 ****** | │ │ │ │ │ +|} | │ │ │ │ │ +| | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_SUPERSEEDING | │ │ │ │ │ +| void torrent::set_super_seeding(bool const on) | │ │ │ │ │ +| { | │ │ │ │ │ +| if (on == m_super_seeding) return; | │ │ │ │ │ +| | │ │ │ │ │ +| m_super_seeding = on; | │ │ │ │ │ +| set_need_save_resume(torrent_handle::if_state_changed); | │ │ │ │ │ +| state_updated(); | │ │ │ │ │ +| | │ │ │ │ │ +| if (m_super_seeding) return; | │ │ │ │ │ +| | │ │ │ │ │ +| // disable super seeding for all peers | │ │ │ │ │ +| for (auto pc : *this) | │ │ │ │ │ +| { | │ │ │ │ │ +| pc->superseed_piece(piece_index_t(-1), piece_index_t(-1)); | │ │ │ │ │ +| } | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +|piece_index_t torrent::get_piece_to_super_seed(typed_bitfield const& bits) | │ │ │ │ │ +|{ | │ │ │ │ │ +| // return a piece with low availability that is not in | │ │ │ │ │ +| // the bitfield and that is not currently being super | │ │ │ │ │ +| // seeded by any peer | │ │ │ │ │ +| TORRENT_ASSERT(m_super_seeding); | │ │ │ │ │ +| | │ │ │ │ │ +| // do a linear search from the first piece | │ │ │ │ │ +| int min_availability = 9999; | │ │ │ │ │ +| std::vector avail_vec; | │ │ │ │ │ +| for (auto const i : m_torrent_file->piece_range()) | │ │ │ │ │ +| { | │ │ │ │ │ +| if (bits[i]) continue; | │ │ │ │ │ +| | │ │ │ │ │ +| int availability = 0; | │ │ │ │ │ +| for (auto pc : *this) | │ │ │ │ │ +| { | │ │ │ │ │ +| if (pc->super_seeded_piece(i)) | │ │ │ │ │ +| { | │ │ │ │ │ +| // avoid super-seeding the same piece to more than one | │ │ │ │ │ +| // peer if we can avoid it. Do this by artificially | │ │ │ │ │ +| // increase the availability | │ │ │ │ │ +| availability = 999; | │ │ │ │ │ +| break; | │ │ │ │ │ +| } | │ │ │ │ │ +| if (pc->has_piece(i)) ++availability; | │ │ │ │ │ +| } | │ │ │ │ │ +| if (availability > min_availability) continue; | │ │ │ │ │ +| if (availability == min_availability) | │ │ │ │ │ +| { | │ │ │ │ │ +|_ _ _ _ _a_v_a_i_l___v_e_c_._p_u_s_h___b_a_c_k_(_i_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +| |_._._/_s_r_c_/_p_e_e_r___c_o_n_n_e_c_t_i_o_n_._c_p_p_: |instead of having to ask the torrent whether it's in graceful pause mode or not, the peers should keep that state (and the torrent | │ │ │ │ │ +|relevance 3|_3_1_1_9 |should update them when it enters graceful pause). When a peer enters graceful pause mode, it should cancel all outstanding requests| │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_a_n_d_ _c_l_e_a_r_ _i_t_s_ _r_e_q_u_e_s_t_ _q_u_e_u_e_._ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** iinnsstteeaadd ooff hhaavviinngg ttoo aasskk tthhee ttoorrrreenntt wwhheetthheerr iitt''ss iinn ggrraacceeffuull ppaauussee mmooddee oorr nnoott,, tthhee ppeeeerrss sshhoouulldd kkeeeepp tthhaatt ssttaattee ((aanndd tthhee ttoorrrreenntt sshhoouulldd uuppddaattee tthheemm wwhheenn iitt eenntteerrss | │ │ │ │ │ +|ggrraacceeffuull ppaauussee)).. WWhheenn aa ppeeeerr eenntteerrss ggrraacceeffuull ppaauussee mmooddee,, iitt sshhoouulldd ccaanncceell aallll oouuttssttaannddiinngg rreeqquueessttss aanndd cclleeaarr iittss rreeqquueesstt qquueeuuee.. ********** | │ │ │ │ │ +|****** ....//ssrrcc//ppeeeerr__ccoonnnneeccttiioonn..ccpppp::33111199 ****** | │ │ │ │ │ +|// to disk or are in the disk write cache | │ │ │ │ │ +| if (picker.is_piece_finished(p.piece) && !was_finished) | │ │ │ │ │ +| { | │ │ │ │ │ +|#if TORRENT_USE_INVARIANT_CHECKS | │ │ │ │ │ +| check_postcondition post_checker2_(t, false); | │ │ │ │ │ +|#endif | │ │ │ │ │ +| t->verify_piece(p.piece); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| check_graceful_pause(); | │ │ │ │ │ +| | │ │ │ │ │ +| if (is_disconnecting()) return; | │ │ │ │ │ +| | │ │ │ │ │ +| if (request_a_block(*t, *this)) | │ │ │ │ │ +| m_counters.inc_stats_counter(counters::incoming_piece_picks); | │ │ │ │ │ +| send_block_requests(); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| void peer_connection::check_graceful_pause() | │ │ │ │ │ +| { | │ │ │ │ │ +|std::shared_ptr t = m_torrent.lock(); | │ │ │ │ │ +|if (!t || !t->graceful_pause()) return; | │ │ │ │ │ +| | │ │ │ │ │ +| if (m_outstanding_bytes > 0) return; | │ │ │ │ │ +| | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ +| peer_log(peer_log_alert::info, "GRACEFUL_PAUSE", "NO MORE DOWNLOAD"); | │ │ │ │ │ +|#endif | │ │ │ │ │ +| disconnect(errors::torrent_paused, operation_t::bittorrent); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| void peer_connection::on_disk_write_complete(storage_error const& error | │ │ │ │ │ +| , peer_request const& p, std::shared_ptr t) | │ │ │ │ │ +| { | │ │ │ │ │ +| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ +| if (should_log(peer_log_alert::info)) | │ │ │ │ │ +| { | │ │ │ │ │ +| peer_log(peer_log_alert::info, "FILE_ASYNC_WRITE_COMPLETE", "piece: %d s: %x l: %x e: %s" | │ │ │ │ │ +| , static_cast(p.piece), p.start, p.length, error.ec.message().c_str()); | │ │ │ │ │ +| } | │ │ │ │ │ +|#endif | │ │ │ │ │ +| | │ │ │ │ │ +| m_counters.inc_stats_counter(counters::queued_write_bytes, -p.length); | │ │ │ │ │ +| m_outstanding_writing_bytes -= p.length; | │ │ │ │ │ +| | │ │ │ │ │ +| TORRENT_ASSERT(m_outstanding_writing_bytes >= 0); | │ │ │ │ │ +| | │ │ │ │ │ +| // every peer is entitled to allocate a disk buffer if it has no writes outstanding | │ │ │ │ │ +| // see the comment in incoming_piece | │ │ │ │ │ +|_ _ _i_f_ _(_m___o_u_t_s_t_a_n_d_i_n_g___w_r_i_t_i_n_g___b_y_t_e_s_ _=_=_ _0_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 3|_._._/_s_r_c_/_p_e_e_r___c_o_n_n_e_c_t_i_o_n_._c_p_p_: |once peers are properly put in graceful pause mode, they can cancel all outstanding requests and this test can be removed. | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_4_0_2_7_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** oonnccee ppeeeerrss aarree pprrooppeerrllyy ppuutt iinn ggrraacceeffuull ppaauussee mmooddee,, tthheeyy ccaann ccaanncceell aallll oouuttssttaannddiinngg rreeqquueessttss aanndd tthhiiss tteesstt ccaann bbee rreemmoovveedd.. ********** | │ │ │ │ │ +|****** ....//ssrrcc//ppeeeerr__ccoonnnneeccttiioonn..ccpppp::44002277 ****** | │ │ │ │ │ +| if (!p->m_deferred_send_block_requests) | │ │ │ │ │ +| return; | │ │ │ │ │ +| | │ │ │ │ │ +| p->m_deferred_send_block_requests = false; | │ │ │ │ │ +| p->send_block_requests_impl(); | │ │ │ │ │ +| }); | │ │ │ │ │ +| m_deferred_send_block_requests = true; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| void peer_connection::send_block_requests_impl() | │ │ │ │ │ +| { | │ │ │ │ │ +| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ +| INVARIANT_CHECK; | │ │ │ │ │ +| | │ │ │ │ │ +| std::shared_ptr t = m_torrent.lock(); | │ │ │ │ │ +| TORRENT_ASSERT(t); | │ │ │ │ │ +| | │ │ │ │ │ +| if (m_disconnecting) return; | │ │ │ │ │ +| | │ │ │ │ │ +|if (t->graceful_pause()) return; | │ │ │ │ │ +| | │ │ │ │ │ +| // we can't download pieces in these states | │ │ │ │ │ +| if (t->state() == torrent_status::checking_files | │ │ │ │ │ +| || t->state() == torrent_status::checking_resume_data | │ │ │ │ │ +| || t->state() == torrent_status::downloading_metadata) | │ │ │ │ │ +| return; | │ │ │ │ │ +| | │ │ │ │ │ +| if (int(m_download_queue.size()) >= m_desired_queue_size | │ │ │ │ │ +| || t->upload_mode()) return; | │ │ │ │ │ +| | │ │ │ │ │ +| bool const empty_download_queue = m_download_queue.empty(); | │ │ │ │ │ +| | │ │ │ │ │ +| while (!m_request_queue.empty() | │ │ │ │ │ +| && (int(m_download_queue.size()) < m_desired_queue_size | │ │ │ │ │ +| || m_queued_time_critical > 0)) | │ │ │ │ │ +| { | │ │ │ │ │ +| pending_block block = m_request_queue.front(); | │ │ │ │ │ +| | │ │ │ │ │ +| m_request_queue.erase(m_request_queue.begin()); | │ │ │ │ │ +| if (m_queued_time_critical) --m_queued_time_critical; | │ │ │ │ │ +| | │ │ │ │ │ +| // if we're a seed, we don't have a piece picker | │ │ │ │ │ +| // so we don't have to worry about invariants getting | │ │ │ │ │ +| // out of sync with it | │ │ │ │ │ +| if (!t->has_picker()) continue; | │ │ │ │ │ +| | │ │ │ │ │ +| // this can happen if a block times out, is re-requested and | │ │ │ │ │ +| // then arrives "unexpectedly" | │ │ │ │ │ +| if (t->picker().is_downloaded(block.block)) | │ │ │ │ │ +|_ _ _ _{_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 3|_._._/_s_r_c_/_p_e_e_r___c_o_n_n_e_c_t_i_o_n_._c_p_p_: |new_piece should be an optional. piece index -1 should not be allowed | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_4_7_1_3_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** nneeww__ppiieeccee sshhoouulldd bbee aann ooppttiioonnaall.. ppiieeccee iinnddeexx --11 sshhoouulldd nnoott bbee aalllloowweedd ********** | │ │ │ │ │ +|****** ....//ssrrcc//ppeeeerr__ccoonnnneeccttiioonn..ccpppp::44771133 ****** | │ │ │ │ │ +| // pieces may be empty if we don't have metadata yet | │ │ │ │ │ +| if (p.pieces.empty()) | │ │ │ │ │ +| { | │ │ │ │ │ +| p.progress = 0.f; | │ │ │ │ │ +| p.progress_ppm = 0; | │ │ │ │ │ +| } | │ │ │ │ │ +| else | │ │ │ │ │ +| { | │ │ │ │ │ +|#if TORRENT_NO_FPU | │ │ │ │ │ +| p.progress = 0.f; | │ │ │ │ │ +|#else | │ │ │ │ │ +| p.progress = float(p.pieces.count()) / float(p.pieces.size()); | │ │ │ │ │ +|#endif | │ │ │ │ │ +| p.progress_ppm = int(std::int64_t(p.pieces.count()) * 1000000 / p.pieces.size()); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_SUPERSEEDING | │ │ │ │ │ +|void peer_connection::superseed_piece(piece_index_t const replace_piece | │ │ │ │ │ +|, piece_index_t const new_piece) | │ │ │ │ │ +| { | │ │ │ │ │ +| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ +| | │ │ │ │ │ +| if (is_connecting()) return; | │ │ │ │ │ +| if (in_handshake()) return; | │ │ │ │ │ +| | │ │ │ │ │ +| if (new_piece == piece_index_t(-1)) | │ │ │ │ │ +| { | │ │ │ │ │ +| if (m_superseed_piece[0] == piece_index_t(-1)) return; | │ │ │ │ │ +| m_superseed_piece[0] = piece_index_t(-1); | │ │ │ │ │ +| m_superseed_piece[1] = piece_index_t(-1); | │ │ │ │ │ +| | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ +| peer_log(peer_log_alert::info, "SUPER_SEEDING", "ending"); | │ │ │ │ │ +|#endif | │ │ │ │ │ +| std::shared_ptr t = m_torrent.lock(); | │ │ │ │ │ +| TORRENT_ASSERT(t); | │ │ │ │ │ +| | │ │ │ │ │ +| // this will either send a full bitfield or | │ │ │ │ │ +| // a have-all message, effectively terminating | │ │ │ │ │ +| // super-seeding, since the peer may pick any piece | │ │ │ │ │ +| write_bitfield(); | │ │ │ │ │ +| | │ │ │ │ │ +| return; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| TORRENT_ASSERT(!has_piece(new_piece)); | │ │ │ │ │ +| | │ │ │ │ │ +|_#_i_f_n_d_e_f_ _T_O_R_R_E_N_T___D_I_S_A_B_L_E___L_O_G_G_I_N_G_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |_r_e_l_e_v_a_n_c_e_ _3_|_._._/_s_r_c_/_s_e_s_s_i_o_n___h_a_n_d_l_e_._c_p_p_:_6_7_2_ _|_e_x_p_o_s_e_ _t_h_e_ _s_e_q_u_e_n_c_e___n_u_m_b_e_r_,_ _p_u_b_l_i_c___k_e_y_,_ _s_e_c_r_e_t___k_e_y_ _a_n_d_ _s_i_g_n_a_t_u_r_e_ _t_y_p_e_s_ _t_o_ _t_h_e_ _c_l_i_e_n_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** eexxppoossee tthhee sseeqquueennccee__nnuummbbeerr,, ppuubblliicc__kkeeyy,, sseeccrreett__kkeeyy aanndd ssiiggnnaattuurree ttyyppeess ttoo tthhee cclliieenntt ********** | │ │ │ │ │ |****** ....//ssrrcc//sseessssiioonn__hhaannddllee..ccpppp::667722 ****** | │ │ │ │ │ |void session_handle::dht_get_item(sha1_hash const& target) | │ │ │ │ │ | { | │ │ │ │ │ |#ifndef TORRENT_DISABLE_DHT | │ │ │ │ │ | async_call(&session_impl::dht_get_immutable_item, target); | │ │ │ │ │ @@ -1595,14 +1561,48 @@ │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ | void session_handle::dht_get_peers(sha1_hash const& info_hash) | │ │ │ │ │ | { | │ │ │ │ │ |#ifndef TORRENT_DISABLE_DHT | │ │ │ │ │ | async_call(&session_impl::dht_get_peers, info_hash); | │ │ │ │ │ |_#_e_l_s_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _3_|_._._/_s_r_c_/_u_t___m_e_t_a_d_a_t_a_._c_p_p_:_2_6_8_ _ _ _ _|_u_s_e_ _t_h_e_ _a_u_x_:_:_w_r_i_t_e___*_ _f_u_n_c_t_i_o_n_s_ _a_n_d_ _t_h_e_ _s_p_a_n_ _h_e_r_e_ _i_n_s_t_e_a_d_,_ _i_t_ _w_i_l_l_ _f_i_t_ _b_e_t_t_e_r_ _w_i_t_h_ _s_e_n_d___b_u_f_f_e_r_(_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** uussee tthhee aauuxx::::wwrriittee__** ffuunnccttiioonnss aanndd tthhee ssppaann hheerree iinnsstteeaadd,, iitt wwiillll ffiitt bbeetttteerr wwiitthh sseenndd__bbuuffffeerr(()) ********** | │ │ │ │ │ +|****** ....//ssrrcc//uutt__mmeettaaddaattaa..ccpppp::226688 ****** | │ │ │ │ │ +|int metadata_piece_size = 0; | │ │ │ │ │ +| | │ │ │ │ │ +| if (m_torrent.valid_metadata()) | │ │ │ │ │ +| e["total_size"] = m_tp.metadata().size(); | │ │ │ │ │ +| | │ │ │ │ │ +| if (type == msg_t::piece) | │ │ │ │ │ +| { | │ │ │ │ │ +| TORRENT_ASSERT(piece >= 0 && piece < (m_tp.metadata().size() + 16 * 1024 - 1) / (16 * 1024)); | │ │ │ │ │ +| TORRENT_ASSERT(m_pc.associated_torrent().lock()->valid_metadata()); | │ │ │ │ │ +| TORRENT_ASSERT(m_torrent.valid_metadata()); | │ │ │ │ │ +| | │ │ │ │ │ +| int const offset = piece * 16 * 1024; | │ │ │ │ │ +| metadata = m_tp.metadata().data() + offset; | │ │ │ │ │ +| metadata_piece_size = std::min( | │ │ │ │ │ +| int(m_tp.metadata().size()) - offset, 16 * 1024); | │ │ │ │ │ +| TORRENT_ASSERT(metadata_piece_size > 0); | │ │ │ │ │ +| TORRENT_ASSERT(offset >= 0); | │ │ │ │ │ +| TORRENT_ASSERT(offset + metadata_piece_size <= m_tp.metadata().size()); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +|char msg[200]; | │ │ │ │ │ +|char* header = msg; | │ │ │ │ │ +| char* p = &msg[6]; | │ │ │ │ │ +| int const len = bencode(p, e); | │ │ │ │ │ +| int const total_size = 2 + len + metadata_piece_size; | │ │ │ │ │ +| namespace io = aux; | │ │ │ │ │ +| io::write_uint32(total_size, header); | │ │ │ │ │ +| io::write_uint8(bt_peer_connection::msg_extended, header); | │ │ │ │ │ +| io::write_uint8(m_message_index, header); | │ │ │ │ │ +| | │ │ │ │ │ +|_ _ _ _m___p_c_._s_e_n_d___b_u_f_f_e_r_(_{_m_s_g_,_ _l_e_n_ _+_ _6_}_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |relevance 3|_._._/_s_r_c_/_k_a_d_e_m_l_i_a_/ |move this into it's own .cpp file | │ │ │ │ │ |_ _ _ _ _ _ _ _ _ _ _ _|_r_p_c___m_a_n_a_g_e_r_._c_p_p_:_7_1_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** mmoovvee tthhiiss iinnttoo iitt''ss oowwnn ..ccpppp ffiillee ********** | │ │ │ │ │ |****** ....//ssrrcc//kkaaddeemmlliiaa//rrppcc__mmaannaaggeerr..ccpppp::7711 ****** | │ │ │ │ │ |#include | │ │ │ │ │ |#include | │ │ │ │ │ |#include | │ │ │ │ │ @@ -1650,172 +1650,14 @@ │ │ │ │ │ | } | │ │ │ │ │ | else | │ │ │ │ │ | { | │ │ │ │ │ | flags &= ~flag_ipv6_address; | │ │ │ │ │ | m_addr.v4 = ep.address().to_v4().to_bytes(); | │ │ │ │ │ | } | │ │ │ │ │ |_}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 3|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |unify url_seed and http_seed with just web_seed, using the web_seed_entry. | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_t_o_r_r_e_n_t___h_a_n_d_l_e_._h_p_p_:_5_3_5_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** uunniiffyy uurrll__sseeeedd aanndd hhttttpp__sseeeedd wwiitthh jjuusstt wweebb__sseeeedd,, uussiinngg tthhee wweebb__sseeeedd__eennttrryy.. ********** | │ │ │ │ │ -|****** ....//iinncclluuddee//lliibbttoorrrreenntt//ttoorrrreenntt__hhaannddllee..hhpppp::553355 ****** | │ │ │ │ │ -|// one returned from ``trackers()`` and will replace it. If you want an | │ │ │ │ │ -| // immediate effect, you have to call force_reannounce(). See | │ │ │ │ │ -| // announce_entry. | │ │ │ │ │ -| // | │ │ │ │ │ -| // ``post_trackers()`` is the asynchronous version of ``trackers()``. It | │ │ │ │ │ -| // will trigger a tracker_list_alert to be posted. | │ │ │ │ │ -| // | │ │ │ │ │ -| // ``add_tracker()`` will look if the specified tracker is already in the | │ │ │ │ │ -| // set. If it is, it doesn't do anything. If it's not in the current set | │ │ │ │ │ -| // of trackers, it will insert it in the tier specified in the | │ │ │ │ │ -| // announce_entry. | │ │ │ │ │ -| // | │ │ │ │ │ -| // The updated set of trackers will be saved in the resume data, and when | │ │ │ │ │ -| // a torrent is started with resume data, the trackers from the resume | │ │ │ │ │ -| // data will replace the original ones. | │ │ │ │ │ -| std::vector trackers() const; | │ │ │ │ │ -| void replace_trackers(std::vector const&) const; | │ │ │ │ │ -| void add_tracker(announce_entry const&) const; | │ │ │ │ │ -| void post_trackers() const; | │ │ │ │ │ -| | │ │ │ │ │ -| | │ │ │ │ │ -|// ``add_url_seed()`` adds another url to the torrent's list of url | │ │ │ │ │ -| // seeds. If the given url already exists in that list, the call has no | │ │ │ │ │ -| // effect. The torrent will connect to the server and try to download | │ │ │ │ │ -| // pieces from it, unless it's paused, queued, checking or seeding. | │ │ │ │ │ -| // ``remove_url_seed()`` removes the given url if it exists already. | │ │ │ │ │ -| // ``url_seeds()`` return a set of the url seeds currently in this | │ │ │ │ │ -| // torrent. Note that URLs that fails may be removed automatically from | │ │ │ │ │ -| // the list. | │ │ │ │ │ -| // | │ │ │ │ │ -| // See http-seeding_ for more information. | │ │ │ │ │ -| void add_url_seed(std::string const& url) const; | │ │ │ │ │ -| void remove_url_seed(std::string const& url) const; | │ │ │ │ │ -| std::set url_seeds() const; | │ │ │ │ │ -| | │ │ │ │ │ -| // These functions are identical as the ``*_url_seed()`` variants, but | │ │ │ │ │ -| // they operate on `BEP 17`_ web seeds instead of `BEP 19`_. | │ │ │ │ │ -| // | │ │ │ │ │ -| // See http-seeding_ for more information. | │ │ │ │ │ -| void add_http_seed(std::string const& url) const; | │ │ │ │ │ -| void remove_http_seed(std::string const& url) const; | │ │ │ │ │ -| std::set http_seeds() const; | │ │ │ │ │ -| | │ │ │ │ │ -| // add the specified extension to this torrent. The ``ext`` argument is | │ │ │ │ │ -| // a function that will be called from within libtorrent's context | │ │ │ │ │ -| // passing in the internal torrent object and the specified userdata | │ │ │ │ │ -| // pointer. The function is expected to return a shared pointer to | │ │ │ │ │ -| // a torrent_plugin instance. | │ │ │ │ │ -| void add_extension( | │ │ │ │ │ -| std::function(torrent_handle const&, client_data_t)> const& ext | │ │ │ │ │ -|_ _ _ _,_ _c_l_i_e_n_t___d_a_t_a___t_ _u_s_e_r_d_a_t_a_ _=_ _c_l_i_e_n_t___d_a_t_a___t_{_}_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 3|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |if we make this be a disk_buffer_holder instead we would save a copy use allocate_disk_receive_buffer and | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_w_e_b___p_e_e_r___c_o_n_n_e_c_t_i_o_n_._h_p_p_:_1_1_9_ _ _ _|_r_e_l_e_a_s_e___d_i_s_k___r_e_c_e_i_v_e___b_u_f_f_e_r_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** iiff wwee mmaakkee tthhiiss bbee aa ddiisskk__bbuuffffeerr__hhoollddeerr iinnsstteeaadd wwee wwoouulldd ssaavvee aa ccooppyy uussee aallllooccaattee__ddiisskk__rreecceeiivvee__bbuuffffeerr aanndd rreelleeaassee__ddiisskk__rreecceeiivvee__bbuuffffeerr ********** | │ │ │ │ │ -|****** ....//iinncclluuddee//lliibbttoorrrreenntt//wweebb__ppeeeerr__ccoonnnneeccttiioonn..hhpppp::111199 ****** | │ │ │ │ │ -|piece_block_progress downloading_piece_progress() const override; | │ │ │ │ │ -| | │ │ │ │ │ -| void handle_padfile(); | │ │ │ │ │ -| | │ │ │ │ │ -| // this has one entry per http-request | │ │ │ │ │ -| // (might be more than the bt requests) | │ │ │ │ │ -| struct file_request_t | │ │ │ │ │ -| { | │ │ │ │ │ -| file_index_t file_index; | │ │ │ │ │ -| int length; | │ │ │ │ │ -| std::int64_t start; | │ │ │ │ │ -| }; | │ │ │ │ │ -| std::deque m_file_requests; | │ │ │ │ │ -| | │ │ │ │ │ -| std::string m_url; | │ │ │ │ │ -| | │ │ │ │ │ -| web_seed_t* m_web; | │ │ │ │ │ -| | │ │ │ │ │ -| // this is used for intermediate storage of pieces to be delivered to the | │ │ │ │ │ -| // bittorrent engine | │ │ │ │ │ -|aux::vector m_piece; | │ │ │ │ │ -| | │ │ │ │ │ -| // the number of bytes we've forwarded to the incoming_payload() function | │ │ │ │ │ -| // in the current HTTP response. used to know where in the buffer the | │ │ │ │ │ -| // next response starts | │ │ │ │ │ -| int m_received_body; | │ │ │ │ │ -| | │ │ │ │ │ -| // this is the offset inside the current receive | │ │ │ │ │ -| // buffer where the next chunk header will be. | │ │ │ │ │ -| // this is updated for each chunk header that's | │ │ │ │ │ -| // parsed. It does not necessarily point to a valid | │ │ │ │ │ -| // offset in the receive buffer, if we haven't received | │ │ │ │ │ -| // it yet. This offset never includes the HTTP header | │ │ │ │ │ -| int m_chunk_pos; | │ │ │ │ │ -| | │ │ │ │ │ -| // this is the number of bytes we've already received | │ │ │ │ │ -| // from the next chunk header we're waiting for | │ │ │ │ │ -| int m_partial_chunk_header; | │ │ │ │ │ -| | │ │ │ │ │ -| // the number of responses we've received so far on | │ │ │ │ │ -| // this connection | │ │ │ │ │ -| int m_num_responses; | │ │ │ │ │ -| }; | │ │ │ │ │ -|} | │ │ │ │ │ -| | │ │ │ │ │ -|_#_e_n_d_i_f_ _/_/_ _T_O_R_R_E_N_T___W_E_B___P_E_E_R___C_O_N_N_E_C_T_I_O_N___H_P_P___I_N_C_L_U_D_E_D_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 3|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |everything but payload counters and rates could probably be removed from here | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_s_t_a_t_._h_p_p_:_2_5_7_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** eevveerryytthhiinngg bbuutt ppaayyllooaadd ccoouunntteerrss aanndd rraatteess ccoouulldd pprroobbaabbllyy bbee rreemmoovveedd ffrroomm hheerree ********** | │ │ │ │ │ -|****** ....//iinncclluuddee//lliibbttoorrrreenntt//ssttaatt..hhpppp::225577 ****** | │ │ │ │ │ -|// peer_connection is opened and have some previous | │ │ │ │ │ -| // transfers from earlier connections. | │ │ │ │ │ -| void add_stat(std::int64_t downloaded, std::int64_t uploaded) | │ │ │ │ │ -| { | │ │ │ │ │ -| m_stat[download_payload].offset(downloaded); | │ │ │ │ │ -| m_stat[upload_payload].offset(uploaded); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| int last_payload_downloaded() const | │ │ │ │ │ -| { return m_stat[download_payload].counter(); } | │ │ │ │ │ -| int last_payload_uploaded() const | │ │ │ │ │ -| { return m_stat[upload_payload].counter(); } | │ │ │ │ │ -| int last_protocol_downloaded() const | │ │ │ │ │ -| { return m_stat[download_protocol].counter(); } | │ │ │ │ │ -| int last_protocol_uploaded() const | │ │ │ │ │ -| { return m_stat[upload_protocol].counter(); } | │ │ │ │ │ -| | │ │ │ │ │ -| // these are the channels we keep stats for | │ │ │ │ │ -| enum | │ │ │ │ │ -| { | │ │ │ │ │ -|upload_payload, | │ │ │ │ │ -|upload_protocol, | │ │ │ │ │ -| download_payload, | │ │ │ │ │ -| download_protocol, | │ │ │ │ │ -| upload_ip_protocol, | │ │ │ │ │ -| download_ip_protocol, | │ │ │ │ │ -| num_channels | │ │ │ │ │ -| }; | │ │ │ │ │ -| | │ │ │ │ │ -| void clear() | │ │ │ │ │ -| { | │ │ │ │ │ -| for (int i = 0; i < num_channels; ++i) | │ │ │ │ │ -| m_stat[i].clear(); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| stat_channel const& operator[](int i) const | │ │ │ │ │ -| { | │ │ │ │ │ -| TORRENT_ASSERT(i >= 0 && i < num_channels); | │ │ │ │ │ -| return m_stat[i]; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| private: | │ │ │ │ │ -| | │ │ │ │ │ -| stat_channel m_stat[num_channels]; | │ │ │ │ │ -| }; | │ │ │ │ │ -| | │ │ │ │ │ -|} | │ │ │ │ │ -| | │ │ │ │ │ -|_#_e_n_d_i_f_ _/_/_ _T_O_R_R_E_N_T___S_T_A_T___H_P_P___I_N_C_L_U_D_E_D_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |relevance 3|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |factor out predictive pieces and all operations on it into a separate class (to use as member here instead) | │ │ │ │ │ |_ _ _ _ _ _ _ _ _ _ _ _|_t_o_r_r_e_n_t_._h_p_p_:_1_4_3_8_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** ffaaccttoorr oouutt pprreeddiiccttiivvee ppiieecceess aanndd aallll ooppeerraattiioonnss oonn iitt iinnttoo aa sseeppaarraattee ccllaassss ((ttoo uussee aass mmeemmbbeerr hheerree iinnsstteeaadd)) ********** | │ │ │ │ │ |****** ....//iinncclluuddee//lliibbttoorrrreenntt//ttoorrrreenntt..hhpppp::11443388 ****** | │ │ │ │ │ |#endif | │ │ │ │ │ | | │ │ │ │ │ | std::string m_trackerid; | │ │ │ │ │ @@ -1917,14 +1759,67 @@ │ │ │ │ │ | | │ │ │ │ │ | // the number of pieces we completed the check of | │ │ │ │ │ | piece_index_t m_num_checked_pieces{0}; | │ │ │ │ │ | | │ │ │ │ │ | // if the error occurred on a file, this is the index of that file | │ │ │ │ │ | // there are a few special cases, when this is negative. See | │ │ │ │ │ |_ _ _/_/_ _s_e_t___e_r_r_o_r_(_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 3|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |everything but payload counters and rates could probably be removed from here | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_s_t_a_t_._h_p_p_:_2_5_7_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** eevveerryytthhiinngg bbuutt ppaayyllooaadd ccoouunntteerrss aanndd rraatteess ccoouulldd pprroobbaabbllyy bbee rreemmoovveedd ffrroomm hheerree ********** | │ │ │ │ │ +|****** ....//iinncclluuddee//lliibbttoorrrreenntt//ssttaatt..hhpppp::225577 ****** | │ │ │ │ │ +|// peer_connection is opened and have some previous | │ │ │ │ │ +| // transfers from earlier connections. | │ │ │ │ │ +| void add_stat(std::int64_t downloaded, std::int64_t uploaded) | │ │ │ │ │ +| { | │ │ │ │ │ +| m_stat[download_payload].offset(downloaded); | │ │ │ │ │ +| m_stat[upload_payload].offset(uploaded); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| int last_payload_downloaded() const | │ │ │ │ │ +| { return m_stat[download_payload].counter(); } | │ │ │ │ │ +| int last_payload_uploaded() const | │ │ │ │ │ +| { return m_stat[upload_payload].counter(); } | │ │ │ │ │ +| int last_protocol_downloaded() const | │ │ │ │ │ +| { return m_stat[download_protocol].counter(); } | │ │ │ │ │ +| int last_protocol_uploaded() const | │ │ │ │ │ +| { return m_stat[upload_protocol].counter(); } | │ │ │ │ │ +| | │ │ │ │ │ +| // these are the channels we keep stats for | │ │ │ │ │ +| enum | │ │ │ │ │ +| { | │ │ │ │ │ +|upload_payload, | │ │ │ │ │ +|upload_protocol, | │ │ │ │ │ +| download_payload, | │ │ │ │ │ +| download_protocol, | │ │ │ │ │ +| upload_ip_protocol, | │ │ │ │ │ +| download_ip_protocol, | │ │ │ │ │ +| num_channels | │ │ │ │ │ +| }; | │ │ │ │ │ +| | │ │ │ │ │ +| void clear() | │ │ │ │ │ +| { | │ │ │ │ │ +| for (int i = 0; i < num_channels; ++i) | │ │ │ │ │ +| m_stat[i].clear(); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| stat_channel const& operator[](int i) const | │ │ │ │ │ +| { | │ │ │ │ │ +| TORRENT_ASSERT(i >= 0 && i < num_channels); | │ │ │ │ │ +| return m_stat[i]; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| private: | │ │ │ │ │ +| | │ │ │ │ │ +| stat_channel m_stat[num_channels]; | │ │ │ │ │ +| }; | │ │ │ │ │ +| | │ │ │ │ │ +|} | │ │ │ │ │ +| | │ │ │ │ │ +|_#_e_n_d_i_f_ _/_/_ _T_O_R_R_E_N_T___S_T_A_T___H_P_P___I_N_C_L_U_D_E_D_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |relevance 3|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |dh_key_exchange should probably move into its own file | │ │ │ │ │ |_ _ _ _ _ _ _ _ _ _ _ _|_p_e___c_r_y_p_t_o_._h_p_p_:_7_2_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** ddhh__kkeeyy__eexxcchhaannggee sshhoouulldd pprroobbaabbllyy mmoovvee iinnttoo iittss oowwnn ffiillee ********** | │ │ │ │ │ |****** ....//iinncclluuddee//lliibbttoorrrreenntt//ppee__ccrryyppttoo..hhpppp::7722 ****** | │ │ │ │ │ |#include | │ │ │ │ │ |#include | │ │ │ │ │ |#include | │ │ │ │ │ @@ -2026,14 +1921,119 @@ │ │ │ │ │ | // try to use SO_BINDTODEVICE here, if that exists. If it fails, | │ │ │ │ │ | // fall back to the mechanism we have below | │ │ │ │ │ | aux::bind_device(sock, device_name, ec); | │ │ │ │ │ | if (ec) | │ │ │ │ │ |#endif | │ │ │ │ │ | { | │ │ │ │ │ |_ _ _ _e_c_._c_l_e_a_r_(_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 3|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |if we make this be a disk_buffer_holder instead we would save a copy use allocate_disk_receive_buffer and | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_w_e_b___p_e_e_r___c_o_n_n_e_c_t_i_o_n_._h_p_p_:_1_1_9_ _ _ _|_r_e_l_e_a_s_e___d_i_s_k___r_e_c_e_i_v_e___b_u_f_f_e_r_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** iiff wwee mmaakkee tthhiiss bbee aa ddiisskk__bbuuffffeerr__hhoollddeerr iinnsstteeaadd wwee wwoouulldd ssaavvee aa ccooppyy uussee aallllooccaattee__ddiisskk__rreecceeiivvee__bbuuffffeerr aanndd rreelleeaassee__ddiisskk__rreecceeiivvee__bbuuffffeerr ********** | │ │ │ │ │ +|****** ....//iinncclluuddee//lliibbttoorrrreenntt//wweebb__ppeeeerr__ccoonnnneeccttiioonn..hhpppp::111199 ****** | │ │ │ │ │ +|piece_block_progress downloading_piece_progress() const override; | │ │ │ │ │ +| | │ │ │ │ │ +| void handle_padfile(); | │ │ │ │ │ +| | │ │ │ │ │ +| // this has one entry per http-request | │ │ │ │ │ +| // (might be more than the bt requests) | │ │ │ │ │ +| struct file_request_t | │ │ │ │ │ +| { | │ │ │ │ │ +| file_index_t file_index; | │ │ │ │ │ +| int length; | │ │ │ │ │ +| std::int64_t start; | │ │ │ │ │ +| }; | │ │ │ │ │ +| std::deque m_file_requests; | │ │ │ │ │ +| | │ │ │ │ │ +| std::string m_url; | │ │ │ │ │ +| | │ │ │ │ │ +| web_seed_t* m_web; | │ │ │ │ │ +| | │ │ │ │ │ +| // this is used for intermediate storage of pieces to be delivered to the | │ │ │ │ │ +| // bittorrent engine | │ │ │ │ │ +|aux::vector m_piece; | │ │ │ │ │ +| | │ │ │ │ │ +| // the number of bytes we've forwarded to the incoming_payload() function | │ │ │ │ │ +| // in the current HTTP response. used to know where in the buffer the | │ │ │ │ │ +| // next response starts | │ │ │ │ │ +| int m_received_body; | │ │ │ │ │ +| | │ │ │ │ │ +| // this is the offset inside the current receive | │ │ │ │ │ +| // buffer where the next chunk header will be. | │ │ │ │ │ +| // this is updated for each chunk header that's | │ │ │ │ │ +| // parsed. It does not necessarily point to a valid | │ │ │ │ │ +| // offset in the receive buffer, if we haven't received | │ │ │ │ │ +| // it yet. This offset never includes the HTTP header | │ │ │ │ │ +| int m_chunk_pos; | │ │ │ │ │ +| | │ │ │ │ │ +| // this is the number of bytes we've already received | │ │ │ │ │ +| // from the next chunk header we're waiting for | │ │ │ │ │ +| int m_partial_chunk_header; | │ │ │ │ │ +| | │ │ │ │ │ +| // the number of responses we've received so far on | │ │ │ │ │ +| // this connection | │ │ │ │ │ +| int m_num_responses; | │ │ │ │ │ +| }; | │ │ │ │ │ +|} | │ │ │ │ │ +| | │ │ │ │ │ +|_#_e_n_d_i_f_ _/_/_ _T_O_R_R_E_N_T___W_E_B___P_E_E_R___C_O_N_N_E_C_T_I_O_N___H_P_P___I_N_C_L_U_D_E_D_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 3|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |unify url_seed and http_seed with just web_seed, using the web_seed_entry. | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_t_o_r_r_e_n_t___h_a_n_d_l_e_._h_p_p_:_5_3_5_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** uunniiffyy uurrll__sseeeedd aanndd hhttttpp__sseeeedd wwiitthh jjuusstt wweebb__sseeeedd,, uussiinngg tthhee wweebb__sseeeedd__eennttrryy.. ********** | │ │ │ │ │ +|****** ....//iinncclluuddee//lliibbttoorrrreenntt//ttoorrrreenntt__hhaannddllee..hhpppp::553355 ****** | │ │ │ │ │ +|// one returned from ``trackers()`` and will replace it. If you want an | │ │ │ │ │ +| // immediate effect, you have to call force_reannounce(). See | │ │ │ │ │ +| // announce_entry. | │ │ │ │ │ +| // | │ │ │ │ │ +| // ``post_trackers()`` is the asynchronous version of ``trackers()``. It | │ │ │ │ │ +| // will trigger a tracker_list_alert to be posted. | │ │ │ │ │ +| // | │ │ │ │ │ +| // ``add_tracker()`` will look if the specified tracker is already in the | │ │ │ │ │ +| // set. If it is, it doesn't do anything. If it's not in the current set | │ │ │ │ │ +| // of trackers, it will insert it in the tier specified in the | │ │ │ │ │ +| // announce_entry. | │ │ │ │ │ +| // | │ │ │ │ │ +| // The updated set of trackers will be saved in the resume data, and when | │ │ │ │ │ +| // a torrent is started with resume data, the trackers from the resume | │ │ │ │ │ +| // data will replace the original ones. | │ │ │ │ │ +| std::vector trackers() const; | │ │ │ │ │ +| void replace_trackers(std::vector const&) const; | │ │ │ │ │ +| void add_tracker(announce_entry const&) const; | │ │ │ │ │ +| void post_trackers() const; | │ │ │ │ │ +| | │ │ │ │ │ +| | │ │ │ │ │ +|// ``add_url_seed()`` adds another url to the torrent's list of url | │ │ │ │ │ +| // seeds. If the given url already exists in that list, the call has no | │ │ │ │ │ +| // effect. The torrent will connect to the server and try to download | │ │ │ │ │ +| // pieces from it, unless it's paused, queued, checking or seeding. | │ │ │ │ │ +| // ``remove_url_seed()`` removes the given url if it exists already. | │ │ │ │ │ +| // ``url_seeds()`` return a set of the url seeds currently in this | │ │ │ │ │ +| // torrent. Note that URLs that fails may be removed automatically from | │ │ │ │ │ +| // the list. | │ │ │ │ │ +| // | │ │ │ │ │ +| // See http-seeding_ for more information. | │ │ │ │ │ +| void add_url_seed(std::string const& url) const; | │ │ │ │ │ +| void remove_url_seed(std::string const& url) const; | │ │ │ │ │ +| std::set url_seeds() const; | │ │ │ │ │ +| | │ │ │ │ │ +| // These functions are identical as the ``*_url_seed()`` variants, but | │ │ │ │ │ +| // they operate on `BEP 17`_ web seeds instead of `BEP 19`_. | │ │ │ │ │ +| // | │ │ │ │ │ +| // See http-seeding_ for more information. | │ │ │ │ │ +| void add_http_seed(std::string const& url) const; | │ │ │ │ │ +| void remove_http_seed(std::string const& url) const; | │ │ │ │ │ +| std::set http_seeds() const; | │ │ │ │ │ +| | │ │ │ │ │ +| // add the specified extension to this torrent. The ``ext`` argument is | │ │ │ │ │ +| // a function that will be called from within libtorrent's context | │ │ │ │ │ +| // passing in the internal torrent object and the specified userdata | │ │ │ │ │ +| // pointer. The function is expected to return a shared pointer to | │ │ │ │ │ +| // a torrent_plugin instance. | │ │ │ │ │ +| void add_extension( | │ │ │ │ │ +| std::function(torrent_handle const&, client_data_t)> const& ext | │ │ │ │ │ +|_ _ _ _,_ _c_l_i_e_n_t___d_a_t_a___t_ _u_s_e_r_d_a_t_a_ _=_ _c_l_i_e_n_t___d_a_t_a___t_{_}_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |relevance 3|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |to improve memory locality and scanning performance, turn the routing table into a single vector with boundaries for the nodes | │ │ │ │ │ |_ _ _ _ _ _ _ _ _ _ _ _|_k_a_d_e_m_l_i_a_/_r_o_u_t_i_n_g___t_a_b_l_e_._h_p_p_:_1_5_3_|_i_n_s_t_e_a_d_._ _P_e_r_h_a_p_s_ _r_e_p_l_a_c_e_m_e_n_t_ _n_o_d_e_s_ _s_h_o_u_l_d_ _b_e_ _i_n_ _a_ _s_e_p_a_r_a_t_e_ _v_e_c_t_o_r_._ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** ttoo iimmpprroovvee mmeemmoorryy llooccaalliittyy aanndd ssccaannnniinngg ppeerrffoorrmmaannccee,, ttuurrnn tthhee rroouuttiinngg ttaabbllee iinnttoo aa ssiinnggllee vveeccttoorr wwiitthh bboouunnddaarriieess ffoorr tthhee nnooddeess iinnsstteeaadd.. PPeerrhhaappss rreeppllaacceemmeenntt nnooddeess sshhoouulldd | │ │ │ │ │ |bbee iinn aa sseeppaarraattee vveeccttoorr.. ********** | │ │ │ │ │ |****** ....//iinncclluuddee//lliibbttoorrrreenntt//kkaaddeemmlliiaa//rroouuttiinngg__ttaabbllee..hhpppp::115533 ****** | │ │ │ │ │ |// * Nodes are not marked as being stale, they keep a counter | │ │ │ │ │ |// that tells how many times in a row they have failed. When | │ │ │ │ │ @@ -2136,68 +2136,14 @@ │ │ │ │ │ | , move_flags_t flags, storage_error& ec); | │ │ │ │ │ | | │ │ │ │ │ | // deletes the files on fs from save_path according to options. Options may | │ │ │ │ │ | // opt to only delete the partfile | │ │ │ │ │ | TORRENT_EXTRA_EXPORT void | │ │ │ │ │ | delete_files(file_storage const& fs, std::string const& save_path | │ │ │ │ │ |_ _ _,_ _s_t_d_:_:_s_t_r_i_n_g_ _c_o_n_s_t_&_ _p_a_r_t___f_i_l_e___n_a_m_e_,_ _r_e_m_o_v_e___f_l_a_g_s___t_ _o_p_t_i_o_n_s_,_ _s_t_o_r_a_g_e___e_r_r_o_r_&_ _e_c_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _2_|_._._/_t_e_s_t_/_t_e_s_t___s_t_o_r_a_g_e_._c_p_p_:_6_3_9_ _ _|_s_p_l_i_t_ _t_h_i_s_ _t_e_s_t_ _u_p_ _i_n_t_o_ _s_m_a_l_l_e_r_ _p_a_r_t_s_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** sspplliitt tthhiiss tteesstt uupp iinnttoo ssmmaalllleerr ppaarrttss ********** | │ │ │ │ │ -|****** ....//tteesstt//tteesstt__ssttoorraaggee..ccpppp::663399 ****** | │ │ │ │ │ -|io->submit_jobs(); | │ │ │ │ │ -| ios.restart(); | │ │ │ │ │ -| run_until(ios, done); | │ │ │ │ │ -| | │ │ │ │ │ -| TEST_EQUAL(oversized, bool(flags & test_oversized)); | │ │ │ │ │ -| | │ │ │ │ │ -| for (auto const i : info->piece_range()) | │ │ │ │ │ -| { | │ │ │ │ │ -| done = false; | │ │ │ │ │ -| io->async_hash(st, i, {} | │ │ │ │ │ -| , disk_interface::sequential_access | disk_interface::volatile_read | disk_interface::v1_hash | │ │ │ │ │ -| , std::bind(&on_piece_checked, _1, _2, _3, &done)); | │ │ │ │ │ -| io->submit_jobs(); | │ │ │ │ │ -| ios.restart(); | │ │ │ │ │ -| run_until(ios, done); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| io->abort(true); | │ │ │ │ │ -|} | │ │ │ │ │ -| | │ │ │ │ │ -|template | │ │ │ │ │ -|void run_test() | │ │ │ │ │ -|{ | │ │ │ │ │ -| std::string const test_path = current_working_directory(); | │ │ │ │ │ -| std::cout << "\n=== " << test_path << " ===\n" << std::endl; | │ │ │ │ │ -| | │ │ │ │ │ -| std::shared_ptr info; | │ │ │ │ │ -| | │ │ │ │ │ -| std::vector piece0 = new_piece(piece_size); | │ │ │ │ │ -| std::vector piece1 = new_piece(piece_size); | │ │ │ │ │ -| std::vector piece2 = new_piece(piece_size); | │ │ │ │ │ -| std::vector piece3 = new_piece(piece_size); | │ │ │ │ │ -| | │ │ │ │ │ -| delete_dirs("temp_storage"); | │ │ │ │ │ -| | │ │ │ │ │ -| file_storage fs; | │ │ │ │ │ -| fs.add_file("temp_storage/test1.tmp", 17); | │ │ │ │ │ -| fs.add_file("temp_storage/test2.tmp", 612); | │ │ │ │ │ -| fs.add_file("temp_storage/test3.tmp", 0); | │ │ │ │ │ -| fs.add_file("temp_storage/test4.tmp", 0); | │ │ │ │ │ -| fs.add_file("temp_storage/test5.tmp", 3253); | │ │ │ │ │ -| fs.add_file("temp_storage/test6.tmp", 841); | │ │ │ │ │ -| int const last_file_size = 4 * int(piece_size) - int(fs.total_size()); | │ │ │ │ │ -| fs.add_file("temp_storage/test7.tmp", last_file_size); | │ │ │ │ │ -| | │ │ │ │ │ -| // File layout | │ │ │ │ │ -| // +-+--+++-------+-------+----------------------------------------------------------------------------------------+ | │ │ │ │ │ -| // |1| 2||| file5 | file6 | file7 | | │ │ │ │ │ -| // +-+--+++-------+-------+----------------------------------------------------------------------------------------+ | │ │ │ │ │ -| // | | | | | | │ │ │ │ │ -|_ _/_/_ _|_ _p_i_e_c_e_ _0_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _p_i_e_c_e_ _1_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _p_i_e_c_e_ _2_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _p_i_e_c_e_ _3_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |_r_e_l_e_v_a_n_c_e_ _2_|_._._/_t_e_s_t_/_t_e_s_t___d_h_t_._c_p_p_:_1_6_4_2_ _ _ _ _ _|_t_e_s_t_ _n_u_m___g_l_o_b_a_l___n_o_d_e_s_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** tteesstt nnuumm__gglloobbaall__nnooddeess ********** | │ │ │ │ │ |_**_**_**_ _.._.._//_tt_ee_ss_tt_//_tt_ee_ss_tt____dd_hh_tt_.._cc_pp_pp_::_11_66_44_22_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |_r_e_l_e_v_a_n_c_e_ _2_|_._._/_t_e_s_t_/_t_e_s_t___d_h_t_._c_p_p_:_1_6_4_3_ _ _ _ _ _|_t_e_s_t_ _n_e_e_d___r_e_f_r_e_s_h_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** tteesstt nneeeedd__rreeffrreesshh ********** | │ │ │ │ │ |****** ....//tteesstt//tteesstt__ddhhtt..ccpppp::11664433 ****** | │ │ │ │ │ | s.set_bool(settings_pack::dht_restrict_routing_ips, false); | │ │ │ │ │ @@ -2298,241 +2244,126 @@ │ │ │ │ │ | bool ret = verify_message(ent, msg_desc, msg_keys, error_string); | │ │ │ │ │ | TEST_CHECK(ret); | │ │ │ │ │ | TEST_CHECK(msg_keys[0]); | │ │ │ │ │ | if (msg_keys[0]) TEST_EQUAL(msg_keys[0].string_value(), "test"); | │ │ │ │ │ | TEST_CHECK(msg_keys[1]); | │ │ │ │ │ | TEST_CHECK(msg_keys[2]); | │ │ │ │ │ |_ _i_f_ _(_m_s_g___k_e_y_s_[_2_]_)_ _T_E_S_T___E_Q_U_A_L_(_m_s_g___k_e_y_s_[_2_]_._s_t_r_i_n_g___v_a_l_u_e_(_)_,_ _"_t_e_s_t_2_"_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 2|_._._/_t_e_s_t_/_t_e_s_t___p_i_e_c_e___p_i_c_k_e_r_._c_p_p_:|test picking with partial pieces and other peers present so that both backup_pieces and backup_pieces2 are used | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_2_8_2_5_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tteesstt ppiicckkiinngg wwiitthh ppaarrttiiaall ppiieecceess aanndd ootthheerr ppeeeerrss pprreesseenntt ssoo tthhaatt bbootthh bbaacckkuupp__ppiieecceess aanndd bbaacckkuupp__ppiieecceess22 aarree uusseedd ********** | │ │ │ │ │ -|_**_**_**_ _.._.._//_tt_ee_ss_tt_//_tt_ee_ss_tt____pp_ii_ee_cc_ee____pp_ii_cc_kk_ee_rr_.._cc_pp_pp_::_22_88_22_55_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 2|_._._/_s_r_c_/_p_e_e_r___c_o_n_n_e_c_t_i_o_n_._c_p_p_: |this should probably be based on time instead of number of request messages. For a very high throughput connection, 300 may be a | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_2_5_4_8_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_l_e_g_i_t_i_m_a_t_e_ _n_u_m_b_e_r_ _o_f_ _r_e_q_u_e_s_t_s_ _t_o_ _h_a_v_e_ _i_n_ _f_l_i_g_h_t_ _w_h_e_n_ _g_e_t_t_i_n_g_ _c_h_o_k_e_d_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tthhiiss sshhoouulldd pprroobbaabbllyy bbee bbaasseedd oonn ttiimmee iinnsstteeaadd ooff nnuummbbeerr ooff rreeqquueesstt mmeessssaaggeess.. FFoorr aa vveerryy hhiigghh tthhrroouugghhppuutt ccoonnnneeccttiioonn,, 330000 mmaayy bbee aa lleeggiittiimmaattee nnuummbbeerr ooff rreeqquueessttss ttoo hhaavvee iinn| │ │ │ │ │ -|fflliigghhtt wwhheenn ggeettttiinngg cchhookkeedd ********** | │ │ │ │ │ -|****** ....//ssrrcc//ppeeeerr__ccoonnnneeccttiioonn..ccpppp::22554488 ****** | │ │ │ │ │ -|} | │ │ │ │ │ -|#endif | │ │ │ │ │ -| | │ │ │ │ │ -| write_reject_request(r); | │ │ │ │ │ -| if (m_num_invalid_requests < std::numeric_limits::max()) | │ │ │ │ │ -| ++m_num_invalid_requests; | │ │ │ │ │ -| | │ │ │ │ │ -| if (t->alerts().should_post()) | │ │ │ │ │ -| { | │ │ │ │ │ -| // msvc 12 appears to deduce the rvalue reference template | │ │ │ │ │ -| // incorrectly for bool temporaries. So, create a dummy instance | │ │ │ │ │ -| bool const peer_interested = bool(m_peer_interested); | │ │ │ │ │ -| t->alerts().emplace_alert( | │ │ │ │ │ -| t->get_handle(), m_remote, m_peer_id, r | │ │ │ │ │ -| , t->has_piece_passed(r.piece), peer_interested, false); | │ │ │ │ │ -| } | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _2_|_._._/_t_e_s_t_/_t_e_s_t___s_t_o_r_a_g_e_._c_p_p_:_6_3_9_ _ _|_s_p_l_i_t_ _t_h_i_s_ _t_e_s_t_ _u_p_ _i_n_t_o_ _s_m_a_l_l_e_r_ _p_a_r_t_s_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** sspplliitt tthhiiss tteesstt uupp iinnttoo ssmmaalllleerr ppaarrttss ********** | │ │ │ │ │ +|****** ....//tteesstt//tteesstt__ssttoorraaggee..ccpppp::663399 ****** | │ │ │ │ │ +|io->submit_jobs(); | │ │ │ │ │ +| ios.restart(); | │ │ │ │ │ +| run_until(ios, done); | │ │ │ │ │ | | │ │ │ │ │ -| // every ten invalid request, remind the peer that it's choked | │ │ │ │ │ -| if (!m_peer_interested && m_num_invalid_requests % 10 == 0 && m_choked) | │ │ │ │ │ -| { | │ │ │ │ │ -|if (m_num_invalid_requests > 300 && !m_peer_choked | │ │ │ │ │ -|&& can_disconnect(errors::too_many_requests_when_choked)) | │ │ │ │ │ -| { | │ │ │ │ │ -| disconnect(errors::too_many_requests_when_choked, operation_t::bittorrent, peer_error); | │ │ │ │ │ -| return; | │ │ │ │ │ -| } | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ -| peer_log(peer_log_alert::outgoing_message, "CHOKE"); | │ │ │ │ │ -|#endif | │ │ │ │ │ -| write_choke(); | │ │ │ │ │ -| } | │ │ │ │ │ +| TEST_EQUAL(oversized, bool(flags & test_oversized)); | │ │ │ │ │ | | │ │ │ │ │ -| return; | │ │ │ │ │ -| } | │ │ │ │ │ +| for (auto const i : info->piece_range()) | │ │ │ │ │ +| { | │ │ │ │ │ +| done = false; | │ │ │ │ │ +| io->async_hash(st, i, {} | │ │ │ │ │ +| , disk_interface::sequential_access | disk_interface::volatile_read | disk_interface::v1_hash | │ │ │ │ │ +| , std::bind(&on_piece_checked, _1, _2, _3, &done)); | │ │ │ │ │ +| io->submit_jobs(); | │ │ │ │ │ +| ios.restart(); | │ │ │ │ │ +| run_until(ios, done); | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -| // if we have choked the client | │ │ │ │ │ -| // ignore the request | │ │ │ │ │ -| int const blocks_per_piece = | │ │ │ │ │ -| (ti.piece_length() + t->block_size() - 1) / t->block_size(); | │ │ │ │ │ +| io->abort(true); | │ │ │ │ │ +|} | │ │ │ │ │ | | │ │ │ │ │ -| // disconnect peers that downloads more than foo times an allowed | │ │ │ │ │ -| // fast piece | │ │ │ │ │ -| if (m_choked && fast_idx != -1 && m_accept_fast_piece_cnt[fast_idx] >= 3 * blocks_per_piece | │ │ │ │ │ -| && can_disconnect(errors::too_many_requests_when_choked)) | │ │ │ │ │ -| { | │ │ │ │ │ -| disconnect(errors::too_many_requests_when_choked, operation_t::bittorrent, peer_error); | │ │ │ │ │ -| return; | │ │ │ │ │ -| } | │ │ │ │ │ +|template | │ │ │ │ │ +|void run_test() | │ │ │ │ │ +|{ | │ │ │ │ │ +| std::string const test_path = current_working_directory(); | │ │ │ │ │ +| std::cout << "\n=== " << test_path << " ===\n" << std::endl; | │ │ │ │ │ | | │ │ │ │ │ -| if (m_choked && fast_idx == -1) | │ │ │ │ │ -|_ _ _{_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -| |_._._/_s_r_c_/_p_e_e_r___c_o_n_n_e_c_t_i_o_n_._c_p_p_: |since we throw away the queue entry once we issue the disk job, this may happen. Instead, we should keep the queue entry around, | │ │ │ │ │ -|relevance 2|_3_2_9_3 |mark it as having been requested from disk and once the disk job comes back, discard it if it has been cancelled. Maybe even be able| │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_t_o_ _c_a_n_c_e_l_ _d_i_s_k_ _j_o_b_s_?_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** ssiinnccee wwee tthhrrooww aawwaayy tthhee qquueeuuee eennttrryy oonnccee wwee iissssuuee tthhee ddiisskk jjoobb,, tthhiiss mmaayy hhaappppeenn.. IInnsstteeaadd,, wwee sshhoouulldd kkeeeepp tthhee qquueeuuee eennttrryy aarroouunndd,, mmaarrkk iitt aass hhaavviinngg bbeeeenn rreeqquueesstteedd ffrroomm | │ │ │ │ │ -|ddiisskk aanndd oonnccee tthhee ddiisskk jjoobb ccoommeess bbaacckk,, ddiissccaarrdd iitt iiff iitt hhaass bbeeeenn ccaanncceelllleedd.. MMaayybbee eevveenn bbee aabbllee ttoo ccaanncceell ddiisskk jjoobbss?? ********** | │ │ │ │ │ -|****** ....//ssrrcc//ppeeeerr__ccoonnnneeccttiioonn..ccpppp::33229933 ****** | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ -| peer_log(peer_log_alert::incoming_message, "CANCEL" | │ │ │ │ │ -| , "piece: %d s: %x l: %x", static_cast(r.piece), r.start, r.length); | │ │ │ │ │ -|#endif | │ │ │ │ │ +| std::shared_ptr info; | │ │ │ │ │ | | │ │ │ │ │ -| auto const i = std::find(m_requests.begin(), m_requests.end(), r); | │ │ │ │ │ +| std::vector piece0 = new_piece(piece_size); | │ │ │ │ │ +| std::vector piece1 = new_piece(piece_size); | │ │ │ │ │ +| std::vector piece2 = new_piece(piece_size); | │ │ │ │ │ +| std::vector piece3 = new_piece(piece_size); | │ │ │ │ │ | | │ │ │ │ │ -| if (i != m_requests.end()) | │ │ │ │ │ -| { | │ │ │ │ │ -| m_counters.inc_stats_counter(counters::cancelled_piece_requests); | │ │ │ │ │ -| m_requests.erase(i); | │ │ │ │ │ +| delete_dirs("temp_storage"); | │ │ │ │ │ | | │ │ │ │ │ -| if (m_requests.empty()) | │ │ │ │ │ -| m_counters.inc_stats_counter(counters::num_peers_up_requests, -1); | │ │ │ │ │ +| file_storage fs; | │ │ │ │ │ +| fs.add_file("temp_storage/test1.tmp", 17); | │ │ │ │ │ +| fs.add_file("temp_storage/test2.tmp", 612); | │ │ │ │ │ +| fs.add_file("temp_storage/test3.tmp", 0); | │ │ │ │ │ +| fs.add_file("temp_storage/test4.tmp", 0); | │ │ │ │ │ +| fs.add_file("temp_storage/test5.tmp", 3253); | │ │ │ │ │ +| fs.add_file("temp_storage/test6.tmp", 841); | │ │ │ │ │ +| int const last_file_size = 4 * int(piece_size) - int(fs.total_size()); | │ │ │ │ │ +| fs.add_file("temp_storage/test7.tmp", last_file_size); | │ │ │ │ │ | | │ │ │ │ │ -| write_reject_request(r); | │ │ │ │ │ -| } | │ │ │ │ │ -| else | │ │ │ │ │ -| { | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ -|peer_log(peer_log_alert::info, "INVALID_CANCEL", "got cancel not in the queue"); | │ │ │ │ │ -|#endif | │ │ │ │ │ -| } | │ │ │ │ │ -| } | │ │ │ │ │ +| // File layout | │ │ │ │ │ +| // +-+--+++-------+-------+----------------------------------------------------------------------------------------+ | │ │ │ │ │ +| // |1| 2||| file5 | file6 | file7 | | │ │ │ │ │ +| // +-+--+++-------+-------+----------------------------------------------------------------------------------------+ | │ │ │ │ │ +| // | | | | | | │ │ │ │ │ +|_ _/_/_ _|_ _p_i_e_c_e_ _0_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _p_i_e_c_e_ _1_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _p_i_e_c_e_ _2_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _p_i_e_c_e_ _3_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 2|_._._/_t_e_s_t_/_t_e_s_t___p_i_e_c_e___p_i_c_k_e_r_._c_p_p_:|test picking with partial pieces and other peers present so that both backup_pieces and backup_pieces2 are used | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_2_8_2_5_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tteesstt ppiicckkiinngg wwiitthh ppaarrttiiaall ppiieecceess aanndd ootthheerr ppeeeerrss pprreesseenntt ssoo tthhaatt bbootthh bbaacckkuupp__ppiieecceess aanndd bbaacckkuupp__ppiieecceess22 aarree uusseedd ********** | │ │ │ │ │ +|_**_**_**_ _.._.._//_tt_ee_ss_tt_//_tt_ee_ss_tt____pp_ii_ee_cc_ee____pp_ii_cc_kk_ee_rr_.._cc_pp_pp_::_22_88_22_55_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _2_|_._._/_s_r_c_/_a_l_e_r_t_._c_p_p_:_2_0_2_1_ _ _ _ _ _ _ _ _ _|_t_h_e_ _s_a_l_t_ _h_e_r_e_ _i_s_ _a_l_l_o_c_a_t_e_d_ _o_n_ _t_h_e_ _h_e_a_p_._ _I_t_ _w_o_u_l_d_ _b_e_ _n_i_c_e_ _t_o_ _a_l_l_o_c_a_t_e_ _i_n_ _t_h_e_ _s_t_a_c_k___a_l_l_o_c_a_t_o_r_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tthhee ssaalltt hheerree iiss aallllooccaatteedd oonn tthhee hheeaapp.. IItt wwoouulldd bbee nniiccee ttoo aallllooccaattee iinn tthhee ssttaacckk__aallllooccaattoorr ********** | │ │ │ │ │ +|****** ....//ssrrcc//aalleerrtt..ccpppp::22002211 ****** | │ │ │ │ │ +|} | │ │ │ │ │ | | │ │ │ │ │ -| // ----------------------------- | │ │ │ │ │ -| // --------- DHT PORT ---------- | │ │ │ │ │ -| // ----------------------------- | │ │ │ │ │ +| dht_immutable_item_alert::dht_immutable_item_alert(aux::stack_allocator& | │ │ │ │ │ +| , sha1_hash const& t, entry i) | │ │ │ │ │ +| : target(t), item(std::move(i)) | │ │ │ │ │ +| {} | │ │ │ │ │ | | │ │ │ │ │ -| void peer_connection::incoming_dht_port(int const listen_port) | │ │ │ │ │ +| std::string dht_immutable_item_alert::message() const | │ │ │ │ │ | { | │ │ │ │ │ -| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ -| INVARIANT_CHECK; | │ │ │ │ │ -| | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ -| peer_log(peer_log_alert::incoming_message, "DHT_PORT", "p: %d", listen_port); | │ │ │ │ │ -|#endif | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_DHT | │ │ │ │ │ -| m_ses.add_dht_node({m_remote.address(), std::uint16_t(listen_port)}); | │ │ │ │ │ +|#ifdef TORRENT_DISABLE_ALERT_MSG | │ │ │ │ │ +| return {}; | │ │ │ │ │ |#else | │ │ │ │ │ -| TORRENT_UNUSED(listen_port); | │ │ │ │ │ +| char msg[1050]; | │ │ │ │ │ +| std::snprintf(msg, sizeof(msg), "DHT immutable item %s [ %s ]" | │ │ │ │ │ +| , aux::to_hex(target).c_str() | │ │ │ │ │ +| , item.to_string().c_str()); | │ │ │ │ │ +| return msg; | │ │ │ │ │ |#endif | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -| // ----------------------------- | │ │ │ │ │ -| // --------- HAVE ALL ---------- | │ │ │ │ │ -| // ----------------------------- | │ │ │ │ │ -| | │ │ │ │ │ -| void peer_connection::incoming_have_all() | │ │ │ │ │ -|_ _{_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 2|_._._/_s_r_c_/_p_e_e_r___c_o_n_n_e_c_t_i_o_n_._c_p_p_: |use a deadline_timer for timeouts. Don't rely on second_tick()! Hook this up to connect timeout as well. This would improve | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_4_9_5_8_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_p_e_r_f_o_r_m_a_n_c_e_ _b_e_c_a_u_s_e_ _o_f_ _l_e_s_s_ _w_o_r_k_ _i_n_ _s_e_c_o_n_d___t_i_c_k_(_)_,_ _a_n_d_ _m_i_g_h_t_ _l_e_t_ _u_s_e_ _r_e_m_o_v_e_ _t_i_c_k_i_n_g_ _e_n_t_i_r_e_l_y_ _e_v_e_n_t_u_a_l_l_y_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** uussee aa ddeeaaddlliinnee__ttiimmeerr ffoorr ttiimmeeoouuttss.. DDoonn''tt rreellyy oonn sseeccoonndd__ttiicckk(())!! HHooookk tthhiiss uupp ttoo ccoonnnneecctt ttiimmeeoouutt aass wweellll.. TThhiiss wwoouulldd iimmpprroovvee ppeerrffoorrmmaannccee bbeeccaauussee ooff lleessss wwoorrkk iinn | │ │ │ │ │ -|sseeccoonndd__ttiicckk(()),, aanndd mmiigghhtt lleett uussee rreemmoovvee ttiicckkiinngg eennttiirreellyy eevveennttuuaallllyy ********** | │ │ │ │ │ -|****** ....//ssrrcc//ppeeeerr__ccoonnnneeccttiioonn..ccpppp::44995588 ****** | │ │ │ │ │ -|if (d > seconds(connect_timeout) | │ │ │ │ │ -| && can_disconnect(errors::timed_out)) | │ │ │ │ │ -| { | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ -| peer_log(peer_log_alert::info, "CONNECT_FAILED", "waited %d seconds" | │ │ │ │ │ -| , int(total_seconds(d))); | │ │ │ │ │ -|#endif | │ │ │ │ │ -| connect_failed(errors::timed_out); | │ │ │ │ │ -| return; | │ │ │ │ │ -| } | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| // if the bw_network flag isn't set, it means we are not even trying to | │ │ │ │ │ -| // read from this peer's socket. Most likely because we're applying a | │ │ │ │ │ -| // rate limit. If the peer is "slow" because we are rate limiting it, | │ │ │ │ │ -| // don't enforce timeouts. However, as soon as we *do* read from the | │ │ │ │ │ -| // socket, we expect to receive data, and not have timed out. Then we | │ │ │ │ │ -| // can enforce the timeouts. | │ │ │ │ │ -| bool const reading_socket = bool(m_channel_state[download_channel] & peer_info::bw_network); | │ │ │ │ │ -| | │ │ │ │ │ -|if (reading_socket && d > seconds(timeout()) && !m_connecting && m_reading_bytes == 0 | │ │ │ │ │ -|&& can_disconnect(errors::timed_out_inactivity)) | │ │ │ │ │ -| { | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ -| peer_log(peer_log_alert::info, "LAST_ACTIVITY", "%d seconds ago" | │ │ │ │ │ -| , int(total_seconds(d))); | │ │ │ │ │ -|#endif | │ │ │ │ │ -| disconnect(errors::timed_out_inactivity, operation_t::bittorrent); | │ │ │ │ │ -| return; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| // do not stall waiting for a handshake | │ │ │ │ │ -| int timeout = m_settings.get_int (settings_pack::handshake_timeout); | │ │ │ │ │ -|#if TORRENT_USE_I2P | │ │ │ │ │ -| timeout *= is_i2p(m_socket) ? 4 : 1; | │ │ │ │ │ -|#endif | │ │ │ │ │ -| if (reading_socket | │ │ │ │ │ -| && !m_connecting | │ │ │ │ │ -| && in_handshake() | │ │ │ │ │ -| && d > seconds(timeout)) | │ │ │ │ │ -| { | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ -| peer_log(peer_log_alert::info, "NO_HANDSHAKE", "waited %d seconds" | │ │ │ │ │ -| , int(total_seconds(d))); | │ │ │ │ │ -|#endif | │ │ │ │ │ -| disconnect(errors::timed_out_no_handshake, operation_t::bittorrent); | │ │ │ │ │ -| return; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| // disconnect peers that we unchoked, but they didn't send a request in | │ │ │ │ │ -|_ _ _/_/_ _t_h_e_ _l_a_s_t_ _6_0_ _s_e_c_o_n_d_s_,_ _a_n_d_ _w_e_ _h_a_v_e_n_'_t_ _b_e_e_n_ _w_o_r_k_i_n_g_ _o_n_ _s_e_r_v_i_c_i_n_g_ _a_ _r_e_q_u_e_s_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 2|_._._/_s_r_c_/ |peer_connection and tracker_connection should probably be flags | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_i_n_s_t_a_n_t_i_a_t_e___c_o_n_n_e_c_t_i_o_n_._c_p_p_:_4_4_ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** ppeeeerr__ccoonnnneeccttiioonn aanndd ttrraacckkeerr__ccoonnnneeccttiioonn sshhoouulldd pprroobbaabbllyy bbee ffllaaggss ********** | │ │ │ │ │ -|****** ....//ssrrcc//iinnssttaannttiiaattee__ccoonnnneeccttiioonn..ccpppp::4444 ****** | │ │ │ │ │ -|ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | │ │ │ │ │ -|LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | │ │ │ │ │ -|CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | │ │ │ │ │ -|SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | │ │ │ │ │ -|INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | │ │ │ │ │ -|CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | │ │ │ │ │ -|ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | │ │ │ │ │ -|POSSIBILITY OF SUCH DAMAGE. | │ │ │ │ │ -| | │ │ │ │ │ -|*/ | │ │ │ │ │ -| | │ │ │ │ │ -|#include "libtorrent/socket.hpp" | │ │ │ │ │ -|#include "libtorrent/aux_/socket_type.hpp" | │ │ │ │ │ -|#include "libtorrent/aux_/utp_socket_manager.hpp" | │ │ │ │ │ -|#include "libtorrent/aux_/instantiate_connection.hpp" | │ │ │ │ │ -|#include "libtorrent/aux_/utp_stream.hpp" | │ │ │ │ │ -|#include "libtorrent/ssl_stream.hpp" | │ │ │ │ │ -| | │ │ │ │ │ -|namespace libtorrent { namespace aux { | │ │ │ │ │ +|dht_mutable_item_alert::dht_mutable_item_alert(aux::stack_allocator& | │ │ │ │ │ +|, std::array const& k | │ │ │ │ │ +| , std::array const& sig | │ │ │ │ │ +| , std::int64_t sequence | │ │ │ │ │ +| , string_view s | │ │ │ │ │ +| , entry i | │ │ │ │ │ +| , bool a) | │ │ │ │ │ +| : key(k), signature(sig), seq(sequence), salt(s), item(std::move(i)), authoritative(a) | │ │ │ │ │ +| {} | │ │ │ │ │ | | │ │ │ │ │ -|aux::socket_type instantiate_connection(io_context& ios | │ │ │ │ │ -|, aux::proxy_settings const& ps | │ │ │ │ │ -| , void* ssl_context | │ │ │ │ │ -| , utp_socket_manager* sm | │ │ │ │ │ -| , bool peer_connection | │ │ │ │ │ -| , bool tracker_connection) | │ │ │ │ │ +| std::string dht_mutable_item_alert::message() const | │ │ │ │ │ | { | │ │ │ │ │ -|#if !TORRENT_USE_SSL | │ │ │ │ │ -| TORRENT_UNUSED(ssl_context); | │ │ │ │ │ +|#ifdef TORRENT_DISABLE_ALERT_MSG | │ │ │ │ │ +| return {}; | │ │ │ │ │ +|#else | │ │ │ │ │ +| char msg[1050]; | │ │ │ │ │ +| std::snprintf(msg, sizeof(msg), "DHT mutable item (key=%s salt=%s seq=%" PRId64 " %s) [ %s ]" | │ │ │ │ │ +| , aux::to_hex(key).c_str() | │ │ │ │ │ +| , salt.c_str() | │ │ │ │ │ +| , seq | │ │ │ │ │ +| , authoritative ? "auth" : "non-auth" | │ │ │ │ │ +| , item.to_string().c_str()); | │ │ │ │ │ +| return msg; | │ │ │ │ │ |#endif | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -| if (sm) | │ │ │ │ │ -| { | │ │ │ │ │ -|#if TORRENT_USE_SSL | │ │ │ │ │ -| if (ssl_context) | │ │ │ │ │ -| { | │ │ │ │ │ -| ssl_stream s(ios, *static_cast(ssl_context)); | │ │ │ │ │ -| s.next_layer().set_impl(sm->new_utp_socket(&s.next_layer())); | │ │ │ │ │ -| return socket_type(std::move(s)); | │ │ │ │ │ -| } | │ │ │ │ │ -| else | │ │ │ │ │ -|#endif | │ │ │ │ │ -| { | │ │ │ │ │ -| utp_stream s(ios); | │ │ │ │ │ -| s.set_impl(sm->new_utp_socket(&s)); | │ │ │ │ │ -| return socket_type(std::move(s)); | │ │ │ │ │ -| } | │ │ │ │ │ -| } | │ │ │ │ │ -|#if TORRENT_USE_I2P | │ │ │ │ │ -| else if (ps.type == settings_pack::i2p_proxy) | │ │ │ │ │ -|_ _ _{_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +| dht_put_alert::dht_put_alert(aux::stack_allocator&, sha1_hash const& t, int n) | │ │ │ │ │ +| : target(t) | │ │ │ │ │ +| , public_key() | │ │ │ │ │ +| , signature() | │ │ │ │ │ +|_ _ _,_ _s_a_l_t_(_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |relevance 2|_._._/_s_r_c_/ |just make this peer not have the pieces associated with the file we just requested. Only when it doesn't have any of the file do the| │ │ │ │ │ |_ _ _ _ _ _ _ _ _ _ _ _|_w_e_b___p_e_e_r___c_o_n_n_e_c_t_i_o_n_._c_p_p_:_6_2_6_ _ _ _|_f_o_l_l_o_w_i_n_g_ _p_a_d_ _f_i_l_e_s_ _w_i_l_l_ _m_a_k_e_ _i_t_ _c_o_m_p_l_i_c_a_t_e_d_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** jjuusstt mmaakkee tthhiiss ppeeeerr nnoott hhaavvee tthhee ppiieecceess aassssoocciiaatteedd wwiitthh tthhee ffiillee wwee jjuusstt rreeqquueesstteedd.. OOnnllyy wwhheenn iitt ddooeessnn''tt hhaavvee aannyy ooff tthhee ffiillee ddoo tthhee ffoolllloowwiinngg ppaadd ffiilleess wwiillll mmaakkee iitt | │ │ │ │ │ |ccoommpplliiccaatteedd ********** | │ │ │ │ │ |****** ....//ssrrcc//wweebb__ppeeeerr__ccoonnnneeccttiioonn..ccpppp::662266 ****** | │ │ │ │ │ | peer_connection::received_invalid_data(index, single_peer); | │ │ │ │ │ | | │ │ │ │ │ @@ -2580,340 +2411,177 @@ │ │ │ │ │ | } | │ │ │ │ │ | m_web = nullptr; | │ │ │ │ │ | TORRENT_ASSERT(is_disconnecting()); | │ │ │ │ │ |} | │ │ │ │ │ | | │ │ │ │ │ |void web_peer_connection::handle_redirect(int const bytes_left) | │ │ │ │ │ |_{_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _2_|_._._/_s_r_c_/_p_a_t_h_._c_p_p_:_4_2_9_ _ _ _ _ _ _ _ _ _ _ _|_t_e_s_t_ _t_h_i_s_ _o_n_ _a_ _F_A_T_ _v_o_l_u_m_e_ _t_o_ _s_e_e_ _w_h_a_t_ _e_r_r_o_r_ _w_e_ _g_e_t_!_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tteesstt tthhiiss oonn aa FFAATT vvoolluummee ttoo sseeee wwhhaatt eerrrroorr wwee ggeett!! ********** | │ │ │ │ │ -|****** ....//ssrrcc//ppaatthh..ccpppp::442299 ****** | │ │ │ │ │ -|// it's possible CreateHardLink will copy the file internally too, | │ │ │ │ │ -| // if the filesystem does not support it. | │ │ │ │ │ -| ec.assign(GetLastError(), system_category()); | │ │ │ │ │ -| return; | │ │ │ │ │ -| } | │ │ │ │ │ +|relevance 2|_._._/_s_r_c_/ |peer_connection and tracker_connection should probably be flags | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_i_n_s_t_a_n_t_i_a_t_e___c_o_n_n_e_c_t_i_o_n_._c_p_p_:_4_4_ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** ppeeeerr__ccoonnnneeccttiioonn aanndd ttrraacckkeerr__ccoonnnneeccttiioonn sshhoouulldd pprroobbaabbllyy bbee ffllaaggss ********** | │ │ │ │ │ +|****** ....//ssrrcc//iinnssttaannttiiaattee__ccoonnnneeccttiioonn..ccpppp::4444 ****** | │ │ │ │ │ +|ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | │ │ │ │ │ +|LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | │ │ │ │ │ +|CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | │ │ │ │ │ +|SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | │ │ │ │ │ +|INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | │ │ │ │ │ +|CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | │ │ │ │ │ +|ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | │ │ │ │ │ +|POSSIBILITY OF SUCH DAMAGE. | │ │ │ │ │ | | │ │ │ │ │ -| // fall back to making a copy | │ │ │ │ │ -|#endif | │ │ │ │ │ -|#else | │ │ │ │ │ -| // assume posix's link() function exists | │ │ │ │ │ -| int ret = ::link(n_exist.c_str(), n_link.c_str()); | │ │ │ │ │ +|*/ | │ │ │ │ │ | | │ │ │ │ │ -| if (ret == 0) | │ │ │ │ │ -| { | │ │ │ │ │ -| ec.clear(); | │ │ │ │ │ -| return; | │ │ │ │ │ -| } | │ │ │ │ │ +|#include "libtorrent/socket.hpp" | │ │ │ │ │ +|#include "libtorrent/aux_/socket_type.hpp" | │ │ │ │ │ +|#include "libtorrent/aux_/utp_socket_manager.hpp" | │ │ │ │ │ +|#include "libtorrent/aux_/instantiate_connection.hpp" | │ │ │ │ │ +|#include "libtorrent/aux_/utp_stream.hpp" | │ │ │ │ │ +|#include "libtorrent/ssl_stream.hpp" | │ │ │ │ │ | | │ │ │ │ │ -| // most errors are passed through, except for the ones that indicate that | │ │ │ │ │ -| // hard links are not supported and require a copy. | │ │ │ │ │ -|if (errno != EMLINK | │ │ │ │ │ -|&& errno != EXDEV | │ │ │ │ │ -|#ifdef TORRENT_BEOS | │ │ │ │ │ -| // haiku returns EPERM when the filesystem doesn't support hard link | │ │ │ │ │ -| && errno != EPERM | │ │ │ │ │ +|namespace libtorrent { namespace aux { | │ │ │ │ │ +| | │ │ │ │ │ +|aux::socket_type instantiate_connection(io_context& ios | │ │ │ │ │ +|, aux::proxy_settings const& ps | │ │ │ │ │ +| , void* ssl_context | │ │ │ │ │ +| , utp_socket_manager* sm | │ │ │ │ │ +| , bool peer_connection | │ │ │ │ │ +| , bool tracker_connection) | │ │ │ │ │ +| { | │ │ │ │ │ +|#if !TORRENT_USE_SSL | │ │ │ │ │ +| TORRENT_UNUSED(ssl_context); | │ │ │ │ │ |#endif | │ │ │ │ │ -| ) | │ │ │ │ │ +| | │ │ │ │ │ +| if (sm) | │ │ │ │ │ | { | │ │ │ │ │ -| // some error happened, report up to the caller | │ │ │ │ │ -| ec.assign(errno, system_category()); | │ │ │ │ │ -| return; | │ │ │ │ │ +|#if TORRENT_USE_SSL | │ │ │ │ │ +| if (ssl_context) | │ │ │ │ │ +| { | │ │ │ │ │ +| ssl_stream s(ios, *static_cast(ssl_context)); | │ │ │ │ │ +| s.next_layer().set_impl(sm->new_utp_socket(&s.next_layer())); | │ │ │ │ │ +| return socket_type(std::move(s)); | │ │ │ │ │ +| } | │ │ │ │ │ +| else | │ │ │ │ │ +|#endif | │ │ │ │ │ +| { | │ │ │ │ │ +| utp_stream s(ios); | │ │ │ │ │ +| s.set_impl(sm->new_utp_socket(&s)); | │ │ │ │ │ +| return socket_type(std::move(s)); | │ │ │ │ │ +| } | │ │ │ │ │ | } | │ │ │ │ │ -| | │ │ │ │ │ -| // fall back to making a copy | │ │ │ │ │ -| | │ │ │ │ │ +|#if TORRENT_USE_I2P | │ │ │ │ │ +| else if (ps.type == settings_pack::i2p_proxy) | │ │ │ │ │ +|_ _ _{_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _2_|_._._/_s_r_c_/_t_r_a_c_k_e_r___m_a_n_a_g_e_r_._c_p_p_:_3_6_9_|_i_m_p_l_e_m_e_n_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** iimmpplleemmeenntt ********** | │ │ │ │ │ +|****** ....//ssrrcc//ttrraacckkeerr__mmaannaaggeerr..ccpppp::336699 ****** | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ +| if (m_ses.should_log()) | │ │ │ │ │ +| { | │ │ │ │ │ +| m_ses.session_log("incoming UDP tracker packet from %s has invalid " | │ │ │ │ │ +| "transaction ID (%x)", print_endpoint(ep).c_str() | │ │ │ │ │ +| , transaction); | │ │ │ │ │ +| } | │ │ │ │ │ |#endif | │ │ │ │ │ +| return false; | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -| // if we get here, we should copy the file | │ │ │ │ │ -| storage_error se; | │ │ │ │ │ -| aux::copy_file(file, link, se); | │ │ │ │ │ -| ec = se.ec; | │ │ │ │ │ +| std::shared_ptr const p = i->second; | │ │ │ │ │ +| // on_receive() may remove the tracker connection from the list | │ │ │ │ │ +| return p->on_receive(ep, buf); | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -| bool is_directory(std::string const& f, error_code& ec) | │ │ │ │ │ +| void tracker_manager::incoming_error(error_code const& | │ │ │ │ │ +| , udp::endpoint const&) | │ │ │ │ │ | { | │ │ │ │ │ -| ec.clear(); | │ │ │ │ │ -| error_code e; | │ │ │ │ │ -| file_status s; | │ │ │ │ │ -| stat_file(f, &s, e); | │ │ │ │ │ -| if (!e && s.mode & file_status::directory) return true; | │ │ │ │ │ -|_ _ _e_c_ _=_ _e_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _2_|_._._/_s_r_c_/_b_d_e_c_o_d_e_._c_p_p_:_8_2_6_ _ _ _ _ _ _ _ _|_a_t_t_e_m_p_t_ _t_o_ _s_i_m_p_l_i_f_y_ _t_h_i_s_ _i_m_p_l_e_m_e_n_t_a_t_i_o_n_ _b_y_ _e_m_b_r_a_c_i_n_g_ _t_h_e_ _s_p_a_n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** aatttteemmpptt ttoo ssiimmpplliiffyy tthhiiss iimmpplleemmeennttaattiioonn bbyy eemmbbrraacciinngg tthhee ssppaann ********** | │ │ │ │ │ -|****** ....//ssrrcc//bbddeeccooddee..ccpppp::882266 ****** | │ │ │ │ │ +| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ |} | │ │ │ │ │ | | │ │ │ │ │ -| bdecode_node bdecode(span buffer | │ │ │ │ │ -| , error_code& ec, int* error_pos, int depth_limit, int token_limit) | │ │ │ │ │ +| bool tracker_manager::incoming_packet(string_view const hostname | │ │ │ │ │ +| , span const buf) | │ │ │ │ │ | { | │ │ │ │ │ -| bdecode_node ret; | │ │ │ │ │ -| ec.clear(); | │ │ │ │ │ -| | │ │ │ │ │ -| if (buffer.size() > bdecode_token::max_offset) | │ │ │ │ │ -| { | │ │ │ │ │ -| if (error_pos) *error_pos = 0; | │ │ │ │ │ -| ec = bdecode_errors::limit_exceeded; | │ │ │ │ │ -| return ret; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| // this is the stack of bdecode_token indices, into m_tokens. | │ │ │ │ │ -| // sp is the stack pointer, as index into the array, stack | │ │ │ │ │ -| int sp = 0; | │ │ │ │ │ -| TORRENT_ALLOCA(stack, stack_frame, depth_limit); | │ │ │ │ │ -| | │ │ │ │ │ -|char const* start = buffer.data(); | │ │ │ │ │ -|char const* end = start + buffer.size(); | │ │ │ │ │ -| char const* const orig_start = start; | │ │ │ │ │ -| | │ │ │ │ │ -| if (start == end) | │ │ │ │ │ -| TORRENT_FAIL_BDECODE(bdecode_errors::unexpected_eof); | │ │ │ │ │ -| | │ │ │ │ │ -| while (start <= end) | │ │ │ │ │ -| { | │ │ │ │ │ -| if (start >= end) TORRENT_FAIL_BDECODE(bdecode_errors::unexpected_eof); | │ │ │ │ │ -| | │ │ │ │ │ -| if (sp >= depth_limit) | │ │ │ │ │ -| TORRENT_FAIL_BDECODE(bdecode_errors::depth_exceeded); | │ │ │ │ │ -| | │ │ │ │ │ -| --token_limit; | │ │ │ │ │ -| if (token_limit < 0) | │ │ │ │ │ -| TORRENT_FAIL_BDECODE(bdecode_errors::limit_exceeded); | │ │ │ │ │ -| | │ │ │ │ │ -| // look for a new token | │ │ │ │ │ -| char const t = *start; | │ │ │ │ │ -| | │ │ │ │ │ -| int const current_frame = sp; | │ │ │ │ │ -| | │ │ │ │ │ -| // if we're currently parsing a dictionary, assert that | │ │ │ │ │ -| // every other node is a string. | │ │ │ │ │ -| if (current_frame > 0 | │ │ │ │ │ -| && ret.m_tokens[stack[current_frame - 1].token].type == bdecode_token::dict) | │ │ │ │ │ -| { | │ │ │ │ │ -| if (stack[current_frame - 1].state == 0) | │ │ │ │ │ -| { | │ │ │ │ │ -|_ _ _ _ _ _/_/_ _t_h_e_ _c_u_r_r_e_n_t_ _p_a_r_e_n_t_ _i_s_ _a_ _d_i_c_t_ _a_n_d_ _w_e_ _a_r_e_ _p_a_r_s_i_n_g_ _a_ _k_e_y_._ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _2_|_._._/_s_r_c_/_a_l_e_r_t___m_a_n_a_g_e_r_._c_p_p_:_8_0_ _ _ _|_k_e_e_p_ _a_ _c_o_u_n_t_ _o_f_ _t_h_e_ _n_u_m_b_e_r_ _o_f_ _t_h_r_e_a_d_s_ _w_a_i_t_i_n_g_._ _O_n_l_y_ _i_f_ _i_t_'_s_ _>_ _0_ _n_o_t_i_f_y_ _t_h_e_m_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** kkeeeepp aa ccoouunntt ooff tthhee nnuummbbeerr ooff tthhrreeaaddss wwaaiittiinngg.. OOnnllyy iiff iitt''ss >> 00 nnoottiiffyy tthheemm ********** | │ │ │ │ │ -|****** ....//ssrrcc//aalleerrtt__mmaannaaggeerr..ccpppp::8800 ****** | │ │ │ │ │ -|return m_alerts[m_generation].front(); | │ │ │ │ │ +| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ +| // ignore packets smaller than 8 bytes | │ │ │ │ │ +| if (buf.size() < 16) return false; | │ │ │ │ │ | | │ │ │ │ │ -| // this call can be interrupted prematurely by other signals | │ │ │ │ │ -| m_condition.wait_for(lock, max_wait); | │ │ │ │ │ -| if (!m_alerts[m_generation].empty()) | │ │ │ │ │ -| return m_alerts[m_generation].front(); | │ │ │ │ │ +| // the first word is the action, if it's not [0, 3] | │ │ │ │ │ +| // it's not a valid udp tracker response | │ │ │ │ │ +| span ptr = buf; | │ │ │ │ │ +| std::uint32_t const action = aux::read_uint32(ptr); | │ │ │ │ │ +| if (action > 3) return false; | │ │ │ │ │ | | │ │ │ │ │ -| return nullptr; | │ │ │ │ │ -| } | │ │ │ │ │ +| std::uint32_t const transaction = aux::read_uint32(ptr); | │ │ │ │ │ +| auto const i = m_udp_conns.find(transaction); | │ │ │ │ │ | | │ │ │ │ │ -| void alert_manager::maybe_notify(alert* a) | │ │ │ │ │ -| { | │ │ │ │ │ -| if (m_alerts[m_generation].size() == 1) | │ │ │ │ │ +| if (i == m_udp_conns.end()) | │ │ │ │ │ | { | │ │ │ │ │ -| // we just posted to an empty queue. If anyone is waiting for | │ │ │ │ │ -| // alerts, we need to notify them. Also (potentially) call the | │ │ │ │ │ -| // user supplied m_notify callback to let the client wake up its | │ │ │ │ │ -| // message loop to poll for alerts. | │ │ │ │ │ -| if (m_notify) m_notify(); | │ │ │ │ │ -| | │ │ │ │ │ -|m_condition.notify_all(); | │ │ │ │ │ -|} | │ │ │ │ │ -| | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_EXTENSIONS | │ │ │ │ │ -| for (auto& e : m_ses_extensions) | │ │ │ │ │ -| e->on_alert(a); | │ │ │ │ │ -|#else | │ │ │ │ │ -| TORRENT_UNUSED(a); | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ +| // now, this may not have been meant to be a tracker response, | │ │ │ │ │ +| // but chances are pretty good, so it's probably worth logging | │ │ │ │ │ +| m_ses.session_log("incoming UDP tracker packet from %s has invalid " | │ │ │ │ │ +| "transaction ID (%x)", std::string(hostname).c_str(), int(transaction)); | │ │ │ │ │ |#endif | │ │ │ │ │ +| return false; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| std::shared_ptr const p = i->second; | │ │ │ │ │ +|_ _ _/_/_ _o_n___r_e_c_e_i_v_e_(_)_ _m_a_y_ _r_e_m_o_v_e_ _t_h_e_ _t_r_a_c_k_e_r_ _c_o_n_n_e_c_t_i_o_n_ _f_r_o_m_ _t_h_e_ _l_i_s_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _2_|_._._/_s_r_c_/_e_s_c_a_p_e___s_t_r_i_n_g_._c_p_p_:_1_9_4_ _ _|_t_h_i_s_ _s_h_o_u_l_d_ _p_r_o_b_a_b_l_y_ _b_e_ _m_o_v_e_d_ _i_n_t_o_ _s_t_r_i_n_g___u_t_i_l_._c_p_p_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tthhiiss sshhoouulldd pprroobbaabbllyy bbee mmoovveedd iinnttoo ssttrriinngg__uuttiill..ccpppp ********** | │ │ │ │ │ +|****** ....//ssrrcc//eessccaappee__ssttrriinngg..ccpppp::119944 ****** | │ │ │ │ │ +|{ | │ │ │ │ │ +| return escape_string_impl(str.data(), int(str.size()), 10); | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -| void alert_manager::set_notify_function(std::function const& fun) | │ │ │ │ │ +| bool need_encoding(char const* str, int const len) | │ │ │ │ │ | { | │ │ │ │ │ -| std::unique_lock lock(m_mutex); | │ │ │ │ │ -| m_notify = fun; | │ │ │ │ │ -| if (!m_alerts[m_generation].empty()) | │ │ │ │ │ +| for (int i = 0; i < len; ++i) | │ │ │ │ │ | { | │ │ │ │ │ -| if (m_notify) m_notify(); | │ │ │ │ │ +| if (std::strchr(unreserved_chars, *str) == nullptr || *str == 0) | │ │ │ │ │ +| return true; | │ │ │ │ │ +| ++str; | │ │ │ │ │ | } | │ │ │ │ │ +| return false; | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_EXTENSIONS | │ │ │ │ │ -| void alert_manager::add_extension(std::shared_ptr ext) | │ │ │ │ │ +| void convert_path_to_posix(std::string& path) | │ │ │ │ │ | { | │ │ │ │ │ -| m_ses_extensions.push_back(ext); | │ │ │ │ │ +| std::replace(path.begin(), path.end(), '\\', '/'); | │ │ │ │ │ | } | │ │ │ │ │ -|#endif | │ │ │ │ │ -| | │ │ │ │ │ -| void alert_manager::get_all(std::vector& alerts) | │ │ │ │ │ -| { | │ │ │ │ │ -|_ _ _s_t_d_:_:_l_o_c_k___g_u_a_r_d_<_s_t_d_:_:_r_e_c_u_r_s_i_v_e___m_u_t_e_x_>_ _l_o_c_k_(_m___m_u_t_e_x_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -| | |technically, this is where the transaction of moving the files is completed. This is where the new save_path should be committed. If| │ │ │ │ │ -|relevance 2|_._._/_s_r_c_/_s_t_o_r_a_g_e___u_t_i_l_s_._c_p_p_:_2_9_4 |there is an error in the code below, that should not prevent the new save path to be set. Maybe it would make sense to make the | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_s_a_v_e___p_a_t_h_ _a_n_ _i_n_-_o_u_t_ _p_a_r_a_m_e_t_e_r_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tteecchhnniiccaallllyy,, tthhiiss iiss wwhheerree tthhee ttrraannssaaccttiioonn ooff mmoovviinngg tthhee ffiilleess iiss ccoommpplleetteedd.. TThhiiss iiss wwhheerree tthhee nneeww ssaavvee__ppaatthh sshhoouulldd bbee ccoommmmiitttteedd.. IIff tthheerree iiss aann eerrrroorr iinn tthhee ccooddee bbeellooww,,| │ │ │ │ │ -|tthhaatt sshhoouulldd nnoott pprreevveenntt tthhee nneeww ssaavvee ppaatthh ttoo bbee sseett.. MMaayybbee iitt wwoouulldd mmaakkee sseennssee ttoo mmaakkee tthhee ssaavvee__ppaatthh aann iinn--oouutt ppaarraammeetteerr ********** | │ │ │ │ │ -|****** ....//ssrrcc//ssttoorraaggee__uuttiillss..ccpppp::229944 ****** | │ │ │ │ │ -|while (--file_index >= file_index_t(0)) | │ │ │ │ │ -| { | │ │ │ │ │ -| // files moved out to absolute paths are not moved | │ │ │ │ │ -| if (f.file_absolute_path(file_index)) continue; | │ │ │ │ │ -| | │ │ │ │ │ -| // if we ended up copying the file, don't do anything during | │ │ │ │ │ -| // roll-back | │ │ │ │ │ -| if (copied_files[file_index]) continue; | │ │ │ │ │ -| | │ │ │ │ │ -| std::string const old_path = combine_path(save_path, f.file_path(file_index)); | │ │ │ │ │ -| std::string const new_path = combine_path(new_save_path, f.file_path(file_index)); | │ │ │ │ │ -| | │ │ │ │ │ -| // ignore errors when rolling back | │ │ │ │ │ -| storage_error ignore; | │ │ │ │ │ -| move_file(new_path, old_path, ignore); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| return { status_t::fatal_disk_error, save_path }; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| | │ │ │ │ │ -|std::set subdirs; | │ │ │ │ │ -| for (auto const i : f.file_range()) | │ │ │ │ │ -| { | │ │ │ │ │ -| // files moved out to absolute paths are not moved | │ │ │ │ │ -| if (f.file_absolute_path(i)) continue; | │ │ │ │ │ -| | │ │ │ │ │ -| if (has_parent_path(f.file_path(i))) | │ │ │ │ │ -| subdirs.insert(parent_path(f.file_path(i))); | │ │ │ │ │ -| | │ │ │ │ │ -| // if we ended up renaming the file instead of moving it, there's no | │ │ │ │ │ -| // need to delete the source. | │ │ │ │ │ -| if (copied_files[i] == false) continue; | │ │ │ │ │ -| | │ │ │ │ │ -| std::string const old_path = combine_path(save_path, f.file_path(i)); | │ │ │ │ │ -| | │ │ │ │ │ -| // we may still have some files in old save_path | │ │ │ │ │ -| // eg. if (flags == dont_replace && exists(new_path)) | │ │ │ │ │ -| // ignore errors when removing | │ │ │ │ │ -| error_code ignore; | │ │ │ │ │ -| remove(old_path, ignore); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| for (std::string const& s : subdirs) | │ │ │ │ │ -| { | │ │ │ │ │ -| error_code err; | │ │ │ │ │ -| std::string subdir = combine_path(save_path, s); | │ │ │ │ │ -| | │ │ │ │ │ -| while (!path_equal(subdir, save_path) && !err) | │ │ │ │ │ -| { | │ │ │ │ │ -|_ _ _ _ _r_e_m_o_v_e_(_s_u_b_d_i_r_,_ _e_r_r_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 2|_._._/_s_r_c_/_s_t_o_r_a_g_e___u_t_i_l_s_._c_p_p_:_4_8_6 |is this risky? The upper layer will assume we have the whole file. Perhaps we should verify that at least the size of the file is | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_c_o_r_r_e_c_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** iiss tthhiiss rriisskkyy?? TThhee uuppppeerr llaayyeerr wwiillll aassssuummee wwee hhaavvee tthhee wwhhoollee ffiillee.. PPeerrhhaappss wwee sshhoouulldd vveerriiffyy tthhaatt aatt lleeaasstt tthhee ssiizzee ooff tthhee ffiillee iiss ccoorrrreecctt ********** | │ │ │ │ │ -|****** ....//ssrrcc//ssttoorraaggee__uuttiillss..ccpppp::448866 ****** | │ │ │ │ │ -|{ | │ │ │ │ │ -| // we create directories lazily, so it's possible it hasn't | │ │ │ │ │ -| // been created yet. Create the directories now and try | │ │ │ │ │ -| // again | │ │ │ │ │ -| create_directories(parent_path(file_path), err); | │ │ │ │ │ -| | │ │ │ │ │ -| if (err) | │ │ │ │ │ -| { | │ │ │ │ │ -| ec.file(idx); | │ │ │ │ │ -| ec.operation = operation_t::mkdir; | │ │ │ │ │ -| return false; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| hard_link(s, file_path, err); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| // if the file already exists, that's not an error | │ │ │ │ │ -| if (err == boost::system::errc::file_exists) | │ │ │ │ │ -| continue; | │ │ │ │ │ | | │ │ │ │ │ -|if (err) | │ │ │ │ │ +|std::string read_until(char const*& str, char const delim, char const* end) | │ │ │ │ │ |{ | │ │ │ │ │ -| ec.ec = err; | │ │ │ │ │ -| ec.file(idx); | │ │ │ │ │ -| ec.operation = operation_t::file_hard_link; | │ │ │ │ │ -| return false; | │ │ │ │ │ -| } | │ │ │ │ │ -| added_files = true; | │ │ │ │ │ -| stat.set_dirty(idx); | │ │ │ │ │ -| } | │ │ │ │ │ -| } | │ │ │ │ │ -|#endif // TORRENT_DISABLE_MUTABLE_TORRENTS | │ │ │ │ │ -| | │ │ │ │ │ -| bool const seed = (rd.have_pieces.size() >= fs.num_pieces() | │ │ │ │ │ -| && rd.have_pieces.all_set()) | │ │ │ │ │ -| || (rd.flags & torrent_flags::seed_mode); | │ │ │ │ │ +| TORRENT_ASSERT(str <= end); | │ │ │ │ │ | | │ │ │ │ │ -| if (seed) | │ │ │ │ │ +| std::string ret; | │ │ │ │ │ +| while (str != end && *str != delim) | │ │ │ │ │ | { | │ │ │ │ │ -| for (file_index_t const file_index : fs.file_range()) | │ │ │ │ │ -| { | │ │ │ │ │ -| if (fs.pad_file_at(file_index)) continue; | │ │ │ │ │ -| | │ │ │ │ │ -| // files with priority zero may not have been saved to disk at their | │ │ │ │ │ -| // expected location, but is likely to be in a partfile. Just exempt it | │ │ │ │ │ -| // from checking | │ │ │ │ │ -| if (file_index < file_priority.end_index() | │ │ │ │ │ -| && file_priority[file_index] == dont_download | │ │ │ │ │ -| && !(rd.flags & torrent_flags::seed_mode)) | │ │ │ │ │ -|_ _ _ _ _ _c_o_n_t_i_n_u_e_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _2_|_._._/_s_r_c_/_u_p_n_p_._c_p_p_:_1_0_6_ _ _ _ _ _ _ _ _ _ _ _|_u_s_e_ _b_o_o_s_t_:_:_a_s_i_o_:_:_i_p_:_:_n_e_t_w_o_r_k_ _i_n_s_t_e_a_d_ _o_f_ _n_e_t_m_a_s_k_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** uussee bboooosstt::::aassiioo::::iipp::::nneettwwoorrkk iinnsstteeaadd ooff nneettmmaasskk ********** | │ │ │ │ │ -|****** ....//ssrrcc//uuppnnpp..ccpppp::110066 ****** | │ │ │ │ │ -|static error_code ignore_error; | │ │ │ │ │ -| | │ │ │ │ │ -|upnp::rootdevice::rootdevice() = default; | │ │ │ │ │ -| | │ │ │ │ │ -|#if TORRENT_USE_ASSERTS | │ │ │ │ │ -|upnp::rootdevice::~rootdevice() | │ │ │ │ │ -|{ | │ │ │ │ │ -| TORRENT_ASSERT(magic == 1337); | │ │ │ │ │ -| magic = 0; | │ │ │ │ │ -|} | │ │ │ │ │ -|#else | │ │ │ │ │ -|upnp::rootdevice::~rootdevice() = default; | │ │ │ │ │ -|#endif | │ │ │ │ │ +| ret += *str; | │ │ │ │ │ +| ++str; | │ │ │ │ │ +| } | │ │ │ │ │ +| // skip the delimiter as well | │ │ │ │ │ +| while (str != end && *str == delim) ++str; | │ │ │ │ │ +| return ret; | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -|upnp::rootdevice::rootdevice(rootdevice const&) = default; | │ │ │ │ │ -|upnp::rootdevice& upnp::rootdevice::operator=(rootdevice const&) & = default; | │ │ │ │ │ -|upnp::rootdevice::rootdevice(rootdevice&&) noexcept = default; | │ │ │ │ │ -|upnp::rootdevice& upnp::rootdevice::operator=(rootdevice&&) & = default; | │ │ │ │ │ +| std::string maybe_url_encode(std::string const& url) | │ │ │ │ │ +| { | │ │ │ │ │ +| std::string protocol, host, auth, path; | │ │ │ │ │ +| int port; | │ │ │ │ │ +| error_code ec; | │ │ │ │ │ +| std::tie(protocol, auth, host, port, path) = parse_url_components(url, ec); | │ │ │ │ │ +| if (ec) return url; | │ │ │ │ │ | | │ │ │ │ │ -|upnp::upnp(io_context& ios | │ │ │ │ │ -|, aux::session_settings const& settings | │ │ │ │ │ -| , aux::portmap_callback& cb | │ │ │ │ │ -| , address_v4 const listen_address | │ │ │ │ │ -| , address_v4 const netmask | │ │ │ │ │ -| , std::string listen_device | │ │ │ │ │ -| , listen_socket_handle ls) | │ │ │ │ │ -| : m_settings(settings) | │ │ │ │ │ -| , m_callback(cb) | │ │ │ │ │ -| , m_io_service(ios) | │ │ │ │ │ -| , m_resolver(ios) | │ │ │ │ │ -| , m_multicast(ios) | │ │ │ │ │ -| , m_unicast(ios) | │ │ │ │ │ -| , m_broadcast_timer(ios) | │ │ │ │ │ -| , m_refresh_timer(ios) | │ │ │ │ │ -| , m_map_timer(ios) | │ │ │ │ │ -| , m_listen_address(listen_address) | │ │ │ │ │ -| , m_netmask(netmask) | │ │ │ │ │ -| , m_device(std::move(listen_device)) | │ │ │ │ │ -|#if TORRENT_USE_SSL | │ │ │ │ │ -| , m_ssl_ctx(ssl::context::sslv23_client) | │ │ │ │ │ -|#endif | │ │ │ │ │ -| , m_listen_handle(std::move(ls)) | │ │ │ │ │ -|{ | │ │ │ │ │ -|#if TORRENT_USE_SSL | │ │ │ │ │ -| m_ssl_ctx.set_verify_mode(ssl::context::verify_none); | │ │ │ │ │ -|#endif | │ │ │ │ │ -|} | │ │ │ │ │ +| // first figure out if this url contains unencoded characters | │ │ │ │ │ +| if (!need_encoding(path.c_str(), int(path.size()))) | │ │ │ │ │ +| return url; | │ │ │ │ │ | | │ │ │ │ │ -|void upnp::start() | │ │ │ │ │ -|_{_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +| std::string msg; | │ │ │ │ │ +| std::string escaped_path { escape_path(path) }; | │ │ │ │ │ +| // reserve enough space so further append will | │ │ │ │ │ +|_ _ _/_/_ _o_n_l_y_ _c_o_p_y_ _v_a_l_u_e_s_ _t_o_ _e_x_i_s_t_i_n_g_ _l_o_c_a_t_i_o_n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ | |_._._/_s_r_c_/ | | │ │ │ │ │ |relevance 2|_h_t_t_p___t_r_a_c_k_e_r___c_o_n_n_e_c_t_i_o_n_._c_p_p_: |returning a bool here is redundant. Instead this function should return the peer_entry | │ │ │ │ │ |_ _ _ _ _ _ _ _ _ _ _ _|_4_7_9_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** rreettuurrnniinngg aa bbooooll hheerree iiss rreedduunnddaanntt.. IInnsstteeaadd tthhiiss ffuunnccttiioonn sshhoouulldd rreettuurrnn tthhee ppeeeerr__eennttrryy ********** | │ │ │ │ │ |****** ....//ssrrcc//hhttttpp__ttrraacckkeerr__ccoonnnneeccttiioonn..ccpppp::447799 ****** | │ │ │ │ │ |{ | │ │ │ │ │ | cb->tracker_scrape_response(tracker_req(), resp.complete | │ │ │ │ │ @@ -2962,177 +2630,322 @@ │ │ │ │ │ | return false; | │ │ │ │ │ | } | │ │ │ │ │ | ret.hostname = i.string_value().to_string(); | │ │ │ │ │ | | │ │ │ │ │ | // extract port | │ │ │ │ │ | i = info.dict_find_int("port"); | │ │ │ │ │ |_ _ _i_f_ _(_!_i_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 2|_._._/_s_r_c_/ |support authentication here. tracker_req().auth | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_u_d_p___t_r_a_c_k_e_r___c_o_n_n_e_c_t_i_o_n_._c_p_p_:_8_1_ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** ssuuppppoorrtt aauutthheennttiiccaattiioonn hheerree.. ttrraacckkeerr__rreeqq(())..aauutthh ********** | │ │ │ │ │ -|****** ....//ssrrcc//uuddpp__ttrraacckkeerr__ccoonnnneeccttiioonn..ccpppp::8811 ****** | │ │ │ │ │ -|udp_tracker_connection::m_connection_cache; | │ │ │ │ │ -| | │ │ │ │ │ -| std::mutex udp_tracker_connection::m_cache_mutex; | │ │ │ │ │ -| | │ │ │ │ │ -| udp_tracker_connection::udp_tracker_connection( | │ │ │ │ │ -| io_context& ios | │ │ │ │ │ -| , tracker_manager& man | │ │ │ │ │ -| , tracker_request const& req | │ │ │ │ │ -| , std::weak_ptr c) | │ │ │ │ │ -| : tracker_connection(man, req, ios, std::move(c)) | │ │ │ │ │ -| , m_transaction_id(0) | │ │ │ │ │ -| , m_attempts(0) | │ │ │ │ │ -| , m_state(action_t::error) | │ │ │ │ │ -| , m_abort(false) | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _2_|_._._/_s_r_c_/_s_e_s_s_i_o_n___i_m_p_l_._c_p_p_:_5_9_9_ _ _ _|_i_s_ _t_h_e_r_e_ _a_ _r_e_a_s_o_n_ _n_o_t_ _t_o_ _m_o_v_e_ _a_l_l_ _o_f_ _t_h_i_s_ _i_n_t_o_ _i_n_i_t_(_)_?_ _a_n_d_ _j_u_s_t_ _p_o_s_t_ _i_t_ _t_o_ _t_h_e_ _i_o___c_o_n_t_e_x_t_?_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** iiss tthheerree aa rreeaassoonn nnoott ttoo mmoovvee aallll ooff tthhiiss iinnttoo iinniitt(())?? aanndd jjuusstt ppoosstt iitt ttoo tthhee iioo__ccoonntteexxtt?? ********** | │ │ │ │ │ +|****** ....//ssrrcc//sseessssiioonn__iimmppll..ccpppp::559999 ****** | │ │ │ │ │ +|try | │ │ │ │ │ +|#endif | │ │ │ │ │ | { | │ │ │ │ │ -| update_transaction_id(); | │ │ │ │ │ +| (this->*f)(std::forward(a)...); | │ │ │ │ │ +| } | │ │ │ │ │ +|#ifndef BOOST_NO_EXCEPTIONS | │ │ │ │ │ +| catch (system_error const& e) { | │ │ │ │ │ +| alerts().emplace_alert(e.code(), e.what()); | │ │ │ │ │ +| pause(); | │ │ │ │ │ +| } catch (std::exception const& e) { | │ │ │ │ │ +| alerts().emplace_alert(error_code(), e.what()); | │ │ │ │ │ +| pause(); | │ │ │ │ │ +| } catch (...) { | │ │ │ │ │ +| alerts().emplace_alert(error_code(), "unknown error"); | │ │ │ │ │ +| pause(); | │ │ │ │ │ | } | │ │ │ │ │ +|#endif | │ │ │ │ │ | | │ │ │ │ │ -| void udp_tracker_connection::start() | │ │ │ │ │ -| { | │ │ │ │ │ -|std::string hostname; | │ │ │ │ │ -|std::string protocol; | │ │ │ │ │ -| int port; | │ │ │ │ │ +| // This function is called by the creating thread, not in the message loop's | │ │ │ │ │ +| // io_context thread. | │ │ │ │ │ +|void session_impl::start_session() | │ │ │ │ │ +|{ | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ +| session_log("start session"); | │ │ │ │ │ +|#endif | │ │ │ │ │ +| | │ │ │ │ │ +|#if TORRENT_USE_SSL | │ │ │ │ │ | error_code ec; | │ │ │ │ │ +| m_ssl_ctx.set_default_verify_paths(ec); | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ +| if (ec) session_log("SSL set_default verify_paths failed: %s", ec.message().c_str()); | │ │ │ │ │ +| ec.clear(); | │ │ │ │ │ +|#endif | │ │ │ │ │ +|_#_i_f_ _d_e_f_i_n_e_d_ _T_O_R_R_E_N_T___W_I_N_D_O_W_S_ _&_&_ _d_e_f_i_n_e_d_ _T_O_R_R_E_N_T___U_S_E___O_P_E_N_S_S_L_ _&_&_ _!_d_e_f_i_n_e_d_ _T_O_R_R_E_N_T___W_I_N_R_T_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _2_|_._._/_s_r_c_/_s_e_s_s_i_o_n___i_m_p_l_._c_p_p_:_7_6_1_ _ _ _|_t_h_e_ _i_p_ _f_i_l_t_e_r_ _s_h_o_u_l_d_ _p_r_o_b_a_b_l_y_ _b_e_ _s_a_v_e_d_ _h_e_r_e_ _t_o_o_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tthhee iipp ffiilltteerr sshhoouulldd pprroobbaabbllyy bbee ssaavveedd hheerree ttoooo ********** | │ │ │ │ │ +|****** ....//ssrrcc//sseessssiioonn__iimmppll..ccpppp::776611 ****** | │ │ │ │ │ +|m_lsd_announce_timer.async_wait([this](error_code const& e) { | │ │ │ │ │ +| wrap(&session_impl::on_lsd_announce, e); } ); | │ │ │ │ │ | | │ │ │ │ │ -| std::tie(protocol, std::ignore, hostname, port, std::ignore) | │ │ │ │ │ -| = parse_url_components(tracker_req().url, ec); | │ │ │ │ │ -| if (port == -1) port = protocol == "http" ? 80 : 443; | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ +| session_log(" done starting session"); | │ │ │ │ │ +|#endif | │ │ │ │ │ | | │ │ │ │ │ -| if (ec) | │ │ │ │ │ +| // this applies unchoke settings from m_settings | │ │ │ │ │ +| recalculate_unchoke_slots(); | │ │ │ │ │ +| | │ │ │ │ │ +| // apply all m_settings to this session | │ │ │ │ │ +| run_all_updates(*this); | │ │ │ │ │ +| reopen_listen_sockets(false); | │ │ │ │ │ +| | │ │ │ │ │ +|#if TORRENT_USE_INVARIANT_CHECKS | │ │ │ │ │ +| check_invariant(); | │ │ │ │ │ +|#endif | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +|#if TORRENT_ABI_VERSION <= 2 | │ │ │ │ │ +|void session_impl::save_state(entry* eptr, save_state_flags_t const flags) const | │ │ │ │ │ +|{ | │ │ │ │ │ +| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ +| | │ │ │ │ │ +| entry& e = *eptr; | │ │ │ │ │ +| // make it a dict | │ │ │ │ │ +| e.dict(); | │ │ │ │ │ +| | │ │ │ │ │ +| if (flags & session::save_settings) | │ │ │ │ │ | { | │ │ │ │ │ -| tracker_connection::fail(ec, operation_t::parse_address); | │ │ │ │ │ -| return; | │ │ │ │ │ +| entry::dictionary_type& sett = e["settings"].dict(); | │ │ │ │ │ +| save_settings_to_dict(non_default_settings(m_settings), sett); | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -| aux::session_settings const& settings = m_man.settings(); | │ │ │ │ │ -| | │ │ │ │ │ -| int const proxy_type = settings.get_int(settings_pack::proxy_type); | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_DHT | │ │ │ │ │ +| if (flags & session::save_dht_settings) | │ │ │ │ │ +| { | │ │ │ │ │ +| e["dht"] = dht::save_dht_settings(get_dht_settings()); | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -| if (settings.get_bool(settings_pack::proxy_hostnames) | │ │ │ │ │ -| && (proxy_type == settings_pack::socks5 | │ │ │ │ │ -| || proxy_type == settings_pack::socks5_pw)) | │ │ │ │ │ +| if (m_dht && (flags & session::save_dht_state)) | │ │ │ │ │ | { | │ │ │ │ │ -| m_hostname = hostname; | │ │ │ │ │ -| m_target.port(std::uint16_t(port)); | │ │ │ │ │ -| start_announce(); | │ │ │ │ │ +| e["dht state"] = dht::save_dht_state(m_dht->state()); | │ │ │ │ │ | } | │ │ │ │ │ -| else | │ │ │ │ │ +|#endif | │ │ │ │ │ +| | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_EXTENSIONS | │ │ │ │ │ +| for (auto const& ext : m_ses_extensions[plugins_all_idx]) | │ │ │ │ │ | { | │ │ │ │ │ -| using namespace std::placeholders; | │ │ │ │ │ -|_ _ _ _A_D_D___O_U_T_S_T_A_N_D_I_N_G___A_S_Y_N_C_(_"_u_d_p___t_r_a_c_k_e_r___c_o_n_n_e_c_t_i_o_n_:_:_n_a_m_e___l_o_o_k_u_p_"_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _2_|_._._/_s_r_c_/_a_l_e_r_t_._c_p_p_:_2_0_2_1_ _ _ _ _ _ _ _ _ _|_t_h_e_ _s_a_l_t_ _h_e_r_e_ _i_s_ _a_l_l_o_c_a_t_e_d_ _o_n_ _t_h_e_ _h_e_a_p_._ _I_t_ _w_o_u_l_d_ _b_e_ _n_i_c_e_ _t_o_ _a_l_l_o_c_a_t_e_ _i_n_ _t_h_e_ _s_t_a_c_k___a_l_l_o_c_a_t_o_r_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tthhee ssaalltt hheerree iiss aallllooccaatteedd oonn tthhee hheeaapp.. IItt wwoouulldd bbee nniiccee ttoo aallllooccaattee iinn tthhee ssttaacckk__aallllooccaattoorr ********** | │ │ │ │ │ -|****** ....//ssrrcc//aalleerrtt..ccpppp::22002211 ****** | │ │ │ │ │ -|} | │ │ │ │ │ +| ext->save_state(*eptr); | │ │ │ │ │ +|_ _ _}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 2|_._._/_s_r_c_/_s_e_s_s_i_o_n___i_m_p_l_._c_p_p_:_3_8_8_0 |make a list for torrents that want to be announced on the DHT so we don't have to loop over all torrents, just to find the ones that| │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_w_a_n_t_ _t_o_ _a_n_n_o_u_n_c_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** mmaakkee aa lliisstt ffoorr ttoorrrreennttss tthhaatt wwaanntt ttoo bbee aannnnoouunncceedd oonn tthhee DDHHTT ssoo wwee ddoonn''tt hhaavvee ttoo lloooopp oovveerr aallll ttoorrrreennttss,, jjuusstt ttoo ffiinndd tthhee oonneess tthhaatt wwaanntt ttoo aannnnoouunnccee ********** | │ │ │ │ │ +|****** ....//ssrrcc//sseessssiioonn__iimmppll..ccpppp::33888800 ****** | │ │ │ │ │ +|if (!m_dht_torrents.empty()) | │ │ │ │ │ +| { | │ │ │ │ │ +| std::shared_ptr t; | │ │ │ │ │ +| do | │ │ │ │ │ +| { | │ │ │ │ │ +| t = m_dht_torrents.front().lock(); | │ │ │ │ │ +| m_dht_torrents.pop_front(); | │ │ │ │ │ +| } while (!t && !m_dht_torrents.empty()); | │ │ │ │ │ | | │ │ │ │ │ -| dht_immutable_item_alert::dht_immutable_item_alert(aux::stack_allocator& | │ │ │ │ │ -| , sha1_hash const& t, entry i) | │ │ │ │ │ -| : target(t), item(std::move(i)) | │ │ │ │ │ -| {} | │ │ │ │ │ +| if (t) | │ │ │ │ │ +| { | │ │ │ │ │ +| t->dht_announce(); | │ │ │ │ │ +| return; | │ │ │ │ │ +| } | │ │ │ │ │ +| } | │ │ │ │ │ +| if (m_torrents.empty()) return; | │ │ │ │ │ | | │ │ │ │ │ -| std::string dht_immutable_item_alert::message() const | │ │ │ │ │ +| if (m_next_dht_torrent >= m_torrents.size()) | │ │ │ │ │ +| m_next_dht_torrent = 0; | │ │ │ │ │ +| m_torrents[m_next_dht_torrent]->dht_announce(); | │ │ │ │ │ +|++m_next_dht_torrent; | │ │ │ │ │ +|if (m_next_dht_torrent >= m_torrents.size()) | │ │ │ │ │ +| m_next_dht_torrent = 0; | │ │ │ │ │ +| } | │ │ │ │ │ +|#endif | │ │ │ │ │ +| | │ │ │ │ │ +| void session_impl::on_lsd_announce(error_code const& e) | │ │ │ │ │ | { | │ │ │ │ │ -|#ifdef TORRENT_DISABLE_ALERT_MSG | │ │ │ │ │ -| return {}; | │ │ │ │ │ -|#else | │ │ │ │ │ -| char msg[1050]; | │ │ │ │ │ -| std::snprintf(msg, sizeof(msg), "DHT immutable item %s [ %s ]" | │ │ │ │ │ -| , aux::to_hex(target).c_str() | │ │ │ │ │ -| , item.to_string().c_str()); | │ │ │ │ │ -| return msg; | │ │ │ │ │ +| COMPLETE_ASYNC("session_impl::on_lsd_announce"); | │ │ │ │ │ +| m_stats_counters.inc_stats_counter(counters::on_lsd_counter); | │ │ │ │ │ +| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ +| if (e) return; | │ │ │ │ │ +| | │ │ │ │ │ +| if (m_abort) return; | │ │ │ │ │ +| | │ │ │ │ │ +| ADD_OUTSTANDING_ASYNC("session_impl::on_lsd_announce"); | │ │ │ │ │ +| // announce on local network every 5 minutes | │ │ │ │ │ +| int const delay = std::max(m_settings.get_int(settings_pack::local_service_announce_interval) | │ │ │ │ │ +| / std::max(int(m_torrents.size()), 1), 1); | │ │ │ │ │ +| m_lsd_announce_timer.expires_after(seconds(delay)); | │ │ │ │ │ +| m_lsd_announce_timer.async_wait([this](error_code const& err) { | │ │ │ │ │ +| wrap(&session_impl::on_lsd_announce, err); }); | │ │ │ │ │ +| | │ │ │ │ │ +| if (m_torrents.empty()) return; | │ │ │ │ │ +| | │ │ │ │ │ +| if (m_next_lsd_torrent >= m_torrents.size()) | │ │ │ │ │ +| m_next_lsd_torrent = 0; | │ │ │ │ │ +| m_torrents[m_next_lsd_torrent]->lsd_announce(); | │ │ │ │ │ +| ++m_next_lsd_torrent; | │ │ │ │ │ +| if (m_next_lsd_torrent >= m_torrents.size()) | │ │ │ │ │ +|_ _ _ _m___n_e_x_t___l_s_d___t_o_r_r_e_n_t_ _=_ _0_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _2_|_._._/_s_r_c_/_s_e_s_s_i_o_n___i_m_p_l_._c_p_p_:_5_5_1_3_ _ _|_t_h_i_s_ _f_u_n_c_t_i_o_n_ _s_h_o_u_l_d_ _b_e_ _r_e_m_o_v_e_d_ _a_n_d_ _u_s_e_r_s_ _n_e_e_d_ _t_o_ _d_e_a_l_ _w_i_t_h_ _t_h_e_ _m_o_r_e_ _g_e_n_e_r_i_c_ _c_a_s_e_ _o_f_ _h_a_v_i_n_g_ _m_u_l_t_i_p_l_e_ _l_i_s_t_e_n_ _p_o_r_t_s_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tthhiiss ffuunnccttiioonn sshhoouulldd bbee rreemmoovveedd aanndd uusseerrss nneeeedd ttoo ddeeaall wwiitthh tthhee mmoorree ggeenneerriicc ccaassee ooff hhaavviinngg mmuullttiippllee lliisstteenn ppoorrttss ********** | │ │ │ │ │ +|****** ....//ssrrcc//sseessssiioonn__iimmppll..ccpppp::55551133 ****** | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ +| if (!node_list.empty() && nodes.empty()) | │ │ │ │ │ +| { | │ │ │ │ │ +| session_log("ERROR: failed to parse DHT bootstrap list: %s", node_list.c_str()); | │ │ │ │ │ +| } | │ │ │ │ │ +|#endif | │ │ │ │ │ +| for (auto const& n : nodes) | │ │ │ │ │ +| add_dht_router(n); | │ │ │ │ │ |#endif | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -|dht_mutable_item_alert::dht_mutable_item_alert(aux::stack_allocator& | │ │ │ │ │ -|, std::array const& k | │ │ │ │ │ -| , std::array const& sig | │ │ │ │ │ -| , std::int64_t sequence | │ │ │ │ │ -| , string_view s | │ │ │ │ │ -| , entry i | │ │ │ │ │ -| , bool a) | │ │ │ │ │ -| : key(k), signature(sig), seq(sequence), salt(s), item(std::move(i)), authoritative(a) | │ │ │ │ │ -| {} | │ │ │ │ │ +| void session_impl::update_count_slow() | │ │ │ │ │ +| { | │ │ │ │ │ +| error_code ec; | │ │ │ │ │ +| for (auto const& tp : m_torrents) | │ │ │ │ │ +| { | │ │ │ │ │ +| tp->on_inactivity_tick(ec); | │ │ │ │ │ +| } | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -| std::string dht_mutable_item_alert::message() const | │ │ │ │ │ +|std::uint16_t session_impl::listen_port() const | │ │ │ │ │ +|{ | │ │ │ │ │ +| return listen_port(nullptr); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| std::uint16_t session_impl::listen_port(listen_socket_t* sock) const | │ │ │ │ │ | { | │ │ │ │ │ -|#ifdef TORRENT_DISABLE_ALERT_MSG | │ │ │ │ │ -| return {}; | │ │ │ │ │ +| if (m_listen_sockets.empty()) return 0; | │ │ │ │ │ +| if (sock) | │ │ │ │ │ +| { | │ │ │ │ │ +| // if we're using a proxy, we won't be able to accept any TCP | │ │ │ │ │ +| // connections. Not even uTP connections via the port we know about. | │ │ │ │ │ +| // The DHT may use the implied port to make it work, but the port we | │ │ │ │ │ +| // announce here has no relevance for that. | │ │ │ │ │ +| if (sock->flags & listen_socket_t::proxy) | │ │ │ │ │ +| return 0; | │ │ │ │ │ +| | │ │ │ │ │ +| if (!(sock->flags & listen_socket_t::accept_incoming)) | │ │ │ │ │ +| return 0; | │ │ │ │ │ +| | │ │ │ │ │ +| return std::uint16_t(sock->tcp_external_port()); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +|#ifdef TORRENT_SSL_PEERS | │ │ │ │ │ +| for (auto const& s : m_listen_sockets) | │ │ │ │ │ +| { | │ │ │ │ │ +| if (!(s->flags & listen_socket_t::accept_incoming)) continue; | │ │ │ │ │ +| if (s->ssl == transport::plaintext) | │ │ │ │ │ +| return std::uint16_t(s->tcp_external_port()); | │ │ │ │ │ +| } | │ │ │ │ │ +|_ _ _r_e_t_u_r_n_ _0_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _2_|_._._/_s_r_c_/_s_e_s_s_i_o_n___i_m_p_l_._c_p_p_:_5_5_5_3_ _ _|_t_h_i_s_ _f_u_n_c_t_i_o_n_ _s_h_o_u_l_d_ _b_e_ _r_e_m_o_v_e_d_ _a_n_d_ _u_s_e_r_s_ _n_e_e_d_ _t_o_ _d_e_a_l_ _w_i_t_h_ _t_h_e_ _m_o_r_e_ _g_e_n_e_r_i_c_ _c_a_s_e_ _o_f_ _h_a_v_i_n_g_ _m_u_l_t_i_p_l_e_ _s_s_l_ _p_o_r_t_s_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tthhiiss ffuunnccttiioonn sshhoouulldd bbee rreemmoovveedd aanndd uusseerrss nneeeedd ttoo ddeeaall wwiitthh tthhee mmoorree ggeenneerriicc ccaassee ooff hhaavviinngg mmuullttiippllee ssssll ppoorrttss ********** | │ │ │ │ │ +|****** ....//ssrrcc//sseessssiioonn__iimmppll..ccpppp::55555533 ****** | │ │ │ │ │ +|return 0; | │ │ │ │ │ +| | │ │ │ │ │ +| return std::uint16_t(sock->tcp_external_port()); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +|#ifdef TORRENT_SSL_PEERS | │ │ │ │ │ +| for (auto const& s : m_listen_sockets) | │ │ │ │ │ +| { | │ │ │ │ │ +| if (!(s->flags & listen_socket_t::accept_incoming)) continue; | │ │ │ │ │ +| if (s->ssl == transport::plaintext) | │ │ │ │ │ +| return std::uint16_t(s->tcp_external_port()); | │ │ │ │ │ +| } | │ │ │ │ │ +| return 0; | │ │ │ │ │ |#else | │ │ │ │ │ -| char msg[1050]; | │ │ │ │ │ -| std::snprintf(msg, sizeof(msg), "DHT mutable item (key=%s salt=%s seq=%" PRId64 " %s) [ %s ]" | │ │ │ │ │ -| , aux::to_hex(key).c_str() | │ │ │ │ │ -| , salt.c_str() | │ │ │ │ │ -| , seq | │ │ │ │ │ -| , authoritative ? "auth" : "non-auth" | │ │ │ │ │ -| , item.to_string().c_str()); | │ │ │ │ │ -| return msg; | │ │ │ │ │ +| sock = m_listen_sockets.front().get(); | │ │ │ │ │ +| if (!(sock->flags & listen_socket_t::accept_incoming)) return 0; | │ │ │ │ │ +| return std::uint16_t(sock->tcp_external_port()); | │ │ │ │ │ |#endif | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -| dht_put_alert::dht_put_alert(aux::stack_allocator&, sha1_hash const& t, int n) | │ │ │ │ │ -| : target(t) | │ │ │ │ │ -| , public_key() | │ │ │ │ │ -| , signature() | │ │ │ │ │ -|_ _ _,_ _s_a_l_t_(_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _2_|_._._/_s_r_c_/_e_s_c_a_p_e___s_t_r_i_n_g_._c_p_p_:_1_9_4_ _ _|_t_h_i_s_ _s_h_o_u_l_d_ _p_r_o_b_a_b_l_y_ _b_e_ _m_o_v_e_d_ _i_n_t_o_ _s_t_r_i_n_g___u_t_i_l_._c_p_p_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tthhiiss sshhoouulldd pprroobbaabbllyy bbee mmoovveedd iinnttoo ssttrriinngg__uuttiill..ccpppp ********** | │ │ │ │ │ -|****** ....//ssrrcc//eessccaappee__ssttrriinngg..ccpppp::119944 ****** | │ │ │ │ │ +|std::uint16_t session_impl::ssl_listen_port() const | │ │ │ │ │ |{ | │ │ │ │ │ -| return escape_string_impl(str.data(), int(str.size()), 10); | │ │ │ │ │ +| return ssl_listen_port(nullptr); | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -| bool need_encoding(char const* str, int const len) | │ │ │ │ │ +| std::uint16_t session_impl::ssl_listen_port(listen_socket_t* sock) const | │ │ │ │ │ | { | │ │ │ │ │ -| for (int i = 0; i < len; ++i) | │ │ │ │ │ +|#ifdef TORRENT_SSL_PEERS | │ │ │ │ │ +| if (sock) | │ │ │ │ │ | { | │ │ │ │ │ -| if (std::strchr(unreserved_chars, *str) == nullptr || *str == 0) | │ │ │ │ │ -| return true; | │ │ │ │ │ -| ++str; | │ │ │ │ │ +| if (!(sock->flags & listen_socket_t::accept_incoming)) return 0; | │ │ │ │ │ +| return std::uint16_t(sock->tcp_external_port()); | │ │ │ │ │ | } | │ │ │ │ │ -| return false; | │ │ │ │ │ +| | │ │ │ │ │ +| if (m_settings.get_int(settings_pack::proxy_type) != settings_pack::none | │ │ │ │ │ +| && m_settings.get_bool(settings_pack::proxy_peer_connections)) | │ │ │ │ │ +| return 0; | │ │ │ │ │ +| | │ │ │ │ │ +| for (auto const& s : m_listen_sockets) | │ │ │ │ │ +| { | │ │ │ │ │ +| if (!(s->flags & listen_socket_t::accept_incoming)) continue; | │ │ │ │ │ +| if (s->ssl == transport::ssl) | │ │ │ │ │ +| return std::uint16_t(s->tcp_external_port()); | │ │ │ │ │ +| } | │ │ │ │ │ +|#else | │ │ │ │ │ +| TORRENT_UNUSED(sock); | │ │ │ │ │ +|#endif | │ │ │ │ │ +| return 0; | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -| void convert_path_to_posix(std::string& path) | │ │ │ │ │ -| { | │ │ │ │ │ -| std::replace(path.begin(), path.end(), '\\', '/'); | │ │ │ │ │ +|_ _i_n_t_ _s_e_s_s_i_o_n___i_m_p_l_:_:_g_e_t___l_i_s_t_e_n___p_o_r_t_(_t_r_a_n_s_p_o_r_t_ _c_o_n_s_t_ _s_s_l_,_ _a_u_x_:_:_l_i_s_t_e_n___s_o_c_k_e_t___h_a_n_d_l_e_ _c_o_n_s_t_&_ _s_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _2_|_._._/_s_r_c_/_s_e_s_s_i_o_n___i_m_p_l_._c_p_p_:_6_3_8_8_ _ _|_t_h_i_s_ _s_h_o_u_l_d_ _b_e_ _f_a_c_t_o_r_e_d_ _i_n_t_o_ _t_h_e_ _u_d_p_ _s_o_c_k_e_t_,_ _s_o_ _w_e_ _o_n_l_y_ _h_a_v_e_ _t_h_e_ _c_o_d_e_ _o_n_c_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tthhiiss sshhoouulldd bbee ffaaccttoorreedd iinnttoo tthhee uuddpp ssoocckkeett,, ssoo wwee oonnllyy hhaavvee tthhee ccooddee oonnccee ********** | │ │ │ │ │ +|****** ....//ssrrcc//sseessssiioonn__iimmppll..ccpppp::66338888 ****** | │ │ │ │ │ +|return upload_rate_limit(m_local_peer_class); | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -|std::string read_until(char const*& str, char const delim, char const* end) | │ │ │ │ │ -|{ | │ │ │ │ │ -| TORRENT_ASSERT(str <= end); | │ │ │ │ │ +| int session_impl::local_download_rate_limit() const | │ │ │ │ │ +| { | │ │ │ │ │ +| return download_rate_limit(m_local_peer_class); | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -| std::string ret; | │ │ │ │ │ -| while (str != end && *str != delim) | │ │ │ │ │ -| { | │ │ │ │ │ -| ret += *str; | │ │ │ │ │ -| ++str; | │ │ │ │ │ -| } | │ │ │ │ │ -| // skip the delimiter as well | │ │ │ │ │ -| while (str != end && *str == delim) ++str; | │ │ │ │ │ -| return ret; | │ │ │ │ │ +| int session_impl::upload_rate_limit_depr() const | │ │ │ │ │ +| { | │ │ │ │ │ +| return upload_rate_limit(m_global_class); | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -| std::string maybe_url_encode(std::string const& url) | │ │ │ │ │ +| int session_impl::download_rate_limit_depr() const | │ │ │ │ │ | { | │ │ │ │ │ -| std::string protocol, host, auth, path; | │ │ │ │ │ -| int port; | │ │ │ │ │ -| error_code ec; | │ │ │ │ │ -| std::tie(protocol, auth, host, port, path) = parse_url_components(url, ec); | │ │ │ │ │ -| if (ec) return url; | │ │ │ │ │ +| return download_rate_limit(m_global_class); | │ │ │ │ │ +| } | │ │ │ │ │ +|#endif // DEPRECATE | │ │ │ │ │ | | │ │ │ │ │ -| // first figure out if this url contains unencoded characters | │ │ │ │ │ -| if (!need_encoding(path.c_str(), int(path.size()))) | │ │ │ │ │ -| return url; | │ │ │ │ │ | | │ │ │ │ │ -| std::string msg; | │ │ │ │ │ -| std::string escaped_path { escape_path(path) }; | │ │ │ │ │ -| // reserve enough space so further append will | │ │ │ │ │ -|_ _ _/_/_ _o_n_l_y_ _c_o_p_y_ _v_a_l_u_e_s_ _t_o_ _e_x_i_s_t_i_n_g_ _l_o_c_a_t_i_o_n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|void session_impl::update_peer_dscp() | │ │ │ │ │ +|{ | │ │ │ │ │ +| int const value = m_settings.get_int(settings_pack::peer_dscp); | │ │ │ │ │ +| for (auto const& l : m_listen_sockets) | │ │ │ │ │ +| { | │ │ │ │ │ +| if (l->sock) | │ │ │ │ │ +| { | │ │ │ │ │ +| error_code ec; | │ │ │ │ │ +| set_traffic_class(*l->sock, value, ec); | │ │ │ │ │ +| | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ +| if (should_log()) | │ │ │ │ │ +| { | │ │ │ │ │ +| session_log(">>> SET_DSCP [ tcp (%s %d) value: %x e: %s ]" | │ │ │ │ │ +| , l->sock->local_endpoint().address().to_string().c_str() | │ │ │ │ │ +| , l->sock->local_endpoint().port(), value, ec.message().c_str()); | │ │ │ │ │ +| } | │ │ │ │ │ +|#endif | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| if (l->udp_sock) | │ │ │ │ │ +| { | │ │ │ │ │ +| error_code ec; | │ │ │ │ │ +| set_traffic_class(l->udp_sock->sock, value, ec); | │ │ │ │ │ +| | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ +| if (should_log()) | │ │ │ │ │ +| { | │ │ │ │ │ +| session_log(">>> SET_DSCP [ udp (%s %d) value: %x e: %s ]" | │ │ │ │ │ +| , l->udp_sock->sock.local_endpoint().address().to_string().c_str() | │ │ │ │ │ +|_ _ _ _ _ _ _,_ _l_-_>_u_d_p___s_o_c_k_-_>_s_o_c_k_._l_o_c_a_l___p_o_r_t_(_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |_r_e_l_e_v_a_n_c_e_ _2_|_._._/_s_r_c_/_t_o_r_r_e_n_t_._c_p_p_:_5_0_3_ _ _ _ _ _ _ _ _|_p_o_s_t_ _a_l_e_r_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** ppoosstt aalleerrtt ********** | │ │ │ │ │ |****** ....//ssrrcc//ttoorrrreenntt..ccpppp::550033 ****** | │ │ │ │ │ |if (m_current_gauge_state != no_gauge_state) | │ │ │ │ │ | inc_stats_counter(m_current_gauge_state + counters::num_checking_torrents, -1); | │ │ │ │ │ | if (new_gauge_state != no_gauge_state) | │ │ │ │ │ | inc_stats_counter(new_gauge_state + counters::num_checking_torrents, 1); | │ │ │ │ │ @@ -3395,322 +3208,123 @@ │ │ │ │ │ | , m_max_connections); | │ │ │ │ │ | } | │ │ │ │ │ |#endif | │ │ │ │ │ | p->disconnect(errors::too_many_connections, operation_t::bittorrent); | │ │ │ │ │ | // we have to do this here because from the peer's point of view | │ │ │ │ │ | // it wasn't really attached to the torrent, but we do need | │ │ │ │ │ |_ _ _ _ _/_/_ _t_o_ _l_e_t_ _p_e_e_r___l_i_s_t_ _k_n_o_w_ _w_e_'_r_e_ _r_e_m_o_v_i_n_g_ _i_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _2_|_._._/_s_r_c_/_s_e_s_s_i_o_n___i_m_p_l_._c_p_p_:_5_9_9_ _ _ _|_i_s_ _t_h_e_r_e_ _a_ _r_e_a_s_o_n_ _n_o_t_ _t_o_ _m_o_v_e_ _a_l_l_ _o_f_ _t_h_i_s_ _i_n_t_o_ _i_n_i_t_(_)_?_ _a_n_d_ _j_u_s_t_ _p_o_s_t_ _i_t_ _t_o_ _t_h_e_ _i_o___c_o_n_t_e_x_t_?_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** iiss tthheerree aa rreeaassoonn nnoott ttoo mmoovvee aallll ooff tthhiiss iinnttoo iinniitt(())?? aanndd jjuusstt ppoosstt iitt ttoo tthhee iioo__ccoonntteexxtt?? ********** | │ │ │ │ │ -|****** ....//ssrrcc//sseessssiioonn__iimmppll..ccpppp::559999 ****** | │ │ │ │ │ -|try | │ │ │ │ │ -|#endif | │ │ │ │ │ -| { | │ │ │ │ │ -| (this->*f)(std::forward(a)...); | │ │ │ │ │ -| } | │ │ │ │ │ -|#ifndef BOOST_NO_EXCEPTIONS | │ │ │ │ │ -| catch (system_error const& e) { | │ │ │ │ │ -| alerts().emplace_alert(e.code(), e.what()); | │ │ │ │ │ -| pause(); | │ │ │ │ │ -| } catch (std::exception const& e) { | │ │ │ │ │ -| alerts().emplace_alert(error_code(), e.what()); | │ │ │ │ │ -| pause(); | │ │ │ │ │ -| } catch (...) { | │ │ │ │ │ -| alerts().emplace_alert(error_code(), "unknown error"); | │ │ │ │ │ -| pause(); | │ │ │ │ │ -| } | │ │ │ │ │ -|#endif | │ │ │ │ │ -| | │ │ │ │ │ -| // This function is called by the creating thread, not in the message loop's | │ │ │ │ │ -| // io_context thread. | │ │ │ │ │ -|void session_impl::start_session() | │ │ │ │ │ -|{ | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ -| session_log("start session"); | │ │ │ │ │ -|#endif | │ │ │ │ │ -| | │ │ │ │ │ -|#if TORRENT_USE_SSL | │ │ │ │ │ -| error_code ec; | │ │ │ │ │ -| m_ssl_ctx.set_default_verify_paths(ec); | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ -| if (ec) session_log("SSL set_default verify_paths failed: %s", ec.message().c_str()); | │ │ │ │ │ -| ec.clear(); | │ │ │ │ │ -|#endif | │ │ │ │ │ -|_#_i_f_ _d_e_f_i_n_e_d_ _T_O_R_R_E_N_T___W_I_N_D_O_W_S_ _&_&_ _d_e_f_i_n_e_d_ _T_O_R_R_E_N_T___U_S_E___O_P_E_N_S_S_L_ _&_&_ _!_d_e_f_i_n_e_d_ _T_O_R_R_E_N_T___W_I_N_R_T_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _2_|_._._/_s_r_c_/_s_e_s_s_i_o_n___i_m_p_l_._c_p_p_:_7_6_1_ _ _ _|_t_h_e_ _i_p_ _f_i_l_t_e_r_ _s_h_o_u_l_d_ _p_r_o_b_a_b_l_y_ _b_e_ _s_a_v_e_d_ _h_e_r_e_ _t_o_o_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tthhee iipp ffiilltteerr sshhoouulldd pprroobbaabbllyy bbee ssaavveedd hheerree ttoooo ********** | │ │ │ │ │ -|****** ....//ssrrcc//sseessssiioonn__iimmppll..ccpppp::776611 ****** | │ │ │ │ │ -|m_lsd_announce_timer.async_wait([this](error_code const& e) { | │ │ │ │ │ -| wrap(&session_impl::on_lsd_announce, e); } ); | │ │ │ │ │ -| | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ -| session_log(" done starting session"); | │ │ │ │ │ -|#endif | │ │ │ │ │ -| | │ │ │ │ │ -| // this applies unchoke settings from m_settings | │ │ │ │ │ -| recalculate_unchoke_slots(); | │ │ │ │ │ -| | │ │ │ │ │ -| // apply all m_settings to this session | │ │ │ │ │ -| run_all_updates(*this); | │ │ │ │ │ -| reopen_listen_sockets(false); | │ │ │ │ │ -| | │ │ │ │ │ -|#if TORRENT_USE_INVARIANT_CHECKS | │ │ │ │ │ -| check_invariant(); | │ │ │ │ │ -|#endif | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -|#if TORRENT_ABI_VERSION <= 2 | │ │ │ │ │ -|void session_impl::save_state(entry* eptr, save_state_flags_t const flags) const | │ │ │ │ │ -|{ | │ │ │ │ │ -| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ -| | │ │ │ │ │ -| entry& e = *eptr; | │ │ │ │ │ -| // make it a dict | │ │ │ │ │ -| e.dict(); | │ │ │ │ │ -| | │ │ │ │ │ -| if (flags & session::save_settings) | │ │ │ │ │ -| { | │ │ │ │ │ -| entry::dictionary_type& sett = e["settings"].dict(); | │ │ │ │ │ -| save_settings_to_dict(non_default_settings(m_settings), sett); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_DHT | │ │ │ │ │ -| if (flags & session::save_dht_settings) | │ │ │ │ │ -| { | │ │ │ │ │ -| e["dht"] = dht::save_dht_settings(get_dht_settings()); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| if (m_dht && (flags & session::save_dht_state)) | │ │ │ │ │ -| { | │ │ │ │ │ -| e["dht state"] = dht::save_dht_state(m_dht->state()); | │ │ │ │ │ -| } | │ │ │ │ │ -|#endif | │ │ │ │ │ -| | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_EXTENSIONS | │ │ │ │ │ -| for (auto const& ext : m_ses_extensions[plugins_all_idx]) | │ │ │ │ │ -| { | │ │ │ │ │ -| ext->save_state(*eptr); | │ │ │ │ │ -|_ _ _}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 2|_._._/_s_r_c_/_s_e_s_s_i_o_n___i_m_p_l_._c_p_p_:_3_8_8_0 |make a list for torrents that want to be announced on the DHT so we don't have to loop over all torrents, just to find the ones that| │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_w_a_n_t_ _t_o_ _a_n_n_o_u_n_c_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** mmaakkee aa lliisstt ffoorr ttoorrrreennttss tthhaatt wwaanntt ttoo bbee aannnnoouunncceedd oonn tthhee DDHHTT ssoo wwee ddoonn''tt hhaavvee ttoo lloooopp oovveerr aallll ttoorrrreennttss,, jjuusstt ttoo ffiinndd tthhee oonneess tthhaatt wwaanntt ttoo aannnnoouunnccee ********** | │ │ │ │ │ -|****** ....//ssrrcc//sseessssiioonn__iimmppll..ccpppp::33888800 ****** | │ │ │ │ │ -|if (!m_dht_torrents.empty()) | │ │ │ │ │ -| { | │ │ │ │ │ -| std::shared_ptr t; | │ │ │ │ │ -| do | │ │ │ │ │ -| { | │ │ │ │ │ -| t = m_dht_torrents.front().lock(); | │ │ │ │ │ -| m_dht_torrents.pop_front(); | │ │ │ │ │ -| } while (!t && !m_dht_torrents.empty()); | │ │ │ │ │ -| | │ │ │ │ │ -| if (t) | │ │ │ │ │ -| { | │ │ │ │ │ -| t->dht_announce(); | │ │ │ │ │ -| return; | │ │ │ │ │ -| } | │ │ │ │ │ -| } | │ │ │ │ │ -| if (m_torrents.empty()) return; | │ │ │ │ │ +|relevance 2|_._._/_s_r_c_/ |support authentication here. tracker_req().auth | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_u_d_p___t_r_a_c_k_e_r___c_o_n_n_e_c_t_i_o_n_._c_p_p_:_8_1_ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** ssuuppppoorrtt aauutthheennttiiccaattiioonn hheerree.. ttrraacckkeerr__rreeqq(())..aauutthh ********** | │ │ │ │ │ +|****** ....//ssrrcc//uuddpp__ttrraacckkeerr__ccoonnnneeccttiioonn..ccpppp::8811 ****** | │ │ │ │ │ +|udp_tracker_connection::m_connection_cache; | │ │ │ │ │ | | │ │ │ │ │ -| if (m_next_dht_torrent >= m_torrents.size()) | │ │ │ │ │ -| m_next_dht_torrent = 0; | │ │ │ │ │ -| m_torrents[m_next_dht_torrent]->dht_announce(); | │ │ │ │ │ -|++m_next_dht_torrent; | │ │ │ │ │ -|if (m_next_dht_torrent >= m_torrents.size()) | │ │ │ │ │ -| m_next_dht_torrent = 0; | │ │ │ │ │ -| } | │ │ │ │ │ -|#endif | │ │ │ │ │ +| std::mutex udp_tracker_connection::m_cache_mutex; | │ │ │ │ │ | | │ │ │ │ │ -| void session_impl::on_lsd_announce(error_code const& e) | │ │ │ │ │ +| udp_tracker_connection::udp_tracker_connection( | │ │ │ │ │ +| io_context& ios | │ │ │ │ │ +| , tracker_manager& man | │ │ │ │ │ +| , tracker_request const& req | │ │ │ │ │ +| , std::weak_ptr c) | │ │ │ │ │ +| : tracker_connection(man, req, ios, std::move(c)) | │ │ │ │ │ +| , m_transaction_id(0) | │ │ │ │ │ +| , m_attempts(0) | │ │ │ │ │ +| , m_state(action_t::error) | │ │ │ │ │ +| , m_abort(false) | │ │ │ │ │ | { | │ │ │ │ │ -| COMPLETE_ASYNC("session_impl::on_lsd_announce"); | │ │ │ │ │ -| m_stats_counters.inc_stats_counter(counters::on_lsd_counter); | │ │ │ │ │ -| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ -| if (e) return; | │ │ │ │ │ -| | │ │ │ │ │ -| if (m_abort) return; | │ │ │ │ │ -| | │ │ │ │ │ -| ADD_OUTSTANDING_ASYNC("session_impl::on_lsd_announce"); | │ │ │ │ │ -| // announce on local network every 5 minutes | │ │ │ │ │ -| int const delay = std::max(m_settings.get_int(settings_pack::local_service_announce_interval) | │ │ │ │ │ -| / std::max(int(m_torrents.size()), 1), 1); | │ │ │ │ │ -| m_lsd_announce_timer.expires_after(seconds(delay)); | │ │ │ │ │ -| m_lsd_announce_timer.async_wait([this](error_code const& err) { | │ │ │ │ │ -| wrap(&session_impl::on_lsd_announce, err); }); | │ │ │ │ │ -| | │ │ │ │ │ -| if (m_torrents.empty()) return; | │ │ │ │ │ -| | │ │ │ │ │ -| if (m_next_lsd_torrent >= m_torrents.size()) | │ │ │ │ │ -| m_next_lsd_torrent = 0; | │ │ │ │ │ -| m_torrents[m_next_lsd_torrent]->lsd_announce(); | │ │ │ │ │ -| ++m_next_lsd_torrent; | │ │ │ │ │ -| if (m_next_lsd_torrent >= m_torrents.size()) | │ │ │ │ │ -|_ _ _ _m___n_e_x_t___l_s_d___t_o_r_r_e_n_t_ _=_ _0_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _2_|_._._/_s_r_c_/_s_e_s_s_i_o_n___i_m_p_l_._c_p_p_:_5_5_1_3_ _ _|_t_h_i_s_ _f_u_n_c_t_i_o_n_ _s_h_o_u_l_d_ _b_e_ _r_e_m_o_v_e_d_ _a_n_d_ _u_s_e_r_s_ _n_e_e_d_ _t_o_ _d_e_a_l_ _w_i_t_h_ _t_h_e_ _m_o_r_e_ _g_e_n_e_r_i_c_ _c_a_s_e_ _o_f_ _h_a_v_i_n_g_ _m_u_l_t_i_p_l_e_ _l_i_s_t_e_n_ _p_o_r_t_s_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tthhiiss ffuunnccttiioonn sshhoouulldd bbee rreemmoovveedd aanndd uusseerrss nneeeedd ttoo ddeeaall wwiitthh tthhee mmoorree ggeenneerriicc ccaassee ooff hhaavviinngg mmuullttiippllee lliisstteenn ppoorrttss ********** | │ │ │ │ │ -|****** ....//ssrrcc//sseessssiioonn__iimmppll..ccpppp::55551133 ****** | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ -| if (!node_list.empty() && nodes.empty()) | │ │ │ │ │ -| { | │ │ │ │ │ -| session_log("ERROR: failed to parse DHT bootstrap list: %s", node_list.c_str()); | │ │ │ │ │ -| } | │ │ │ │ │ -|#endif | │ │ │ │ │ -| for (auto const& n : nodes) | │ │ │ │ │ -| add_dht_router(n); | │ │ │ │ │ -|#endif | │ │ │ │ │ +| update_transaction_id(); | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -| void session_impl::update_count_slow() | │ │ │ │ │ +| void udp_tracker_connection::start() | │ │ │ │ │ | { | │ │ │ │ │ +|std::string hostname; | │ │ │ │ │ +|std::string protocol; | │ │ │ │ │ +| int port; | │ │ │ │ │ | error_code ec; | │ │ │ │ │ -| for (auto const& tp : m_torrents) | │ │ │ │ │ -| { | │ │ │ │ │ -| tp->on_inactivity_tick(ec); | │ │ │ │ │ -| } | │ │ │ │ │ -| } | │ │ │ │ │ | | │ │ │ │ │ -|std::uint16_t session_impl::listen_port() const | │ │ │ │ │ -|{ | │ │ │ │ │ -| return listen_port(nullptr); | │ │ │ │ │ -| } | │ │ │ │ │ +| std::tie(protocol, std::ignore, hostname, port, std::ignore) | │ │ │ │ │ +| = parse_url_components(tracker_req().url, ec); | │ │ │ │ │ +| if (port == -1) port = protocol == "http" ? 80 : 443; | │ │ │ │ │ | | │ │ │ │ │ -| std::uint16_t session_impl::listen_port(listen_socket_t* sock) const | │ │ │ │ │ -| { | │ │ │ │ │ -| if (m_listen_sockets.empty()) return 0; | │ │ │ │ │ -| if (sock) | │ │ │ │ │ +| if (ec) | │ │ │ │ │ | { | │ │ │ │ │ -| // if we're using a proxy, we won't be able to accept any TCP | │ │ │ │ │ -| // connections. Not even uTP connections via the port we know about. | │ │ │ │ │ -| // The DHT may use the implied port to make it work, but the port we | │ │ │ │ │ -| // announce here has no relevance for that. | │ │ │ │ │ -| if (sock->flags & listen_socket_t::proxy) | │ │ │ │ │ -| return 0; | │ │ │ │ │ -| | │ │ │ │ │ -| if (!(sock->flags & listen_socket_t::accept_incoming)) | │ │ │ │ │ -| return 0; | │ │ │ │ │ -| | │ │ │ │ │ -| return std::uint16_t(sock->tcp_external_port()); | │ │ │ │ │ +| tracker_connection::fail(ec, operation_t::parse_address); | │ │ │ │ │ +| return; | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -|#ifdef TORRENT_SSL_PEERS | │ │ │ │ │ -| for (auto const& s : m_listen_sockets) | │ │ │ │ │ -| { | │ │ │ │ │ -| if (!(s->flags & listen_socket_t::accept_incoming)) continue; | │ │ │ │ │ -| if (s->ssl == transport::plaintext) | │ │ │ │ │ -| return std::uint16_t(s->tcp_external_port()); | │ │ │ │ │ -| } | │ │ │ │ │ -|_ _ _r_e_t_u_r_n_ _0_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _2_|_._._/_s_r_c_/_s_e_s_s_i_o_n___i_m_p_l_._c_p_p_:_5_5_5_3_ _ _|_t_h_i_s_ _f_u_n_c_t_i_o_n_ _s_h_o_u_l_d_ _b_e_ _r_e_m_o_v_e_d_ _a_n_d_ _u_s_e_r_s_ _n_e_e_d_ _t_o_ _d_e_a_l_ _w_i_t_h_ _t_h_e_ _m_o_r_e_ _g_e_n_e_r_i_c_ _c_a_s_e_ _o_f_ _h_a_v_i_n_g_ _m_u_l_t_i_p_l_e_ _s_s_l_ _p_o_r_t_s_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tthhiiss ffuunnccttiioonn sshhoouulldd bbee rreemmoovveedd aanndd uusseerrss nneeeedd ttoo ddeeaall wwiitthh tthhee mmoorree ggeenneerriicc ccaassee ooff hhaavviinngg mmuullttiippllee ssssll ppoorrttss ********** | │ │ │ │ │ -|****** ....//ssrrcc//sseessssiioonn__iimmppll..ccpppp::55555533 ****** | │ │ │ │ │ -|return 0; | │ │ │ │ │ +| aux::session_settings const& settings = m_man.settings(); | │ │ │ │ │ | | │ │ │ │ │ -| return std::uint16_t(sock->tcp_external_port()); | │ │ │ │ │ -| } | │ │ │ │ │ +| int const proxy_type = settings.get_int(settings_pack::proxy_type); | │ │ │ │ │ | | │ │ │ │ │ -|#ifdef TORRENT_SSL_PEERS | │ │ │ │ │ -| for (auto const& s : m_listen_sockets) | │ │ │ │ │ +| if (settings.get_bool(settings_pack::proxy_hostnames) | │ │ │ │ │ +| && (proxy_type == settings_pack::socks5 | │ │ │ │ │ +| || proxy_type == settings_pack::socks5_pw)) | │ │ │ │ │ | { | │ │ │ │ │ -| if (!(s->flags & listen_socket_t::accept_incoming)) continue; | │ │ │ │ │ -| if (s->ssl == transport::plaintext) | │ │ │ │ │ -| return std::uint16_t(s->tcp_external_port()); | │ │ │ │ │ +| m_hostname = hostname; | │ │ │ │ │ +| m_target.port(std::uint16_t(port)); | │ │ │ │ │ +| start_announce(); | │ │ │ │ │ | } | │ │ │ │ │ -| return 0; | │ │ │ │ │ -|#else | │ │ │ │ │ -| sock = m_listen_sockets.front().get(); | │ │ │ │ │ -| if (!(sock->flags & listen_socket_t::accept_incoming)) return 0; | │ │ │ │ │ -| return std::uint16_t(sock->tcp_external_port()); | │ │ │ │ │ -|#endif | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -|std::uint16_t session_impl::ssl_listen_port() const | │ │ │ │ │ -|{ | │ │ │ │ │ -| return ssl_listen_port(nullptr); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| std::uint16_t session_impl::ssl_listen_port(listen_socket_t* sock) const | │ │ │ │ │ -| { | │ │ │ │ │ -|#ifdef TORRENT_SSL_PEERS | │ │ │ │ │ -| if (sock) | │ │ │ │ │ +| else | │ │ │ │ │ | { | │ │ │ │ │ -| if (!(sock->flags & listen_socket_t::accept_incoming)) return 0; | │ │ │ │ │ -| return std::uint16_t(sock->tcp_external_port()); | │ │ │ │ │ -| } | │ │ │ │ │ +| using namespace std::placeholders; | │ │ │ │ │ +|_ _ _ _A_D_D___O_U_T_S_T_A_N_D_I_N_G___A_S_Y_N_C_(_"_u_d_p___t_r_a_c_k_e_r___c_o_n_n_e_c_t_i_o_n_:_:_n_a_m_e___l_o_o_k_u_p_"_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _2_|_._._/_s_r_c_/_b_d_e_c_o_d_e_._c_p_p_:_8_2_6_ _ _ _ _ _ _ _ _|_a_t_t_e_m_p_t_ _t_o_ _s_i_m_p_l_i_f_y_ _t_h_i_s_ _i_m_p_l_e_m_e_n_t_a_t_i_o_n_ _b_y_ _e_m_b_r_a_c_i_n_g_ _t_h_e_ _s_p_a_n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** aatttteemmpptt ttoo ssiimmpplliiffyy tthhiiss iimmpplleemmeennttaattiioonn bbyy eemmbbrraacciinngg tthhee ssppaann ********** | │ │ │ │ │ +|****** ....//ssrrcc//bbddeeccooddee..ccpppp::882266 ****** | │ │ │ │ │ +|} | │ │ │ │ │ | | │ │ │ │ │ -| if (m_settings.get_int(settings_pack::proxy_type) != settings_pack::none | │ │ │ │ │ -| && m_settings.get_bool(settings_pack::proxy_peer_connections)) | │ │ │ │ │ -| return 0; | │ │ │ │ │ +| bdecode_node bdecode(span buffer | │ │ │ │ │ +| , error_code& ec, int* error_pos, int depth_limit, int token_limit) | │ │ │ │ │ +| { | │ │ │ │ │ +| bdecode_node ret; | │ │ │ │ │ +| ec.clear(); | │ │ │ │ │ | | │ │ │ │ │ -| for (auto const& s : m_listen_sockets) | │ │ │ │ │ +| if (buffer.size() > bdecode_token::max_offset) | │ │ │ │ │ | { | │ │ │ │ │ -| if (!(s->flags & listen_socket_t::accept_incoming)) continue; | │ │ │ │ │ -| if (s->ssl == transport::ssl) | │ │ │ │ │ -| return std::uint16_t(s->tcp_external_port()); | │ │ │ │ │ +| if (error_pos) *error_pos = 0; | │ │ │ │ │ +| ec = bdecode_errors::limit_exceeded; | │ │ │ │ │ +| return ret; | │ │ │ │ │ | } | │ │ │ │ │ -|#else | │ │ │ │ │ -| TORRENT_UNUSED(sock); | │ │ │ │ │ -|#endif | │ │ │ │ │ -| return 0; | │ │ │ │ │ -| } | │ │ │ │ │ | | │ │ │ │ │ -|_ _i_n_t_ _s_e_s_s_i_o_n___i_m_p_l_:_:_g_e_t___l_i_s_t_e_n___p_o_r_t_(_t_r_a_n_s_p_o_r_t_ _c_o_n_s_t_ _s_s_l_,_ _a_u_x_:_:_l_i_s_t_e_n___s_o_c_k_e_t___h_a_n_d_l_e_ _c_o_n_s_t_&_ _s_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _2_|_._._/_s_r_c_/_s_e_s_s_i_o_n___i_m_p_l_._c_p_p_:_6_3_8_8_ _ _|_t_h_i_s_ _s_h_o_u_l_d_ _b_e_ _f_a_c_t_o_r_e_d_ _i_n_t_o_ _t_h_e_ _u_d_p_ _s_o_c_k_e_t_,_ _s_o_ _w_e_ _o_n_l_y_ _h_a_v_e_ _t_h_e_ _c_o_d_e_ _o_n_c_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tthhiiss sshhoouulldd bbee ffaaccttoorreedd iinnttoo tthhee uuddpp ssoocckkeett,, ssoo wwee oonnllyy hhaavvee tthhee ccooddee oonnccee ********** | │ │ │ │ │ -|****** ....//ssrrcc//sseessssiioonn__iimmppll..ccpppp::66338888 ****** | │ │ │ │ │ -|return upload_rate_limit(m_local_peer_class); | │ │ │ │ │ -| } | │ │ │ │ │ +| // this is the stack of bdecode_token indices, into m_tokens. | │ │ │ │ │ +| // sp is the stack pointer, as index into the array, stack | │ │ │ │ │ +| int sp = 0; | │ │ │ │ │ +| TORRENT_ALLOCA(stack, stack_frame, depth_limit); | │ │ │ │ │ | | │ │ │ │ │ -| int session_impl::local_download_rate_limit() const | │ │ │ │ │ -| { | │ │ │ │ │ -| return download_rate_limit(m_local_peer_class); | │ │ │ │ │ -| } | │ │ │ │ │ +|char const* start = buffer.data(); | │ │ │ │ │ +|char const* end = start + buffer.size(); | │ │ │ │ │ +| char const* const orig_start = start; | │ │ │ │ │ | | │ │ │ │ │ -| int session_impl::upload_rate_limit_depr() const | │ │ │ │ │ -| { | │ │ │ │ │ -| return upload_rate_limit(m_global_class); | │ │ │ │ │ -| } | │ │ │ │ │ +| if (start == end) | │ │ │ │ │ +| TORRENT_FAIL_BDECODE(bdecode_errors::unexpected_eof); | │ │ │ │ │ | | │ │ │ │ │ -| int session_impl::download_rate_limit_depr() const | │ │ │ │ │ -| { | │ │ │ │ │ -| return download_rate_limit(m_global_class); | │ │ │ │ │ -| } | │ │ │ │ │ -|#endif // DEPRECATE | │ │ │ │ │ +| while (start <= end) | │ │ │ │ │ +| { | │ │ │ │ │ +| if (start >= end) TORRENT_FAIL_BDECODE(bdecode_errors::unexpected_eof); | │ │ │ │ │ | | │ │ │ │ │ +| if (sp >= depth_limit) | │ │ │ │ │ +| TORRENT_FAIL_BDECODE(bdecode_errors::depth_exceeded); | │ │ │ │ │ | | │ │ │ │ │ -|void session_impl::update_peer_dscp() | │ │ │ │ │ -|{ | │ │ │ │ │ -| int const value = m_settings.get_int(settings_pack::peer_dscp); | │ │ │ │ │ -| for (auto const& l : m_listen_sockets) | │ │ │ │ │ -| { | │ │ │ │ │ -| if (l->sock) | │ │ │ │ │ -| { | │ │ │ │ │ -| error_code ec; | │ │ │ │ │ -| set_traffic_class(*l->sock, value, ec); | │ │ │ │ │ +| --token_limit; | │ │ │ │ │ +| if (token_limit < 0) | │ │ │ │ │ +| TORRENT_FAIL_BDECODE(bdecode_errors::limit_exceeded); | │ │ │ │ │ | | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ -| if (should_log()) | │ │ │ │ │ -| { | │ │ │ │ │ -| session_log(">>> SET_DSCP [ tcp (%s %d) value: %x e: %s ]" | │ │ │ │ │ -| , l->sock->local_endpoint().address().to_string().c_str() | │ │ │ │ │ -| , l->sock->local_endpoint().port(), value, ec.message().c_str()); | │ │ │ │ │ -| } | │ │ │ │ │ -|#endif | │ │ │ │ │ -| } | │ │ │ │ │ +| // look for a new token | │ │ │ │ │ +| char const t = *start; | │ │ │ │ │ | | │ │ │ │ │ -| if (l->udp_sock) | │ │ │ │ │ -| { | │ │ │ │ │ -| error_code ec; | │ │ │ │ │ -| set_traffic_class(l->udp_sock->sock, value, ec); | │ │ │ │ │ +| int const current_frame = sp; | │ │ │ │ │ | | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ -| if (should_log()) | │ │ │ │ │ +| // if we're currently parsing a dictionary, assert that | │ │ │ │ │ +| // every other node is a string. | │ │ │ │ │ +| if (current_frame > 0 | │ │ │ │ │ +| && ret.m_tokens[stack[current_frame - 1].token].type == bdecode_token::dict) | │ │ │ │ │ +| { | │ │ │ │ │ +| if (stack[current_frame - 1].state == 0) | │ │ │ │ │ | { | │ │ │ │ │ -| session_log(">>> SET_DSCP [ udp (%s %d) value: %x e: %s ]" | │ │ │ │ │ -| , l->udp_sock->sock.local_endpoint().address().to_string().c_str() | │ │ │ │ │ -|_ _ _ _ _ _ _,_ _l_-_>_u_d_p___s_o_c_k_-_>_s_o_c_k_._l_o_c_a_l___p_o_r_t_(_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_ _ _ _ _ _/_/_ _t_h_e_ _c_u_r_r_e_n_t_ _p_a_r_e_n_t_ _i_s_ _a_ _d_i_c_t_ _a_n_d_ _w_e_ _a_r_e_ _p_a_r_s_i_n_g_ _a_ _k_e_y_._ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |_r_e_l_e_v_a_n_c_e_ _2_|_._._/_s_r_c_/_p_i_e_c_e___p_i_c_k_e_r_._c_p_p_:_2_0_0_3_ _ _|_m_a_k_e_ _t_h_e_ _2_0_4_8_ _l_i_m_i_t_ _c_o_n_f_i_g_u_r_a_b_l_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** mmaakkee tthhee 22004488 lliimmiitt ccoonnffiigguurraabbllee ********** | │ │ │ │ │ |****** ....//ssrrcc//ppiieeccee__ppiicckkeerr..ccpppp::22000033 ****** | │ │ │ │ │ |// indicating which path thought the picker we took to arrive at the | │ │ │ │ │ | // returned block picks. | │ │ │ │ │ | picker_flags_t piece_picker::pick_pieces(typed_bitfield const& pieces | │ │ │ │ │ | , std::vector& interesting_blocks, int num_blocks | │ │ │ │ │ @@ -3867,68 +3481,14 @@ │ │ │ │ │ | TORRENT_ASSERT(info.num_peers == 0); | │ │ │ │ │ | | │ │ │ │ │ | TORRENT_ASSERT(i->writing > 0); | │ │ │ │ │ | TORRENT_ASSERT(info.state == block_info::state_writing); | │ │ │ │ │ | | │ │ │ │ │ | if (info.state == block_info::state_finished) return; | │ │ │ │ │ |_ _ _i_f_ _(_i_n_f_o_._s_t_a_t_e_ _=_=_ _b_l_o_c_k___i_n_f_o_:_:_s_t_a_t_e___w_r_i_t_i_n_g_)_ _-_-_i_-_>_w_r_i_t_i_n_g_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _2_|_._._/_s_r_c_/_t_r_a_c_k_e_r___m_a_n_a_g_e_r_._c_p_p_:_3_6_9_|_i_m_p_l_e_m_e_n_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** iimmpplleemmeenntt ********** | │ │ │ │ │ -|****** ....//ssrrcc//ttrraacckkeerr__mmaannaaggeerr..ccpppp::336699 ****** | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ -| if (m_ses.should_log()) | │ │ │ │ │ -| { | │ │ │ │ │ -| m_ses.session_log("incoming UDP tracker packet from %s has invalid " | │ │ │ │ │ -| "transaction ID (%x)", print_endpoint(ep).c_str() | │ │ │ │ │ -| , transaction); | │ │ │ │ │ -| } | │ │ │ │ │ -|#endif | │ │ │ │ │ -| return false; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| std::shared_ptr const p = i->second; | │ │ │ │ │ -| // on_receive() may remove the tracker connection from the list | │ │ │ │ │ -| return p->on_receive(ep, buf); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| void tracker_manager::incoming_error(error_code const& | │ │ │ │ │ -| , udp::endpoint const&) | │ │ │ │ │ -| { | │ │ │ │ │ -| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ -|} | │ │ │ │ │ -| | │ │ │ │ │ -| bool tracker_manager::incoming_packet(string_view const hostname | │ │ │ │ │ -| , span const buf) | │ │ │ │ │ -| { | │ │ │ │ │ -| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ -| // ignore packets smaller than 8 bytes | │ │ │ │ │ -| if (buf.size() < 16) return false; | │ │ │ │ │ -| | │ │ │ │ │ -| // the first word is the action, if it's not [0, 3] | │ │ │ │ │ -| // it's not a valid udp tracker response | │ │ │ │ │ -| span ptr = buf; | │ │ │ │ │ -| std::uint32_t const action = aux::read_uint32(ptr); | │ │ │ │ │ -| if (action > 3) return false; | │ │ │ │ │ -| | │ │ │ │ │ -| std::uint32_t const transaction = aux::read_uint32(ptr); | │ │ │ │ │ -| auto const i = m_udp_conns.find(transaction); | │ │ │ │ │ -| | │ │ │ │ │ -| if (i == m_udp_conns.end()) | │ │ │ │ │ -| { | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ -| // now, this may not have been meant to be a tracker response, | │ │ │ │ │ -| // but chances are pretty good, so it's probably worth logging | │ │ │ │ │ -| m_ses.session_log("incoming UDP tracker packet from %s has invalid " | │ │ │ │ │ -| "transaction ID (%x)", std::string(hostname).c_str(), int(transaction)); | │ │ │ │ │ -|#endif | │ │ │ │ │ -| return false; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| std::shared_ptr const p = i->second; | │ │ │ │ │ -|_ _ _/_/_ _o_n___r_e_c_e_i_v_e_(_)_ _m_a_y_ _r_e_m_o_v_e_ _t_h_e_ _t_r_a_c_k_e_r_ _c_o_n_n_e_c_t_i_o_n_ _f_r_o_m_ _t_h_e_ _l_i_s_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |relevance 2|_._._/_s_r_c_/_p_e_e_r___l_i_s_t_._c_p_p_:_5_3_9 |it would be nice if there was a way to iterate over these torrent_peer objects in the order they are allocated in the pool instead. | │ │ │ │ │ |_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_I_t_ _w_o_u_l_d_ _p_r_o_b_a_b_l_y_ _b_e_ _m_o_r_e_ _e_f_f_i_c_i_e_n_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** iitt wwoouulldd bbee nniiccee iiff tthheerree wwaass aa wwaayy ttoo iitteerraattee oovveerr tthheessee ttoorrrreenntt__ppeeeerr oobbjjeeccttss iinn tthhee oorrddeerr tthheeyy aarree aallllooccaatteedd iinn tthhee ppooooll iinnsstteeaadd.. IItt wwoouulldd pprroobbaabbllyy bbee mmoorree eeffffiicciieenntt | │ │ │ │ │ |********** | │ │ │ │ │ |****** ....//ssrrcc//ppeeeerr__lliisstt..ccpppp::553399 ****** | │ │ │ │ │ |, int session_time, torrent_state* state) | │ │ │ │ │ | { | │ │ │ │ │ @@ -3977,69 +3537,454 @@ │ │ │ │ │ | erase_peer(m_peers.begin() + current, state); | │ │ │ │ │ | continue; | │ │ │ │ │ | } | │ │ │ │ │ | else | │ │ │ │ │ | { | │ │ │ │ │ | erase_candidate = current; | │ │ │ │ │ |_ _ _ _ _ _}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 2|_._._/_s_r_c_/_k_a_d_e_m_l_i_a_/ |make this configurable in dht_settings | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_d_h_t___s_t_o_r_a_g_e_._c_p_p_:_8_7_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** mmaakkee tthhiiss ccoonnffiigguurraabbllee iinn ddhhtt__sseettttiinnggss ********** | │ │ │ │ │ -|****** ....//ssrrcc//kkaaddeemmlliiaa//ddhhtt__ssttoorraaggee..ccpppp::8877 ****** | │ │ │ │ │ -|tcp::endpoint addr; | │ │ │ │ │ -| bool seed = 0; | │ │ │ │ │ -| }; | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _2_|_._._/_s_r_c_/_p_a_t_h_._c_p_p_:_4_2_9_ _ _ _ _ _ _ _ _ _ _ _|_t_e_s_t_ _t_h_i_s_ _o_n_ _a_ _F_A_T_ _v_o_l_u_m_e_ _t_o_ _s_e_e_ _w_h_a_t_ _e_r_r_o_r_ _w_e_ _g_e_t_!_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tteesstt tthhiiss oonn aa FFAATT vvoolluummee ttoo sseeee wwhhaatt eerrrroorr wwee ggeett!! ********** | │ │ │ │ │ +|****** ....//ssrrcc//ppaatthh..ccpppp::442299 ****** | │ │ │ │ │ +|// it's possible CreateHardLink will copy the file internally too, | │ │ │ │ │ +| // if the filesystem does not support it. | │ │ │ │ │ +| ec.assign(GetLastError(), system_category()); | │ │ │ │ │ +| return; | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -| // internal | │ │ │ │ │ -| bool operator<(peer_entry const& lhs, peer_entry const& rhs) | │ │ │ │ │ +| // fall back to making a copy | │ │ │ │ │ +|#endif | │ │ │ │ │ +|#else | │ │ │ │ │ +| // assume posix's link() function exists | │ │ │ │ │ +| int ret = ::link(n_exist.c_str(), n_link.c_str()); | │ │ │ │ │ +| | │ │ │ │ │ +| if (ret == 0) | │ │ │ │ │ +| { | │ │ │ │ │ +| ec.clear(); | │ │ │ │ │ +| return; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| // most errors are passed through, except for the ones that indicate that | │ │ │ │ │ +| // hard links are not supported and require a copy. | │ │ │ │ │ +|if (errno != EMLINK | │ │ │ │ │ +|&& errno != EXDEV | │ │ │ │ │ +|#ifdef TORRENT_BEOS | │ │ │ │ │ +| // haiku returns EPERM when the filesystem doesn't support hard link | │ │ │ │ │ +| && errno != EPERM | │ │ │ │ │ +|#endif | │ │ │ │ │ +| ) | │ │ │ │ │ +| { | │ │ │ │ │ +| // some error happened, report up to the caller | │ │ │ │ │ +| ec.assign(errno, system_category()); | │ │ │ │ │ +| return; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| // fall back to making a copy | │ │ │ │ │ +| | │ │ │ │ │ +|#endif | │ │ │ │ │ +| | │ │ │ │ │ +| // if we get here, we should copy the file | │ │ │ │ │ +| storage_error se; | │ │ │ │ │ +| aux::copy_file(file, link, se); | │ │ │ │ │ +| ec = se.ec; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| bool is_directory(std::string const& f, error_code& ec) | │ │ │ │ │ | { | │ │ │ │ │ -| return lhs.addr.address() == rhs.addr.address() | │ │ │ │ │ -| ? lhs.addr.port() < rhs.addr.port() | │ │ │ │ │ -| : lhs.addr.address() < rhs.addr.address(); | │ │ │ │ │ +| ec.clear(); | │ │ │ │ │ +| error_code e; | │ │ │ │ │ +| file_status s; | │ │ │ │ │ +| stat_file(f, &s, e); | │ │ │ │ │ +| if (!e && s.mode & file_status::directory) return true; | │ │ │ │ │ +|_ _ _e_c_ _=_ _e_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +| | |technically, this is where the transaction of moving the files is completed. This is where the new save_path should be committed. If| │ │ │ │ │ +|relevance 2|_._._/_s_r_c_/_s_t_o_r_a_g_e___u_t_i_l_s_._c_p_p_:_2_9_4 |there is an error in the code below, that should not prevent the new save path to be set. Maybe it would make sense to make the | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_s_a_v_e___p_a_t_h_ _a_n_ _i_n_-_o_u_t_ _p_a_r_a_m_e_t_e_r_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tteecchhnniiccaallllyy,, tthhiiss iiss wwhheerree tthhee ttrraannssaaccttiioonn ooff mmoovviinngg tthhee ffiilleess iiss ccoommpplleetteedd.. TThhiiss iiss wwhheerree tthhee nneeww ssaavvee__ppaatthh sshhoouulldd bbee ccoommmmiitttteedd.. IIff tthheerree iiss aann eerrrroorr iinn tthhee ccooddee bbeellooww,,| │ │ │ │ │ +|tthhaatt sshhoouulldd nnoott pprreevveenntt tthhee nneeww ssaavvee ppaatthh ttoo bbee sseett.. MMaayybbee iitt wwoouulldd mmaakkee sseennssee ttoo mmaakkee tthhee ssaavvee__ppaatthh aann iinn--oouutt ppaarraammeetteerr ********** | │ │ │ │ │ +|****** ....//ssrrcc//ssttoorraaggee__uuttiillss..ccpppp::229944 ****** | │ │ │ │ │ +|while (--file_index >= file_index_t(0)) | │ │ │ │ │ +| { | │ │ │ │ │ +| // files moved out to absolute paths are not moved | │ │ │ │ │ +| if (f.file_absolute_path(file_index)) continue; | │ │ │ │ │ +| | │ │ │ │ │ +| // if we ended up copying the file, don't do anything during | │ │ │ │ │ +| // roll-back | │ │ │ │ │ +| if (copied_files[file_index]) continue; | │ │ │ │ │ +| | │ │ │ │ │ +| std::string const old_path = combine_path(save_path, f.file_path(file_index)); | │ │ │ │ │ +| std::string const new_path = combine_path(new_save_path, f.file_path(file_index)); | │ │ │ │ │ +| | │ │ │ │ │ +| // ignore errors when rolling back | │ │ │ │ │ +| storage_error ignore; | │ │ │ │ │ +| move_file(new_path, old_path, ignore); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| return { status_t::fatal_disk_error, save_path }; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| | │ │ │ │ │ +|std::set subdirs; | │ │ │ │ │ +| for (auto const i : f.file_range()) | │ │ │ │ │ +| { | │ │ │ │ │ +| // files moved out to absolute paths are not moved | │ │ │ │ │ +| if (f.file_absolute_path(i)) continue; | │ │ │ │ │ +| | │ │ │ │ │ +| if (has_parent_path(f.file_path(i))) | │ │ │ │ │ +| subdirs.insert(parent_path(f.file_path(i))); | │ │ │ │ │ +| | │ │ │ │ │ +| // if we ended up renaming the file instead of moving it, there's no | │ │ │ │ │ +| // need to delete the source. | │ │ │ │ │ +| if (copied_files[i] == false) continue; | │ │ │ │ │ +| | │ │ │ │ │ +| std::string const old_path = combine_path(save_path, f.file_path(i)); | │ │ │ │ │ +| | │ │ │ │ │ +| // we may still have some files in old save_path | │ │ │ │ │ +| // eg. if (flags == dont_replace && exists(new_path)) | │ │ │ │ │ +| // ignore errors when removing | │ │ │ │ │ +| error_code ignore; | │ │ │ │ │ +| remove(old_path, ignore); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| for (std::string const& s : subdirs) | │ │ │ │ │ +| { | │ │ │ │ │ +| error_code err; | │ │ │ │ │ +| std::string subdir = combine_path(save_path, s); | │ │ │ │ │ +| | │ │ │ │ │ +| while (!path_equal(subdir, save_path) && !err) | │ │ │ │ │ +| { | │ │ │ │ │ +|_ _ _ _ _r_e_m_o_v_e_(_s_u_b_d_i_r_,_ _e_r_r_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 2|_._._/_s_r_c_/_s_t_o_r_a_g_e___u_t_i_l_s_._c_p_p_:_4_8_6 |is this risky? The upper layer will assume we have the whole file. Perhaps we should verify that at least the size of the file is | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_c_o_r_r_e_c_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** iiss tthhiiss rriisskkyy?? TThhee uuppppeerr llaayyeerr wwiillll aassssuummee wwee hhaavvee tthhee wwhhoollee ffiillee.. PPeerrhhaappss wwee sshhoouulldd vveerriiffyy tthhaatt aatt lleeaasstt tthhee ssiizzee ooff tthhee ffiillee iiss ccoorrrreecctt ********** | │ │ │ │ │ +|****** ....//ssrrcc//ssttoorraaggee__uuttiillss..ccpppp::448866 ****** | │ │ │ │ │ +|{ | │ │ │ │ │ +| // we create directories lazily, so it's possible it hasn't | │ │ │ │ │ +| // been created yet. Create the directories now and try | │ │ │ │ │ +| // again | │ │ │ │ │ +| create_directories(parent_path(file_path), err); | │ │ │ │ │ +| | │ │ │ │ │ +| if (err) | │ │ │ │ │ +| { | │ │ │ │ │ +| ec.file(idx); | │ │ │ │ │ +| ec.operation = operation_t::mkdir; | │ │ │ │ │ +| return false; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| hard_link(s, file_path, err); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| // if the file already exists, that's not an error | │ │ │ │ │ +| if (err == boost::system::errc::file_exists) | │ │ │ │ │ +| continue; | │ │ │ │ │ +| | │ │ │ │ │ +|if (err) | │ │ │ │ │ +|{ | │ │ │ │ │ +| ec.ec = err; | │ │ │ │ │ +| ec.file(idx); | │ │ │ │ │ +| ec.operation = operation_t::file_hard_link; | │ │ │ │ │ +| return false; | │ │ │ │ │ +| } | │ │ │ │ │ +| added_files = true; | │ │ │ │ │ +| stat.set_dirty(idx); | │ │ │ │ │ +| } | │ │ │ │ │ +| } | │ │ │ │ │ +|#endif // TORRENT_DISABLE_MUTABLE_TORRENTS | │ │ │ │ │ +| | │ │ │ │ │ +| bool const seed = (rd.have_pieces.size() >= fs.num_pieces() | │ │ │ │ │ +| && rd.have_pieces.all_set()) | │ │ │ │ │ +| || (rd.flags & torrent_flags::seed_mode); | │ │ │ │ │ +| | │ │ │ │ │ +| if (seed) | │ │ │ │ │ +| { | │ │ │ │ │ +| for (file_index_t const file_index : fs.file_range()) | │ │ │ │ │ +| { | │ │ │ │ │ +| if (fs.pad_file_at(file_index)) continue; | │ │ │ │ │ +| | │ │ │ │ │ +| // files with priority zero may not have been saved to disk at their | │ │ │ │ │ +| // expected location, but is likely to be in a partfile. Just exempt it | │ │ │ │ │ +| // from checking | │ │ │ │ │ +| if (file_index < file_priority.end_index() | │ │ │ │ │ +| && file_priority[file_index] == dont_download | │ │ │ │ │ +| && !(rd.flags & torrent_flags::seed_mode)) | │ │ │ │ │ +|_ _ _ _ _ _c_o_n_t_i_n_u_e_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 2|_._._/_s_r_c_/_p_e_e_r___c_o_n_n_e_c_t_i_o_n_._c_p_p_: |this should probably be based on time instead of number of request messages. For a very high throughput connection, 300 may be a | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_2_5_4_8_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_l_e_g_i_t_i_m_a_t_e_ _n_u_m_b_e_r_ _o_f_ _r_e_q_u_e_s_t_s_ _t_o_ _h_a_v_e_ _i_n_ _f_l_i_g_h_t_ _w_h_e_n_ _g_e_t_t_i_n_g_ _c_h_o_k_e_d_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tthhiiss sshhoouulldd pprroobbaabbllyy bbee bbaasseedd oonn ttiimmee iinnsstteeaadd ooff nnuummbbeerr ooff rreeqquueesstt mmeessssaaggeess.. FFoorr aa vveerryy hhiigghh tthhrroouugghhppuutt ccoonnnneeccttiioonn,, 330000 mmaayy bbee aa lleeggiittiimmaattee nnuummbbeerr ooff rreeqquueessttss ttoo hhaavvee iinn| │ │ │ │ │ +|fflliigghhtt wwhheenn ggeettttiinngg cchhookkeedd ********** | │ │ │ │ │ +|****** ....//ssrrcc//ppeeeerr__ccoonnnneeccttiioonn..ccpppp::22554488 ****** | │ │ │ │ │ +|} | │ │ │ │ │ +|#endif | │ │ │ │ │ +| | │ │ │ │ │ +| write_reject_request(r); | │ │ │ │ │ +| if (m_num_invalid_requests < std::numeric_limits::max()) | │ │ │ │ │ +| ++m_num_invalid_requests; | │ │ │ │ │ +| | │ │ │ │ │ +| if (t->alerts().should_post()) | │ │ │ │ │ +| { | │ │ │ │ │ +| // msvc 12 appears to deduce the rvalue reference template | │ │ │ │ │ +| // incorrectly for bool temporaries. So, create a dummy instance | │ │ │ │ │ +| bool const peer_interested = bool(m_peer_interested); | │ │ │ │ │ +| t->alerts().emplace_alert( | │ │ │ │ │ +| t->get_handle(), m_remote, m_peer_id, r | │ │ │ │ │ +| , t->has_piece_passed(r.piece), peer_interested, false); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| // every ten invalid request, remind the peer that it's choked | │ │ │ │ │ +| if (!m_peer_interested && m_num_invalid_requests % 10 == 0 && m_choked) | │ │ │ │ │ +| { | │ │ │ │ │ +|if (m_num_invalid_requests > 300 && !m_peer_choked | │ │ │ │ │ +|&& can_disconnect(errors::too_many_requests_when_choked)) | │ │ │ │ │ +| { | │ │ │ │ │ +| disconnect(errors::too_many_requests_when_choked, operation_t::bittorrent, peer_error); | │ │ │ │ │ +| return; | │ │ │ │ │ +| } | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ +| peer_log(peer_log_alert::outgoing_message, "CHOKE"); | │ │ │ │ │ +|#endif | │ │ │ │ │ +| write_choke(); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| return; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| // if we have choked the client | │ │ │ │ │ +| // ignore the request | │ │ │ │ │ +| int const blocks_per_piece = | │ │ │ │ │ +| (ti.piece_length() + t->block_size() - 1) / t->block_size(); | │ │ │ │ │ +| | │ │ │ │ │ +| // disconnect peers that downloads more than foo times an allowed | │ │ │ │ │ +| // fast piece | │ │ │ │ │ +| if (m_choked && fast_idx != -1 && m_accept_fast_piece_cnt[fast_idx] >= 3 * blocks_per_piece | │ │ │ │ │ +| && can_disconnect(errors::too_many_requests_when_choked)) | │ │ │ │ │ +| { | │ │ │ │ │ +| disconnect(errors::too_many_requests_when_choked, operation_t::bittorrent, peer_error); | │ │ │ │ │ +| return; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| if (m_choked && fast_idx == -1) | │ │ │ │ │ +|_ _ _{_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +| |_._._/_s_r_c_/_p_e_e_r___c_o_n_n_e_c_t_i_o_n_._c_p_p_: |since we throw away the queue entry once we issue the disk job, this may happen. Instead, we should keep the queue entry around, | │ │ │ │ │ +|relevance 2|_3_2_9_3 |mark it as having been requested from disk and once the disk job comes back, discard it if it has been cancelled. Maybe even be able| │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_t_o_ _c_a_n_c_e_l_ _d_i_s_k_ _j_o_b_s_?_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** ssiinnccee wwee tthhrrooww aawwaayy tthhee qquueeuuee eennttrryy oonnccee wwee iissssuuee tthhee ddiisskk jjoobb,, tthhiiss mmaayy hhaappppeenn.. IInnsstteeaadd,, wwee sshhoouulldd kkeeeepp tthhee qquueeuuee eennttrryy aarroouunndd,, mmaarrkk iitt aass hhaavviinngg bbeeeenn rreeqquueesstteedd ffrroomm | │ │ │ │ │ +|ddiisskk aanndd oonnccee tthhee ddiisskk jjoobb ccoommeess bbaacckk,, ddiissccaarrdd iitt iiff iitt hhaass bbeeeenn ccaanncceelllleedd.. MMaayybbee eevveenn bbee aabbllee ttoo ccaanncceell ddiisskk jjoobbss?? ********** | │ │ │ │ │ +|****** ....//ssrrcc//ppeeeerr__ccoonnnneeccttiioonn..ccpppp::33229933 ****** | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ +| peer_log(peer_log_alert::incoming_message, "CANCEL" | │ │ │ │ │ +| , "piece: %d s: %x l: %x", static_cast(r.piece), r.start, r.length); | │ │ │ │ │ +|#endif | │ │ │ │ │ +| | │ │ │ │ │ +| auto const i = std::find(m_requests.begin(), m_requests.end(), r); | │ │ │ │ │ +| | │ │ │ │ │ +| if (i != m_requests.end()) | │ │ │ │ │ +| { | │ │ │ │ │ +| m_counters.inc_stats_counter(counters::cancelled_piece_requests); | │ │ │ │ │ +| m_requests.erase(i); | │ │ │ │ │ +| | │ │ │ │ │ +| if (m_requests.empty()) | │ │ │ │ │ +| m_counters.inc_stats_counter(counters::num_peers_up_requests, -1); | │ │ │ │ │ +| | │ │ │ │ │ +| write_reject_request(r); | │ │ │ │ │ +| } | │ │ │ │ │ +| else | │ │ │ │ │ +| { | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ +|peer_log(peer_log_alert::info, "INVALID_CANCEL", "got cancel not in the queue"); | │ │ │ │ │ +|#endif | │ │ │ │ │ +| } | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -| // this is a group. It contains a set of group members | │ │ │ │ │ -| struct torrent_entry | │ │ │ │ │ +| // ----------------------------- | │ │ │ │ │ +| // --------- DHT PORT ---------- | │ │ │ │ │ +| // ----------------------------- | │ │ │ │ │ +| | │ │ │ │ │ +| void peer_connection::incoming_dht_port(int const listen_port) | │ │ │ │ │ | { | │ │ │ │ │ -| std::string name; | │ │ │ │ │ -| std::vector peers4; | │ │ │ │ │ -| std::vector peers6; | │ │ │ │ │ -| }; | │ │ │ │ │ +| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ +| INVARIANT_CHECK; | │ │ │ │ │ | | │ │ │ │ │ -|constexpr time_duration announce_interval = minutes(30); | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ +| peer_log(peer_log_alert::incoming_message, "DHT_PORT", "p: %d", listen_port); | │ │ │ │ │ +|#endif | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_DHT | │ │ │ │ │ +| m_ses.add_dht_node({m_remote.address(), std::uint16_t(listen_port)}); | │ │ │ │ │ +|#else | │ │ │ │ │ +| TORRENT_UNUSED(listen_port); | │ │ │ │ │ +|#endif | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -| struct dht_immutable_item | │ │ │ │ │ +| // ----------------------------- | │ │ │ │ │ +| // --------- HAVE ALL ---------- | │ │ │ │ │ +| // ----------------------------- | │ │ │ │ │ +| | │ │ │ │ │ +| void peer_connection::incoming_have_all() | │ │ │ │ │ +|_ _{_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 2|_._._/_s_r_c_/_p_e_e_r___c_o_n_n_e_c_t_i_o_n_._c_p_p_: |use a deadline_timer for timeouts. Don't rely on second_tick()! Hook this up to connect timeout as well. This would improve | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_4_9_5_8_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_p_e_r_f_o_r_m_a_n_c_e_ _b_e_c_a_u_s_e_ _o_f_ _l_e_s_s_ _w_o_r_k_ _i_n_ _s_e_c_o_n_d___t_i_c_k_(_)_,_ _a_n_d_ _m_i_g_h_t_ _l_e_t_ _u_s_e_ _r_e_m_o_v_e_ _t_i_c_k_i_n_g_ _e_n_t_i_r_e_l_y_ _e_v_e_n_t_u_a_l_l_y_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** uussee aa ddeeaaddlliinnee__ttiimmeerr ffoorr ttiimmeeoouuttss.. DDoonn''tt rreellyy oonn sseeccoonndd__ttiicckk(())!! HHooookk tthhiiss uupp ttoo ccoonnnneecctt ttiimmeeoouutt aass wweellll.. TThhiiss wwoouulldd iimmpprroovvee ppeerrffoorrmmaannccee bbeeccaauussee ooff lleessss wwoorrkk iinn | │ │ │ │ │ +|sseeccoonndd__ttiicckk(()),, aanndd mmiigghhtt lleett uussee rreemmoovvee ttiicckkiinngg eennttiirreellyy eevveennttuuaallllyy ********** | │ │ │ │ │ +|****** ....//ssrrcc//ppeeeerr__ccoonnnneeccttiioonn..ccpppp::44995588 ****** | │ │ │ │ │ +|if (d > seconds(connect_timeout) | │ │ │ │ │ +| && can_disconnect(errors::timed_out)) | │ │ │ │ │ +| { | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ +| peer_log(peer_log_alert::info, "CONNECT_FAILED", "waited %d seconds" | │ │ │ │ │ +| , int(total_seconds(d))); | │ │ │ │ │ +|#endif | │ │ │ │ │ +| connect_failed(errors::timed_out); | │ │ │ │ │ +| return; | │ │ │ │ │ +| } | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| // if the bw_network flag isn't set, it means we are not even trying to | │ │ │ │ │ +| // read from this peer's socket. Most likely because we're applying a | │ │ │ │ │ +| // rate limit. If the peer is "slow" because we are rate limiting it, | │ │ │ │ │ +| // don't enforce timeouts. However, as soon as we *do* read from the | │ │ │ │ │ +| // socket, we expect to receive data, and not have timed out. Then we | │ │ │ │ │ +| // can enforce the timeouts. | │ │ │ │ │ +| bool const reading_socket = bool(m_channel_state[download_channel] & peer_info::bw_network); | │ │ │ │ │ +| | │ │ │ │ │ +|if (reading_socket && d > seconds(timeout()) && !m_connecting && m_reading_bytes == 0 | │ │ │ │ │ +|&& can_disconnect(errors::timed_out_inactivity)) | │ │ │ │ │ +| { | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ +| peer_log(peer_log_alert::info, "LAST_ACTIVITY", "%d seconds ago" | │ │ │ │ │ +| , int(total_seconds(d))); | │ │ │ │ │ +|#endif | │ │ │ │ │ +| disconnect(errors::timed_out_inactivity, operation_t::bittorrent); | │ │ │ │ │ +| return; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| // do not stall waiting for a handshake | │ │ │ │ │ +| int timeout = m_settings.get_int (settings_pack::handshake_timeout); | │ │ │ │ │ +|#if TORRENT_USE_I2P | │ │ │ │ │ +| timeout *= is_i2p(m_socket) ? 4 : 1; | │ │ │ │ │ +|#endif | │ │ │ │ │ +| if (reading_socket | │ │ │ │ │ +| && !m_connecting | │ │ │ │ │ +| && in_handshake() | │ │ │ │ │ +| && d > seconds(timeout)) | │ │ │ │ │ +| { | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ +| peer_log(peer_log_alert::info, "NO_HANDSHAKE", "waited %d seconds" | │ │ │ │ │ +| , int(total_seconds(d))); | │ │ │ │ │ +|#endif | │ │ │ │ │ +| disconnect(errors::timed_out_no_handshake, operation_t::bittorrent); | │ │ │ │ │ +| return; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| // disconnect peers that we unchoked, but they didn't send a request in | │ │ │ │ │ +|_ _ _/_/_ _t_h_e_ _l_a_s_t_ _6_0_ _s_e_c_o_n_d_s_,_ _a_n_d_ _w_e_ _h_a_v_e_n_'_t_ _b_e_e_n_ _w_o_r_k_i_n_g_ _o_n_ _s_e_r_v_i_c_i_n_g_ _a_ _r_e_q_u_e_s_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _2_|_._._/_s_r_c_/_u_p_n_p_._c_p_p_:_1_0_6_ _ _ _ _ _ _ _ _ _ _ _|_u_s_e_ _b_o_o_s_t_:_:_a_s_i_o_:_:_i_p_:_:_n_e_t_w_o_r_k_ _i_n_s_t_e_a_d_ _o_f_ _n_e_t_m_a_s_k_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** uussee bboooosstt::::aassiioo::::iipp::::nneettwwoorrkk iinnsstteeaadd ooff nneettmmaasskk ********** | │ │ │ │ │ +|****** ....//ssrrcc//uuppnnpp..ccpppp::110066 ****** | │ │ │ │ │ +|static error_code ignore_error; | │ │ │ │ │ +| | │ │ │ │ │ +|upnp::rootdevice::rootdevice() = default; | │ │ │ │ │ +| | │ │ │ │ │ +|#if TORRENT_USE_ASSERTS | │ │ │ │ │ +|upnp::rootdevice::~rootdevice() | │ │ │ │ │ +|{ | │ │ │ │ │ +| TORRENT_ASSERT(magic == 1337); | │ │ │ │ │ +| magic = 0; | │ │ │ │ │ +|} | │ │ │ │ │ +|#else | │ │ │ │ │ +|upnp::rootdevice::~rootdevice() = default; | │ │ │ │ │ +|#endif | │ │ │ │ │ +| | │ │ │ │ │ +|upnp::rootdevice::rootdevice(rootdevice const&) = default; | │ │ │ │ │ +|upnp::rootdevice& upnp::rootdevice::operator=(rootdevice const&) & = default; | │ │ │ │ │ +|upnp::rootdevice::rootdevice(rootdevice&&) noexcept = default; | │ │ │ │ │ +|upnp::rootdevice& upnp::rootdevice::operator=(rootdevice&&) & = default; | │ │ │ │ │ +| | │ │ │ │ │ +|upnp::upnp(io_context& ios | │ │ │ │ │ +|, aux::session_settings const& settings | │ │ │ │ │ +| , aux::portmap_callback& cb | │ │ │ │ │ +| , address_v4 const listen_address | │ │ │ │ │ +| , address_v4 const netmask | │ │ │ │ │ +| , std::string listen_device | │ │ │ │ │ +| , listen_socket_handle ls) | │ │ │ │ │ +| : m_settings(settings) | │ │ │ │ │ +| , m_callback(cb) | │ │ │ │ │ +| , m_io_service(ios) | │ │ │ │ │ +| , m_resolver(ios) | │ │ │ │ │ +| , m_multicast(ios) | │ │ │ │ │ +| , m_unicast(ios) | │ │ │ │ │ +| , m_broadcast_timer(ios) | │ │ │ │ │ +| , m_refresh_timer(ios) | │ │ │ │ │ +| , m_map_timer(ios) | │ │ │ │ │ +| , m_listen_address(listen_address) | │ │ │ │ │ +| , m_netmask(netmask) | │ │ │ │ │ +| , m_device(std::move(listen_device)) | │ │ │ │ │ +|#if TORRENT_USE_SSL | │ │ │ │ │ +| , m_ssl_ctx(ssl::context::sslv23_client) | │ │ │ │ │ +|#endif | │ │ │ │ │ +| , m_listen_handle(std::move(ls)) | │ │ │ │ │ +|{ | │ │ │ │ │ +|#if TORRENT_USE_SSL | │ │ │ │ │ +| m_ssl_ctx.set_verify_mode(ssl::context::verify_none); | │ │ │ │ │ +|#endif | │ │ │ │ │ +|} | │ │ │ │ │ +| | │ │ │ │ │ +|void upnp::start() | │ │ │ │ │ +|_{_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _2_|_._._/_s_r_c_/_a_l_e_r_t___m_a_n_a_g_e_r_._c_p_p_:_8_0_ _ _ _|_k_e_e_p_ _a_ _c_o_u_n_t_ _o_f_ _t_h_e_ _n_u_m_b_e_r_ _o_f_ _t_h_r_e_a_d_s_ _w_a_i_t_i_n_g_._ _O_n_l_y_ _i_f_ _i_t_'_s_ _>_ _0_ _n_o_t_i_f_y_ _t_h_e_m_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** kkeeeepp aa ccoouunntt ooff tthhee nnuummbbeerr ooff tthhrreeaaddss wwaaiittiinngg.. OOnnllyy iiff iitt''ss >> 00 nnoottiiffyy tthheemm ********** | │ │ │ │ │ +|****** ....//ssrrcc//aalleerrtt__mmaannaaggeerr..ccpppp::8800 ****** | │ │ │ │ │ +|return m_alerts[m_generation].front(); | │ │ │ │ │ +| | │ │ │ │ │ +| // this call can be interrupted prematurely by other signals | │ │ │ │ │ +| m_condition.wait_for(lock, max_wait); | │ │ │ │ │ +| if (!m_alerts[m_generation].empty()) | │ │ │ │ │ +| return m_alerts[m_generation].front(); | │ │ │ │ │ +| | │ │ │ │ │ +| return nullptr; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| void alert_manager::maybe_notify(alert* a) | │ │ │ │ │ | { | │ │ │ │ │ -| // the actual value | │ │ │ │ │ -| std::unique_ptr value; | │ │ │ │ │ -| // this counts the number of IPs we have seen | │ │ │ │ │ -| // announcing this item, this is used to determine | │ │ │ │ │ -| // popularity if we reach the limit of items to store | │ │ │ │ │ -| bloom_filter<128> ips; | │ │ │ │ │ -| // the last time we heard about this item | │ │ │ │ │ -| // the correct interpretation of this field | │ │ │ │ │ -| // requires a time reference | │ │ │ │ │ -| time_point last_seen; | │ │ │ │ │ -| // number of IPs in the bloom filter | │ │ │ │ │ -| int num_announcers = 0; | │ │ │ │ │ -| // size of malloced space pointed to by value | │ │ │ │ │ -| int size = 0; | │ │ │ │ │ -| }; | │ │ │ │ │ +| if (m_alerts[m_generation].size() == 1) | │ │ │ │ │ +| { | │ │ │ │ │ +| // we just posted to an empty queue. If anyone is waiting for | │ │ │ │ │ +| // alerts, we need to notify them. Also (potentially) call the | │ │ │ │ │ +| // user supplied m_notify callback to let the client wake up its | │ │ │ │ │ +| // message loop to poll for alerts. | │ │ │ │ │ +| if (m_notify) m_notify(); | │ │ │ │ │ | | │ │ │ │ │ -| struct dht_mutable_item : dht_immutable_item | │ │ │ │ │ +|m_condition.notify_all(); | │ │ │ │ │ +|} | │ │ │ │ │ +| | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_EXTENSIONS | │ │ │ │ │ +| for (auto& e : m_ses_extensions) | │ │ │ │ │ +| e->on_alert(a); | │ │ │ │ │ +|#else | │ │ │ │ │ +| TORRENT_UNUSED(a); | │ │ │ │ │ +|#endif | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| void alert_manager::set_notify_function(std::function const& fun) | │ │ │ │ │ | { | │ │ │ │ │ -| signature sig{}; | │ │ │ │ │ -| sequence_number seq{}; | │ │ │ │ │ -| public_key key{}; | │ │ │ │ │ -| std::string salt; | │ │ │ │ │ -| }; | │ │ │ │ │ +| std::unique_lock lock(m_mutex); | │ │ │ │ │ +| m_notify = fun; | │ │ │ │ │ +| if (!m_alerts[m_generation].empty()) | │ │ │ │ │ +| { | │ │ │ │ │ +| if (m_notify) m_notify(); | │ │ │ │ │ +| } | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -| void set_value(dht_immutable_item& item, span buf) | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_EXTENSIONS | │ │ │ │ │ +| void alert_manager::add_extension(std::shared_ptr ext) | │ │ │ │ │ | { | │ │ │ │ │ -|_ _ _i_n_t_ _c_o_n_s_t_ _s_i_z_e_ _=_ _i_n_t_(_b_u_f_._s_i_z_e_(_)_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +| m_ses_extensions.push_back(ext); | │ │ │ │ │ +| } | │ │ │ │ │ +|#endif | │ │ │ │ │ +| | │ │ │ │ │ +| void alert_manager::get_all(std::vector& alerts) | │ │ │ │ │ +| { | │ │ │ │ │ +|_ _ _s_t_d_:_:_l_o_c_k___g_u_a_r_d_<_s_t_d_:_:_r_e_c_u_r_s_i_v_e___m_u_t_e_x_>_ _l_o_c_k_(_m___m_u_t_e_x_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |_r_e_l_e_v_a_n_c_e_ _2_|_._._/_s_r_c_/_k_a_d_e_m_l_i_a_/_n_o_d_e_._c_p_p_:_6_8_4_ _ _|_i_t_ _w_o_u_l_d_ _b_e_ _n_i_c_e_ _t_o_ _h_a_v_e_ _a_ _b_i_a_s_ _t_o_w_a_r_d_s_ _n_o_d_e_-_i_d_ _p_r_e_f_i_x_e_s_ _t_h_a_t_ _a_r_e_ _m_i_s_s_i_n_g_ _i_n_ _t_h_e_ _b_u_c_k_e_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** iitt wwoouulldd bbee nniiccee ttoo hhaavvee aa bbiiaass ttoowwaarrddss nnooddee--iidd pprreeffiixxeess tthhaatt aarree mmiissssiinngg iinn tthhee bbuucckkeett ********** | │ │ │ │ │ |****** ....//ssrrcc//kkaaddeemmlliiaa//nnooddee..ccpppp::668844 ****** | │ │ │ │ │ |node_entry const* ne = m_table.next_refresh(); | │ │ │ │ │ | if (ne == nullptr) return; | │ │ │ │ │ | | │ │ │ │ │ | // this shouldn't happen | │ │ │ │ │ @@ -4227,69 +4172,69 @@ │ │ │ │ │ | { | │ │ │ │ │ | // this entry belongs in the new bucket | │ │ │ │ │ | if (j->pinged() && int(new_bucket.size()) < new_bucket_size) | │ │ │ │ │ | new_bucket.push_back(*j); | │ │ │ │ │ | else | │ │ │ │ │ | new_replacement_bucket.push_back(*j); | │ │ │ │ │ |_ _ _}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 2|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |add async_connect() that takes a hostname and port as well | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_s_o_c_k_s_5___s_t_r_e_a_m_._h_p_p_:_1_5_3_ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** aadddd aassyynncc__ccoonnnneecctt(()) tthhaatt ttaakkeess aa hhoossttnnaammee aanndd ppoorrtt aass wweellll ********** | │ │ │ │ │ -|****** ....//iinncclluuddee//lliibbttoorrrreenntt//ssoocckkss55__ssttrreeaamm..hhpppp::115533 ****** | │ │ │ │ │ -|TORRENT_ASSERT(!aux::is_ip_address(host)); | │ │ │ │ │ -| m_dst_name = host; | │ │ │ │ │ -| if (m_dst_name.size() > 255) | │ │ │ │ │ -| m_dst_name.resize(255); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| void close(error_code& ec) | │ │ │ │ │ -| { | │ │ │ │ │ -| m_dst_name.clear(); | │ │ │ │ │ -| proxy_base::close(ec); | │ │ │ │ │ -| } | │ │ │ │ │ +|relevance 2|_._._/_s_r_c_/_k_a_d_e_m_l_i_a_/ |make this configurable in dht_settings | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_d_h_t___s_t_o_r_a_g_e_._c_p_p_:_8_7_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** mmaakkee tthhiiss ccoonnffiigguurraabbllee iinn ddhhtt__sseettttiinnggss ********** | │ │ │ │ │ +|****** ....//ssrrcc//kkaaddeemmlliiaa//ddhhtt__ssttoorraaggee..ccpppp::8877 ****** | │ │ │ │ │ +|tcp::endpoint addr; | │ │ │ │ │ +| bool seed = 0; | │ │ │ │ │ +| }; | │ │ │ │ │ | | │ │ │ │ │ -|#ifndef BOOST_NO_EXCEPTIONS | │ │ │ │ │ -| void close() | │ │ │ │ │ +| // internal | │ │ │ │ │ +| bool operator<(peer_entry const& lhs, peer_entry const& rhs) | │ │ │ │ │ | { | │ │ │ │ │ -| m_dst_name.clear(); | │ │ │ │ │ -| proxy_base::close(); | │ │ │ │ │ +| return lhs.addr.address() == rhs.addr.address() | │ │ │ │ │ +| ? lhs.addr.port() < rhs.addr.port() | │ │ │ │ │ +| : lhs.addr.address() < rhs.addr.address(); | │ │ │ │ │ | } | │ │ │ │ │ -|#endif | │ │ │ │ │ | | │ │ │ │ │ -|template | │ │ │ │ │ -|void async_connect(endpoint_type const& endpoint, Handler handler) | │ │ │ │ │ +| // this is a group. It contains a set of group members | │ │ │ │ │ +| struct torrent_entry | │ │ │ │ │ | { | │ │ │ │ │ -| // make sure we don't try to connect to INADDR_ANY. binding is fine, | │ │ │ │ │ -| // and using a hostname is fine on SOCKS version 5. | │ │ │ │ │ -| TORRENT_ASSERT(endpoint.address() != address() | │ │ │ │ │ -| || (!m_dst_name.empty() && m_version == 5)); | │ │ │ │ │ -| | │ │ │ │ │ -| m_remote_endpoint = endpoint; | │ │ │ │ │ +| std::string name; | │ │ │ │ │ +| std::vector peers4; | │ │ │ │ │ +| std::vector peers6; | │ │ │ │ │ +| }; | │ │ │ │ │ | | │ │ │ │ │ -| // the connect is split up in the following steps: | │ │ │ │ │ -| // 1. resolve name of proxy server | │ │ │ │ │ -| // 2. connect to proxy server | │ │ │ │ │ -| // 3. if version == 5: | │ │ │ │ │ -| // 3.1 send SOCKS5 authentication method message | │ │ │ │ │ -| // 3.2 read SOCKS5 authentication response | │ │ │ │ │ -| // 3.3 send username+password | │ │ │ │ │ -| // 4. send SOCKS command message | │ │ │ │ │ +|constexpr time_duration announce_interval = minutes(30); | │ │ │ │ │ | | │ │ │ │ │ -| ADD_OUTSTANDING_ASYNC("socks5_stream::name_lookup"); | │ │ │ │ │ -| m_resolver.async_resolve(m_hostname, to_string(m_port).data(), wrap_allocator( | │ │ │ │ │ -| [this](error_code const& ec, tcp::resolver::results_type ips, Handler hn) { | │ │ │ │ │ -| name_lookup(ec, std::move(ips), std::move(hn)); | │ │ │ │ │ -| }, std::move(handler))); | │ │ │ │ │ -| } | │ │ │ │ │ +| struct dht_immutable_item | │ │ │ │ │ +| { | │ │ │ │ │ +| // the actual value | │ │ │ │ │ +| std::unique_ptr value; | │ │ │ │ │ +| // this counts the number of IPs we have seen | │ │ │ │ │ +| // announcing this item, this is used to determine | │ │ │ │ │ +| // popularity if we reach the limit of items to store | │ │ │ │ │ +| bloom_filter<128> ips; | │ │ │ │ │ +| // the last time we heard about this item | │ │ │ │ │ +| // the correct interpretation of this field | │ │ │ │ │ +| // requires a time reference | │ │ │ │ │ +| time_point last_seen; | │ │ │ │ │ +| // number of IPs in the bloom filter | │ │ │ │ │ +| int num_announcers = 0; | │ │ │ │ │ +| // size of malloced space pointed to by value | │ │ │ │ │ +| int size = 0; | │ │ │ │ │ +| }; | │ │ │ │ │ | | │ │ │ │ │ -|private: | │ │ │ │ │ +| struct dht_mutable_item : dht_immutable_item | │ │ │ │ │ +| { | │ │ │ │ │ +| signature sig{}; | │ │ │ │ │ +| sequence_number seq{}; | │ │ │ │ │ +| public_key key{}; | │ │ │ │ │ +| std::string salt; | │ │ │ │ │ +| }; | │ │ │ │ │ | | │ │ │ │ │ -| template | │ │ │ │ │ -| void name_lookup(error_code const& e, tcp::resolver::results_type ips | │ │ │ │ │ -|_ _ _,_ _H_a_n_d_l_e_r_ _h_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +| void set_value(dht_immutable_item& item, span buf) | │ │ │ │ │ +| { | │ │ │ │ │ +|_ _ _i_n_t_ _c_o_n_s_t_ _s_i_z_e_ _=_ _i_n_t_(_b_u_f_._s_i_z_e_(_)_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |relevance 2|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |use the resolver interface that has a built-in cache | │ │ │ │ │ |_ _ _ _ _ _ _ _ _ _ _ _|_p_r_o_x_y___b_a_s_e_._h_p_p_:_2_9_8_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** uussee tthhee rreessoollvveerr iinntteerrffaaccee tthhaatt hhaass aa bbuuiilltt--iinn ccaacchhee ********** | │ │ │ │ │ |****** ....//iinncclluuddee//lliibbttoorrrreenntt//pprrooxxyy__bbaassee..hhpppp::229988 ****** | │ │ │ │ │ |protected: | │ │ │ │ │ | | │ │ │ │ │ | // The handler must be taken as lvalue reference here since we may not call | │ │ │ │ │ @@ -4391,14 +4336,124 @@ │ │ │ │ │ | } | │ │ │ │ │ | sock.bind(bind_ep, ec); | │ │ │ │ │ | return bind_ep.address(); | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ | // returns the device name whose local address is ``addr``. If | │ │ │ │ │ |_ _/_/_ _n_o_ _s_u_c_h_ _d_e_v_i_c_e_ _i_s_ _f_o_u_n_d_,_ _a_n_ _e_m_p_t_y_ _s_t_r_i_n_g_ _i_s_ _r_e_t_u_r_n_e_d_._ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 2|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |having 8 priority levels is probably excessive. It should probably be changed to 3 levels + dont-download | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_p_i_e_c_e___p_i_c_k_e_r_._h_p_p_:_6_4_7_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** hhaavviinngg 88 pprriioorriittyy lleevveellss iiss pprroobbaabbllyy eexxcceessssiivvee.. IItt sshhoouulldd pprroobbaabbllyy bbee cchhaannggeedd ttoo 33 lleevveellss ++ ddoonntt--ddoowwnnllooaadd ********** | │ │ │ │ │ +|****** ....//iinncclluuddee//lliibbttoorrrreenntt//ppiieeccee__ppiicckkeerr..hhpppp::664477 ****** | │ │ │ │ │ +|else if (state() == piece_full) | │ │ │ │ │ +| state(piece_full_reverse); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| // the number of peers that has this piece | │ │ │ │ │ +| // (availability) | │ │ │ │ │ +| std::uint32_t peer_count : 26; | │ │ │ │ │ +| | │ │ │ │ │ +| // one of the download_queue_t values. This indicates whether this piece | │ │ │ │ │ +| // is currently being downloaded or not, and what state it's in if | │ │ │ │ │ +| // it is. Specifically, as an optimization, pieces that have all blocks | │ │ │ │ │ +| // requested from them are separated out into separate lists to make | │ │ │ │ │ +| // lookups quicker. The main oddity is that whether a downloading piece | │ │ │ │ │ +| // has only been requested from peers that are reverse, that's | │ │ │ │ │ +| // recorded as piece_downloading_reverse, which really means the same | │ │ │ │ │ +| // as piece_downloading, it just saves space to also indicate that it | │ │ │ │ │ +| // has a bit lower priority. The reverse bit is only relevant if the | │ │ │ │ │ +| // state is piece_downloading. | │ │ │ │ │ +| std::uint32_t download_state : 3; | │ │ │ │ │ +| | │ │ │ │ │ +| | │ │ │ │ │ +|// is 0 if the piece is filtered (not to be downloaded) | │ │ │ │ │ +| // 1 is low priority | │ │ │ │ │ +| // 2 is low priority | │ │ │ │ │ +| // 3 is mid priority | │ │ │ │ │ +| // 4 is default priority | │ │ │ │ │ +| // 5 is mid priority | │ │ │ │ │ +| // 6 is high priority | │ │ │ │ │ +| // 7 is high priority | │ │ │ │ │ +| std::uint32_t piece_priority : 3; | │ │ │ │ │ +| | │ │ │ │ │ +| // index in to the piece_info vector | │ │ │ │ │ +| prio_index_t index; | │ │ │ │ │ +| | │ │ │ │ │ +|#ifdef TORRENT_DEBUG_REFCOUNTS | │ │ │ │ │ +| // all the peers that have this piece | │ │ │ │ │ +| std::set have_peers; | │ │ │ │ │ +|#endif | │ │ │ │ │ +| | │ │ │ │ │ +| // index is set to this to indicate that we have the | │ │ │ │ │ +| // piece. There is no entry for the piece in the | │ │ │ │ │ +| // buckets if this is the case. | │ │ │ │ │ +| static constexpr prio_index_t we_have_index{-1}; | │ │ │ │ │ +| | │ │ │ │ │ +| // the priority value that means the piece is filtered | │ │ │ │ │ +| static constexpr std::uint32_t filter_priority = 0; | │ │ │ │ │ +| | │ │ │ │ │ +| // the max number the peer count can hold | │ │ │ │ │ +| static constexpr std::uint32_t max_peer_count = 0xffff; | │ │ │ │ │ +| | │ │ │ │ │ +|_ _ _ _b_o_o_l_ _h_a_v_e_(_)_ _c_o_n_s_t_ _{_ _r_e_t_u_r_n_ _i_n_d_e_x_ _=_=_ _w_e___h_a_v_e___i_n_d_e_x_;_ _}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 2|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |add async_connect() that takes a hostname and port as well | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_s_o_c_k_s_5___s_t_r_e_a_m_._h_p_p_:_1_5_3_ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** aadddd aassyynncc__ccoonnnneecctt(()) tthhaatt ttaakkeess aa hhoossttnnaammee aanndd ppoorrtt aass wweellll ********** | │ │ │ │ │ +|****** ....//iinncclluuddee//lliibbttoorrrreenntt//ssoocckkss55__ssttrreeaamm..hhpppp::115533 ****** | │ │ │ │ │ +|TORRENT_ASSERT(!aux::is_ip_address(host)); | │ │ │ │ │ +| m_dst_name = host; | │ │ │ │ │ +| if (m_dst_name.size() > 255) | │ │ │ │ │ +| m_dst_name.resize(255); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| void close(error_code& ec) | │ │ │ │ │ +| { | │ │ │ │ │ +| m_dst_name.clear(); | │ │ │ │ │ +| proxy_base::close(ec); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +|#ifndef BOOST_NO_EXCEPTIONS | │ │ │ │ │ +| void close() | │ │ │ │ │ +| { | │ │ │ │ │ +| m_dst_name.clear(); | │ │ │ │ │ +| proxy_base::close(); | │ │ │ │ │ +| } | │ │ │ │ │ +|#endif | │ │ │ │ │ +| | │ │ │ │ │ +|template | │ │ │ │ │ +|void async_connect(endpoint_type const& endpoint, Handler handler) | │ │ │ │ │ +| { | │ │ │ │ │ +| // make sure we don't try to connect to INADDR_ANY. binding is fine, | │ │ │ │ │ +| // and using a hostname is fine on SOCKS version 5. | │ │ │ │ │ +| TORRENT_ASSERT(endpoint.address() != address() | │ │ │ │ │ +| || (!m_dst_name.empty() && m_version == 5)); | │ │ │ │ │ +| | │ │ │ │ │ +| m_remote_endpoint = endpoint; | │ │ │ │ │ +| | │ │ │ │ │ +| // the connect is split up in the following steps: | │ │ │ │ │ +| // 1. resolve name of proxy server | │ │ │ │ │ +| // 2. connect to proxy server | │ │ │ │ │ +| // 3. if version == 5: | │ │ │ │ │ +| // 3.1 send SOCKS5 authentication method message | │ │ │ │ │ +| // 3.2 read SOCKS5 authentication response | │ │ │ │ │ +| // 3.3 send username+password | │ │ │ │ │ +| // 4. send SOCKS command message | │ │ │ │ │ +| | │ │ │ │ │ +| ADD_OUTSTANDING_ASYNC("socks5_stream::name_lookup"); | │ │ │ │ │ +| m_resolver.async_resolve(m_hostname, to_string(m_port).data(), wrap_allocator( | │ │ │ │ │ +| [this](error_code const& ec, tcp::resolver::results_type ips, Handler hn) { | │ │ │ │ │ +| name_lookup(ec, std::move(ips), std::move(hn)); | │ │ │ │ │ +| }, std::move(handler))); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +|private: | │ │ │ │ │ +| | │ │ │ │ │ +| template | │ │ │ │ │ +| void name_lookup(error_code const& e, tcp::resolver::results_type ips | │ │ │ │ │ +|_ _ _,_ _H_a_n_d_l_e_r_ _h_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |relevance 2|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |this should really be a circular buffer | │ │ │ │ │ |_ _ _ _ _ _ _ _ _ _ _ _|_p_e_e_r___c_o_n_n_e_c_t_i_o_n_._h_p_p_:_9_9_6_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** tthhiiss sshhoouulldd rreeaallllyy bbee aa cciirrccuullaarr bbuuffffeerr ********** | │ │ │ │ │ |****** ....//iinncclluuddee//lliibbttoorrrreenntt//ppeeeerr__ccoonnnneeccttiioonn..hhpppp::999966 ****** | │ │ │ │ │ |// it just serves as a queue to remember what we've sent, to avoid | │ │ │ │ │ | // re-sending suggests for the same piece | │ │ │ │ │ | // i.e. outgoing suggest pieces | │ │ │ │ │ @@ -4498,69 +4553,69 @@ │ │ │ │ │ | // and false if we got an incoming connection | │ │ │ │ │ | // could be considered: true = local, false = remote | │ │ │ │ │ | bool m_outgoing:1; | │ │ │ │ │ | | │ │ │ │ │ | // is true if we learn the incoming connections listening | │ │ │ │ │ | // during the extended handshake | │ │ │ │ │ |_ _ _b_o_o_l_ _m___r_e_c_e_i_v_e_d___l_i_s_t_e_n___p_o_r_t_:_1_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 2|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |having 8 priority levels is probably excessive. It should probably be changed to 3 levels + dont-download | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_p_i_e_c_e___p_i_c_k_e_r_._h_p_p_:_6_4_7_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** hhaavviinngg 88 pprriioorriittyy lleevveellss iiss pprroobbaabbllyy eexxcceessssiivvee.. IItt sshhoouulldd pprroobbaabbllyy bbee cchhaannggeedd ttoo 33 lleevveellss ++ ddoonntt--ddoowwnnllooaadd ********** | │ │ │ │ │ -|****** ....//iinncclluuddee//lliibbttoorrrreenntt//ppiieeccee__ppiicckkeerr..hhpppp::664477 ****** | │ │ │ │ │ -|else if (state() == piece_full) | │ │ │ │ │ -| state(piece_full_reverse); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| // the number of peers that has this piece | │ │ │ │ │ -| // (availability) | │ │ │ │ │ -| std::uint32_t peer_count : 26; | │ │ │ │ │ +|relevance 2|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/_a_u_x___/ |this type should probably be renamed to send_buffer | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_c_h_a_i_n_e_d___b_u_f_f_e_r_._h_p_p_:_6_0_ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tthhiiss ttyyppee sshhoouulldd pprroobbaabbllyy bbee rreennaammeedd ttoo sseenndd__bbuuffffeerr ********** | │ │ │ │ │ +|****** ....//iinncclluuddee//lliibbttoorrrreenntt//aauuxx__//cchhaaiinneedd__bbuuffffeerr..hhpppp::6600 ****** | │ │ │ │ │ +|#include "libtorrent/aux_/buffer.hpp" | │ │ │ │ │ | | │ │ │ │ │ -| // one of the download_queue_t values. This indicates whether this piece | │ │ │ │ │ -| // is currently being downloaded or not, and what state it's in if | │ │ │ │ │ -| // it is. Specifically, as an optimization, pieces that have all blocks | │ │ │ │ │ -| // requested from them are separated out into separate lists to make | │ │ │ │ │ -| // lookups quicker. The main oddity is that whether a downloading piece | │ │ │ │ │ -| // has only been requested from peers that are reverse, that's | │ │ │ │ │ -| // recorded as piece_downloading_reverse, which really means the same | │ │ │ │ │ -| // as piece_downloading, it just saves space to also indicate that it | │ │ │ │ │ -| // has a bit lower priority. The reverse bit is only relevant if the | │ │ │ │ │ -| // state is piece_downloading. | │ │ │ │ │ -| std::uint32_t download_state : 3; | │ │ │ │ │ +|#include | │ │ │ │ │ +|#include | │ │ │ │ │ | | │ │ │ │ │ +|#include "libtorrent/aux_/disable_warnings_push.hpp" | │ │ │ │ │ +|#include | │ │ │ │ │ +|#include "libtorrent/aux_/disable_warnings_pop.hpp" | │ │ │ │ │ | | │ │ │ │ │ -|// is 0 if the piece is filtered (not to be downloaded) | │ │ │ │ │ -| // 1 is low priority | │ │ │ │ │ -| // 2 is low priority | │ │ │ │ │ -| // 3 is mid priority | │ │ │ │ │ -| // 4 is default priority | │ │ │ │ │ -| // 5 is mid priority | │ │ │ │ │ -| // 6 is high priority | │ │ │ │ │ -| // 7 is high priority | │ │ │ │ │ -| std::uint32_t piece_priority : 3; | │ │ │ │ │ +|#ifdef _MSC_VER | │ │ │ │ │ +|// visual studio requires the value in a deque to be copyable. C++11 | │ │ │ │ │ +|// has looser requirements depending on which functions are actually used. | │ │ │ │ │ +|#define TORRENT_CPP98_DEQUE 1 | │ │ │ │ │ +|#else | │ │ │ │ │ +|#define TORRENT_CPP98_DEQUE 0 | │ │ │ │ │ +|#endif | │ │ │ │ │ | | │ │ │ │ │ -| // index in to the piece_info vector | │ │ │ │ │ -| prio_index_t index; | │ │ │ │ │ +|namespace libtorrent { | │ │ │ │ │ +|namespace aux { | │ │ │ │ │ | | │ │ │ │ │ -|#ifdef TORRENT_DEBUG_REFCOUNTS | │ │ │ │ │ -| // all the peers that have this piece | │ │ │ │ │ -| std::set have_peers; | │ │ │ │ │ +|struct TORRENT_EXTRA_EXPORT chained_buffer : private single_threaded | │ │ │ │ │ +|{ | │ │ │ │ │ +| chained_buffer(): m_bytes(0), m_capacity(0) | │ │ │ │ │ +| { | │ │ │ │ │ +| thread_started(); | │ │ │ │ │ +|#if TORRENT_USE_ASSERTS | │ │ │ │ │ +| m_destructed = false; | │ │ │ │ │ |#endif | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -| // index is set to this to indicate that we have the | │ │ │ │ │ -| // piece. There is no entry for the piece in the | │ │ │ │ │ -| // buckets if this is the case. | │ │ │ │ │ -| static constexpr prio_index_t we_have_index{-1}; | │ │ │ │ │ -| | │ │ │ │ │ -| // the priority value that means the piece is filtered | │ │ │ │ │ -| static constexpr std::uint32_t filter_priority = 0; | │ │ │ │ │ +| private: | │ │ │ │ │ | | │ │ │ │ │ -| // the max number the peer count can hold | │ │ │ │ │ -| static constexpr std::uint32_t max_peer_count = 0xffff; | │ │ │ │ │ +| // destructs/frees the holder object | │ │ │ │ │ +| using destruct_holder_fun = void (*)(void*); | │ │ │ │ │ +| using move_construct_holder_fun = void (*)(void*, void*); | │ │ │ │ │ | | │ │ │ │ │ -|_ _ _ _b_o_o_l_ _h_a_v_e_(_)_ _c_o_n_s_t_ _{_ _r_e_t_u_r_n_ _i_n_d_e_x_ _=_=_ _w_e___h_a_v_e___i_n_d_e_x_;_ _}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +| struct buffer_t | │ │ │ │ │ +| { | │ │ │ │ │ +| buffer_t() {} | │ │ │ │ │ +|#if TORRENT_CPP98_DEQUE | │ │ │ │ │ +| buffer_t(buffer_t&& rhs) noexcept | │ │ │ │ │ +| { | │ │ │ │ │ +| destruct_holder = rhs.destruct_holder; | │ │ │ │ │ +| move_holder = rhs.move_holder; | │ │ │ │ │ +| buf = rhs.buf; | │ │ │ │ │ +| size = rhs.size; | │ │ │ │ │ +| used_size = rhs.used_size; | │ │ │ │ │ +| move_holder(&holder, &rhs.holder); | │ │ │ │ │ +| } | │ │ │ │ │ +| buffer_t& operator=(buffer_t&& rhs) & noexcept | │ │ │ │ │ +|_ _ _ _{_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |relevance 2|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/_a_u_x___/ |make this interface a lot smaller. It could be split up into several smaller interfaces. Each subsystem could then limit the size of| │ │ │ │ │ |_ _ _ _ _ _ _ _ _ _ _ _|_s_e_s_s_i_o_n___i_n_t_e_r_f_a_c_e_._h_p_p_:_1_2_7_ _ _ _ _ _|_t_h_e_ _m_o_c_k_ _o_b_j_e_c_t_ _t_o_ _t_e_s_t_ _i_t_._ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** mmaakkee tthhiiss iinntteerrffaaccee aa lloott ssmmaalllleerr.. IItt ccoouulldd bbee sspplliitt uupp iinnttoo sseevveerraall ssmmaalllleerr iinntteerrffaacceess.. EEaacchh ssuubbssyysstteemm ccoouulldd tthheenn lliimmiitt tthhee ssiizzee ooff tthhee mmoocckk oobbjjeecctt ttoo tteesstt iitt.. ********** | │ │ │ │ │ |****** ....//iinncclluuddee//lliibbttoorrrreenntt//aauuxx__//sseessssiioonn__iinntteerrffaaccee..hhpppp::112277 ****** | │ │ │ │ │ |// a release build with logging disabled (which is the default) will | │ │ │ │ │ | // not have this class at all | │ │ │ │ │ | struct TORRENT_EXTRA_EXPORT session_logger | │ │ │ │ │ @@ -4636,69 +4691,68 @@ │ │ │ │ │ | | │ │ │ │ │ | virtual void remove_torrent(torrent_handle const& h, remove_flags_t options = {}) = 0; | │ │ │ │ │ | virtual void remove_torrent_impl(std::shared_ptr tptr, remove_flags_t options) = 0; | │ │ │ │ │ | | │ │ │ │ │ | // port filter | │ │ │ │ │ | virtual port_filter const& get_port_filter() const = 0; | │ │ │ │ │ |_ _ _v_i_r_t_u_a_l_ _v_o_i_d_ _b_a_n___i_p_(_a_d_d_r_e_s_s_ _a_d_d_r_)_ _=_ _0_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 2|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/_a_u_x___/ |this type should probably be renamed to send_buffer | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_c_h_a_i_n_e_d___b_u_f_f_e_r_._h_p_p_:_6_0_ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tthhiiss ttyyppee sshhoouulldd pprroobbaabbllyy bbee rreennaammeedd ttoo sseenndd__bbuuffffeerr ********** | │ │ │ │ │ -|****** ....//iinncclluuddee//lliibbttoorrrreenntt//aauuxx__//cchhaaiinneedd__bbuuffffeerr..hhpppp::6600 ****** | │ │ │ │ │ -|#include "libtorrent/aux_/buffer.hpp" | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _1_|_._._/_s_r_c_/_s_e_s_s_i_o_n___i_m_p_l_._c_p_p_:_5_7_0_5_ _ _|_r_e_p_o_r_t_ _t_h_e_ _p_r_o_p_e_r_ _a_d_d_r_e_s_s_ _o_f_ _t_h_e_ _r_o_u_t_e_r_ _a_s_ _t_h_e_ _s_o_u_r_c_e_ _I_P_ _o_f_ _t_h_i_s_ _v_o_t_e_ _o_f_ _o_u_r_ _e_x_t_e_r_n_a_l_ _a_d_d_r_e_s_s_,_ _i_n_s_t_e_a_d_ _o_f_ _t_h_e_ _e_m_p_t_y_ _a_d_d_r_e_s_s_ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** rreeppoorrtt tthhee pprrooppeerr aaddddrreessss ooff tthhee rroouutteerr aass tthhee ssoouurrccee IIPP ooff tthhiiss vvoottee ooff oouurr eexxtteerrnnaall aaddddrreessss,, iinnsstteeaadd ooff tthhee eemmppttyy aaddddrreessss ********** | │ │ │ │ │ +|****** ....//ssrrcc//sseessssiioonn__iimmppll..ccpppp::55770055 ****** | │ │ │ │ │ +|, listen_socket_handle const& ls) | │ │ │ │ │ +| { | │ │ │ │ │ +| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ | | │ │ │ │ │ -|#include | │ │ │ │ │ -|#include | │ │ │ │ │ +| listen_socket_t* listen_socket = ls.get(); | │ │ │ │ │ | | │ │ │ │ │ -|#include "libtorrent/aux_/disable_warnings_push.hpp" | │ │ │ │ │ -|#include | │ │ │ │ │ -|#include "libtorrent/aux_/disable_warnings_pop.hpp" | │ │ │ │ │ +| // NOTE: don't assume that if ec != 0, the rest of the logic | │ │ │ │ │ +| // is not necessary, the ports still need to be set, in other | │ │ │ │ │ +| // words, don't early return without careful review of the | │ │ │ │ │ +| // remaining logic | │ │ │ │ │ +| if (ec && m_alerts.should_post()) | │ │ │ │ │ +| { | │ │ │ │ │ +| m_alerts.emplace_alert(mapping | │ │ │ │ │ +| , transport, ec, listen_socket ? listen_socket->local_endpoint.address() : address()); | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -|#ifdef _MSC_VER | │ │ │ │ │ -|// visual studio requires the value in a deque to be copyable. C++11 | │ │ │ │ │ -|// has looser requirements depending on which functions are actually used. | │ │ │ │ │ -|#define TORRENT_CPP98_DEQUE 1 | │ │ │ │ │ -|#else | │ │ │ │ │ -|#define TORRENT_CPP98_DEQUE 0 | │ │ │ │ │ -|#endif | │ │ │ │ │ +| if (!listen_socket) return; | │ │ │ │ │ | | │ │ │ │ │ -|namespace libtorrent { | │ │ │ │ │ -|namespace aux { | │ │ │ │ │ +| if (!ec && !external_ip.is_unspecified()) | │ │ │ │ │ +| { | │ │ │ │ │ +|listen_socket->external_address.cast_vote(external_ip, source_router, address()); | │ │ │ │ │ +|} | │ │ │ │ │ | | │ │ │ │ │ -|struct TORRENT_EXTRA_EXPORT chained_buffer : private single_threaded | │ │ │ │ │ -|{ | │ │ │ │ │ -| chained_buffer(): m_bytes(0), m_capacity(0) | │ │ │ │ │ +| // need to check whether this mapping is for one of session ports (it could also be a user mapping) | │ │ │ │ │ +| if ((proto == portmap_protocol::tcp) && (listen_socket->tcp_port_mapping[transport].mapping == mapping)) | │ │ │ │ │ +| listen_socket->tcp_port_mapping[transport].port = port; | │ │ │ │ │ +| else if ((proto == portmap_protocol::udp) && (listen_socket->udp_port_mapping[transport].mapping == mapping)) | │ │ │ │ │ +| listen_socket->udp_port_mapping[transport].port = port; | │ │ │ │ │ +| | │ │ │ │ │ +| if (!ec && m_alerts.should_post()) | │ │ │ │ │ | { | │ │ │ │ │ -| thread_started(); | │ │ │ │ │ -|#if TORRENT_USE_ASSERTS | │ │ │ │ │ -| m_destructed = false; | │ │ │ │ │ -|#endif | │ │ │ │ │ +| m_alerts.emplace_alert(mapping, port | │ │ │ │ │ +| , transport, proto, listen_socket->local_endpoint.address()); | │ │ │ │ │ | } | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -| private: | │ │ │ │ │ +|#if TORRENT_ABI_VERSION == 1 | │ │ │ │ │ +| session_status session_impl::status() const | │ │ │ │ │ +| { | │ │ │ │ │ +|// INVARIANT_CHECK; | │ │ │ │ │ +| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ | | │ │ │ │ │ -| // destructs/frees the holder object | │ │ │ │ │ -| using destruct_holder_fun = void (*)(void*); | │ │ │ │ │ -| using move_construct_holder_fun = void (*)(void*, void*); | │ │ │ │ │ +| session_status s; | │ │ │ │ │ | | │ │ │ │ │ -| struct buffer_t | │ │ │ │ │ -| { | │ │ │ │ │ -| buffer_t() {} | │ │ │ │ │ -|#if TORRENT_CPP98_DEQUE | │ │ │ │ │ -| buffer_t(buffer_t&& rhs) noexcept | │ │ │ │ │ -| { | │ │ │ │ │ -| destruct_holder = rhs.destruct_holder; | │ │ │ │ │ -| move_holder = rhs.move_holder; | │ │ │ │ │ -| buf = rhs.buf; | │ │ │ │ │ -| size = rhs.size; | │ │ │ │ │ -| used_size = rhs.used_size; | │ │ │ │ │ -| move_holder(&holder, &rhs.holder); | │ │ │ │ │ -| } | │ │ │ │ │ -| buffer_t& operator=(buffer_t&& rhs) & noexcept | │ │ │ │ │ -|_ _ _ _{_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +| s.optimistic_unchoke_counter = m_optimistic_unchoke_time_scaler; | │ │ │ │ │ +| s.unchoke_counter = m_unchoke_time_scaler; | │ │ │ │ │ +| s.num_dead_peers = int(m_undead_peers.size()); | │ │ │ │ │ +| | │ │ │ │ │ +| s.num_peers = int(m_stats_counters[counters::num_peers_connected]); | │ │ │ │ │ +| s.num_unchoked = int(m_stats_counters[counters::num_peers_up_unchoked_all]); | │ │ │ │ │ +|_ _ _s_._a_l_l_o_w_e_d___u_p_l_o_a_d___s_l_o_t_s_ _=_ _i_n_t_(_m___s_t_a_t_s___c_o_u_n_t_e_r_s_[_c_o_u_n_t_e_r_s_:_:_n_u_m___u_n_c_h_o_k_e___s_l_o_t_s_]_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ | | |make this depend on the error and on the filesystem the files are being downloaded to. If the error is no_space_left_on_device and | │ │ │ │ │ |relevance 1|_._._/_s_r_c_/_t_o_r_r_e_n_t_._c_p_p_:_1_1_2_5 |the filesystem doesn't support sparse files, only zero the priorities of the pieces that are at the tails of all files, leaving | │ │ │ │ │ |_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_e_v_e_r_y_t_h_i_n_g_ _u_p_ _t_o_ _t_h_e_ _h_i_g_h_e_s_t_ _w_r_i_t_t_e_n_ _p_i_e_c_e_ _i_n_ _e_a_c_h_ _f_i_l_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** mmaakkee tthhiiss ddeeppeenndd oonn tthhee eerrrroorr aanndd oonn tthhee ffiilleessyysstteemm tthhee ffiilleess aarree bbeeiinngg ddoowwnnllooaaddeedd ttoo.. IIff tthhee eerrrroorr iiss nnoo__ssppaaccee__lleefftt__oonn__ddeevviiccee aanndd tthhee ffiilleessyysstteemm ddooeessnn''tt ssuuppppoorrtt ssppaarrssee | │ │ │ │ │ |ffiilleess,, oonnllyy zzeerroo tthhee pprriioorriittiieess ooff tthhee ppiieecceess tthhaatt aarree aatt tthhee ttaaiillss ooff aallll ffiilleess,, lleeaavviinngg eevveerryytthhiinngg uupp ttoo tthhee hhiigghheesstt wwrriitttteenn ppiieeccee iinn eeaacchh ffiillee ********** | │ │ │ │ │ |****** ....//ssrrcc//ttoorrrreenntt..ccpppp::11112255 ****** | │ │ │ │ │ | // notify the user of the error | │ │ │ │ │ @@ -4800,68 +4854,14 @@ │ │ │ │ │ | // we need to keep the object alive during this operation | │ │ │ │ │ | m_ses.disk_thread().async_release_files(m_storage | │ │ │ │ │ | , std::bind(&torrent::on_cache_flushed, shared_from_this(), false)); | │ │ │ │ │ | m_ses.deferred_submit_jobs(); | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ |_ _ _/_/_ _t_h_i_s_ _t_o_r_r_e_n_t_ _j_u_s_t_ _c_o_m_p_l_e_t_e_d_ _d_o_w_n_l_o_a_d_s_,_ _w_h_i_c_h_ _m_e_a_n_s_ _i_t_ _w_i_l_l_ _f_a_l_l_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _1_|_._._/_s_r_c_/_s_e_s_s_i_o_n___i_m_p_l_._c_p_p_:_5_7_0_5_ _ _|_r_e_p_o_r_t_ _t_h_e_ _p_r_o_p_e_r_ _a_d_d_r_e_s_s_ _o_f_ _t_h_e_ _r_o_u_t_e_r_ _a_s_ _t_h_e_ _s_o_u_r_c_e_ _I_P_ _o_f_ _t_h_i_s_ _v_o_t_e_ _o_f_ _o_u_r_ _e_x_t_e_r_n_a_l_ _a_d_d_r_e_s_s_,_ _i_n_s_t_e_a_d_ _o_f_ _t_h_e_ _e_m_p_t_y_ _a_d_d_r_e_s_s_ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** rreeppoorrtt tthhee pprrooppeerr aaddddrreessss ooff tthhee rroouutteerr aass tthhee ssoouurrccee IIPP ooff tthhiiss vvoottee ooff oouurr eexxtteerrnnaall aaddddrreessss,, iinnsstteeaadd ooff tthhee eemmppttyy aaddddrreessss ********** | │ │ │ │ │ -|****** ....//ssrrcc//sseessssiioonn__iimmppll..ccpppp::55770055 ****** | │ │ │ │ │ -|, listen_socket_handle const& ls) | │ │ │ │ │ -| { | │ │ │ │ │ -| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ -| | │ │ │ │ │ -| listen_socket_t* listen_socket = ls.get(); | │ │ │ │ │ -| | │ │ │ │ │ -| // NOTE: don't assume that if ec != 0, the rest of the logic | │ │ │ │ │ -| // is not necessary, the ports still need to be set, in other | │ │ │ │ │ -| // words, don't early return without careful review of the | │ │ │ │ │ -| // remaining logic | │ │ │ │ │ -| if (ec && m_alerts.should_post()) | │ │ │ │ │ -| { | │ │ │ │ │ -| m_alerts.emplace_alert(mapping | │ │ │ │ │ -| , transport, ec, listen_socket ? listen_socket->local_endpoint.address() : address()); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| if (!listen_socket) return; | │ │ │ │ │ -| | │ │ │ │ │ -| if (!ec && !external_ip.is_unspecified()) | │ │ │ │ │ -| { | │ │ │ │ │ -|listen_socket->external_address.cast_vote(external_ip, source_router, address()); | │ │ │ │ │ -|} | │ │ │ │ │ -| | │ │ │ │ │ -| // need to check whether this mapping is for one of session ports (it could also be a user mapping) | │ │ │ │ │ -| if ((proto == portmap_protocol::tcp) && (listen_socket->tcp_port_mapping[transport].mapping == mapping)) | │ │ │ │ │ -| listen_socket->tcp_port_mapping[transport].port = port; | │ │ │ │ │ -| else if ((proto == portmap_protocol::udp) && (listen_socket->udp_port_mapping[transport].mapping == mapping)) | │ │ │ │ │ -| listen_socket->udp_port_mapping[transport].port = port; | │ │ │ │ │ -| | │ │ │ │ │ -| if (!ec && m_alerts.should_post()) | │ │ │ │ │ -| { | │ │ │ │ │ -| m_alerts.emplace_alert(mapping, port | │ │ │ │ │ -| , transport, proto, listen_socket->local_endpoint.address()); | │ │ │ │ │ -| } | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -|#if TORRENT_ABI_VERSION == 1 | │ │ │ │ │ -| session_status session_impl::status() const | │ │ │ │ │ -| { | │ │ │ │ │ -|// INVARIANT_CHECK; | │ │ │ │ │ -| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ -| | │ │ │ │ │ -| session_status s; | │ │ │ │ │ -| | │ │ │ │ │ -| s.optimistic_unchoke_counter = m_optimistic_unchoke_time_scaler; | │ │ │ │ │ -| s.unchoke_counter = m_unchoke_time_scaler; | │ │ │ │ │ -| s.num_dead_peers = int(m_undead_peers.size()); | │ │ │ │ │ -| | │ │ │ │ │ -| s.num_peers = int(m_stats_counters[counters::num_peers_connected]); | │ │ │ │ │ -| s.num_unchoked = int(m_stats_counters[counters::num_peers_up_unchoked_all]); | │ │ │ │ │ -|_ _ _s_._a_l_l_o_w_e_d___u_p_l_o_a_d___s_l_o_t_s_ _=_ _i_n_t_(_m___s_t_a_t_s___c_o_u_n_t_e_r_s_[_c_o_u_n_t_e_r_s_:_:_n_u_m___u_n_c_h_o_k_e___s_l_o_t_s_]_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |relevance 1|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |have one instance per possible subnet, 192.168.x.x, 10.x.x.x, etc. | │ │ │ │ │ |_ _ _ _ _ _ _ _ _ _ _ _|_i_p___v_o_t_e_r_._h_p_p_:_1_3_0_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** hhaavvee oonnee iinnssttaannccee ppeerr ppoossssiibbllee ssuubbnneett,, 119922..116688..xx..xx,, 1100..xx..xx..xx,, eettcc.. ********** | │ │ │ │ │ |****** ....//iinncclluuddee//lliibbttoorrrreenntt//iipp__vvootteerr..hhpppp::113300 ****** | │ │ │ │ │ |// stores one address for each combination of local/global and ipv4/ipv6 | │ │ │ │ │ | // use of this class should be avoided, get the IP from the appropriate | │ │ │ │ │ | // listen interface wherever possible | │ │ │ │ │ @@ -4884,14 +4884,18 @@ │ │ │ │ │ | // [n][0] = IPv4 [n][1] = IPv6 | │ │ │ │ │ |address m_addresses[2][2]; | │ │ │ │ │ |}; | │ │ │ │ │ | | │ │ │ │ │ |} | │ │ │ │ │ | | │ │ │ │ │ |_#_e_n_d_i_f_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_t_e_s_t_/ |test sending invalid requests (out of bound piece index, offsets and sizes) | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_t_e_s_t___f_a_s_t___e_x_t_e_n_s_i_o_n_._c_p_p_:_1_1_3_5_ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tteesstt sseennddiinngg iinnvvaalliidd rreeqquueessttss ((oouutt ooff bboouunndd ppiieeccee iinnddeexx,, ooffffsseettss aanndd ssiizzeess)) ********** | │ │ │ │ │ +|_**_**_**_ _.._.._//_tt_ee_ss_tt_//_tt_ee_ss_tt____ff_aa_ss_tt____ee_xx_tt_ee_nn_ss_ii_oo_nn_.._cc_pp_pp_::_11_11_33_55_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |relevance 0|_._._/_t_e_s_t_/_t_e_s_t___t_o_r_r_e_n_t___i_n_f_o_._c_p_p_:|test remap_files | │ │ │ │ │ |_ _ _ _ _ _ _ _ _ _ _ _|_4_5_9_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** tteesstt rreemmaapp__ffiilleess ********** | │ │ │ │ │ |_**_**_**_ _.._.._//_tt_ee_ss_tt_//_tt_ee_ss_tt____tt_oo_rr_rr_ee_nn_tt____ii_nn_ff_oo_.._cc_pp_pp_::_44_55_99_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |relevance 0|_._._/_t_e_s_t_/_t_e_s_t___t_o_r_r_e_n_t___i_n_f_o_._c_p_p_:|torrent with 'p' (padfile) attribute | │ │ │ │ │ |_ _ _ _ _ _ _ _ _ _ _ _|_4_6_0_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** ttoorrrreenntt wwiitthh ''pp'' ((ppaaddffiillee)) aattttrriibbuuttee ********** | │ │ │ │ │ @@ -5000,227 +5004,14 @@ │ │ │ │ │ | entry::list_type l; | │ │ │ │ │ | l.push_back(entry("http://foo.com/bar1")); | │ │ │ │ │ | l.push_back(entry("http://foo.com/bar1")); | │ │ │ │ │ | l.push_back(entry("http://foo.com/bar2")); | │ │ │ │ │ | entry const e(l); | │ │ │ │ │ | entry torrent; | │ │ │ │ │ |_ _t_o_r_r_e_n_t_[_"_u_r_l_-_l_i_s_t_"_]_ _=_ _e_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_t_e_s_t_/_t_e_s_t___t_r_a_c_k_e_r_._c_p_p_:_6_0_ _ _ _|_t_e_s_t_ _s_c_r_a_p_e_ _r_e_q_u_e_s_t_s_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tteesstt ssccrraappee rreeqquueessttss ********** | │ │ │ │ │ -|_**_**_**_ _.._.._//_tt_ee_ss_tt_//_tt_ee_ss_tt____tt_rr_aa_cc_kk_ee_rr_.._cc_pp_pp_::_66_00_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_t_e_s_t_/_t_e_s_t___t_r_a_c_k_e_r_._c_p_p_:_6_1_ _ _ _|_t_e_s_t_ _p_a_r_s_e_ _p_e_e_r_s_6_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tteesstt ppaarrssee ppeeeerrss66 ********** | │ │ │ │ │ -|_**_**_**_ _.._.._//_tt_ee_ss_tt_//_tt_ee_ss_tt____tt_rr_aa_cc_kk_ee_rr_.._cc_pp_pp_::_66_11_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_t_e_s_t_/_t_e_s_t___t_r_a_c_k_e_r_._c_p_p_:_6_2_ _ _ _|_t_e_s_t_ _p_a_r_s_e_ _t_r_a_c_k_e_r_-_i_d_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tteesstt ppaarrssee ttrraacckkeerr--iidd ********** | │ │ │ │ │ -|_**_**_**_ _.._.._//_tt_ee_ss_tt_//_tt_ee_ss_tt____tt_rr_aa_cc_kk_ee_rr_.._cc_pp_pp_::_66_22_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_t_e_s_t_/_t_e_s_t___t_r_a_c_k_e_r_._c_p_p_:_6_3_ _ _ _|_t_e_s_t_ _p_a_r_s_e_ _f_a_i_l_u_r_e_-_r_e_a_s_o_n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tteesstt ppaarrssee ffaaiilluurree--rreeaassoonn ********** | │ │ │ │ │ -|_**_**_**_ _.._.._//_tt_ee_ss_tt_//_tt_ee_ss_tt____tt_rr_aa_cc_kk_ee_rr_.._cc_pp_pp_::_66_33_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_t_e_s_t_/_t_e_s_t___t_r_a_c_k_e_r_._c_p_p_:_6_4 |test all failure paths, including invalid bencoding not a dictionary no files entry in scrape response no info-hash entry in scrape | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_r_e_s_p_o_n_s_e_ _m_a_l_f_o_r_m_e_d_ _p_e_e_r_s_ _i_n_ _p_e_e_r_ _l_i_s_t_ _o_f_ _d_i_c_t_i_o_n_a_r_i_e_s_ _u_n_e_v_e_n_ _n_u_m_b_e_r_ _o_f_ _b_y_t_e_s_ _i_n_ _p_e_e_r_s_ _a_n_d_ _p_e_e_r_s_6_ _s_t_r_i_n_g_ _r_e_s_p_o_n_s_e_s_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tteesstt aallll ffaaiilluurree ppaatthhss,, iinncclluuddiinngg iinnvvaalliidd bbeennccooddiinngg nnoott aa ddiiccttiioonnaarryy nnoo ffiilleess eennttrryy iinn ssccrraappee rreessppoonnssee nnoo iinnffoo--hhaasshh eennttrryy iinn ssccrraappee rreessppoonnssee mmaallffoorrmmeedd ppeeeerrss iinn ppeeeerr lliisstt| │ │ │ │ │ -|ooff ddiiccttiioonnaarriieess uunneevveenn nnuummbbeerr ooff bbyytteess iinn ppeeeerrss aanndd ppeeeerrss66 ssttrriinngg rreessppoonnsseess ********** | │ │ │ │ │ -|****** ....//tteesstt//tteesstt__ttrraacckkeerr..ccpppp::6644 ****** | │ │ │ │ │ -|#include "test_utils.hpp" | │ │ │ │ │ -|#include "udp_tracker.hpp" | │ │ │ │ │ -|#include "settings.hpp" | │ │ │ │ │ -|#include "test_utils.hpp" | │ │ │ │ │ -|#include "libtorrent/alert.hpp" | │ │ │ │ │ -|#include "libtorrent/peer_info.hpp" // for peer_list_entry | │ │ │ │ │ -|#include "libtorrent/alert_types.hpp" | │ │ │ │ │ -|#include "libtorrent/session.hpp" | │ │ │ │ │ -|#include "libtorrent/session_params.hpp" | │ │ │ │ │ -|#include "libtorrent/error_code.hpp" | │ │ │ │ │ -|#include "libtorrent/tracker_manager.hpp" | │ │ │ │ │ -|#include "libtorrent/http_tracker_connection.hpp" // for parse_tracker_response | │ │ │ │ │ -|#include "libtorrent/torrent_info.hpp" | │ │ │ │ │ -|#include "libtorrent/announce_entry.hpp" | │ │ │ │ │ -|#include "libtorrent/torrent.hpp" | │ │ │ │ │ -|#include "libtorrent/aux_/path.hpp" | │ │ │ │ │ -|#include "libtorrent/socket_io.hpp" | │ │ │ │ │ -| | │ │ │ │ │ -|using namespace lt; | │ │ │ │ │ -| | │ │ │ │ │ -| | │ │ │ │ │ -|TORRENT_TEST(parse_hostname_peers) | │ │ │ │ │ -|{ | │ │ │ │ │ -| char const response[] = "d5:peersld7:peer id20:aaaaaaaaaaaaaaaaaaaa" | │ │ │ │ │ -| "2:ip13:test_hostname4:porti1000eed" | │ │ │ │ │ -| "7:peer id20:bbbbabaababababababa2:ip12:another_host4:porti1001eeee"; | │ │ │ │ │ -| error_code ec; | │ │ │ │ │ -| tracker_response resp = parse_tracker_response(response | │ │ │ │ │ -| , ec, {}, sha1_hash()); | │ │ │ │ │ -| | │ │ │ │ │ -| TEST_EQUAL(ec, error_code()); | │ │ │ │ │ -| TEST_EQUAL(resp.peers.size(), 2); | │ │ │ │ │ -| if (resp.peers.size() == 2) | │ │ │ │ │ -| { | │ │ │ │ │ -| peer_entry const& e0 = resp.peers[0]; | │ │ │ │ │ -| peer_entry const& e1 = resp.peers[1]; | │ │ │ │ │ -| TEST_EQUAL(e0.hostname, "test_hostname"); | │ │ │ │ │ -| TEST_EQUAL(e0.port, 1000); | │ │ │ │ │ -| TEST_EQUAL(e0.pid, peer_id("aaaaaaaaaaaaaaaaaaaa")); | │ │ │ │ │ -| | │ │ │ │ │ -| TEST_EQUAL(e1.hostname, "another_host"); | │ │ │ │ │ -| TEST_EQUAL(e1.port, 1001); | │ │ │ │ │ -| TEST_EQUAL(e1.pid, peer_id("bbbbabaababababababa")); | │ │ │ │ │ -| } | │ │ │ │ │ -|} | │ │ │ │ │ -| | │ │ │ │ │ -|TORRENT_TEST(parse_peers4) | │ │ │ │ │ -|{ | │ │ │ │ │ -| char const response[] = "d5:peers12:\x01\x02\x03\x04\x30\x10" | │ │ │ │ │ -| "\x09\x08\x07\x06\x20\x10" "e"; | │ │ │ │ │ -|_ _e_r_r_o_r___c_o_d_e_ _e_c_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_t_e_s_t_/_t_e_s_t___f_i_l_e___s_t_o_r_a_g_e_._c_p_p_:|test file attributes | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_1_2_0_8_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tteesstt ffiillee aattttrriibbuutteess ********** | │ │ │ │ │ -|_**_**_**_ _.._.._//_tt_ee_ss_tt_//_tt_ee_ss_tt____ff_ii_ll_ee____ss_tt_oo_rr_aa_gg_ee_.._cc_pp_pp_::_11_22_00_88_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_t_e_s_t_/_t_e_s_t___f_i_l_e___s_t_o_r_a_g_e_._c_p_p_:|test symlinks | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_1_2_0_9_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tteesstt ssyymmlliinnkkss ********** | │ │ │ │ │ -|_**_**_**_ _.._.._//_tt_ee_ss_tt_//_tt_ee_ss_tt____ff_ii_ll_ee____ss_tt_oo_rr_aa_gg_ee_.._cc_pp_pp_::_11_22_00_99_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_t_e_s_t_/_t_e_s_t___b_l_o_o_m___f_i_l_t_e_r_._c_p_p_:|test size() | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_1_3_5_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tteesstt ssiizzee(()) ********** | │ │ │ │ │ -|_**_**_**_ _.._.._//_tt_ee_ss_tt_//_tt_ee_ss_tt____bb_ll_oo_oo_mm____ff_ii_ll_tt_ee_rr_.._cc_pp_pp_::_11_33_55_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_t_e_s_t_/_t_e_s_t___b_l_o_o_m___f_i_l_t_e_r_._c_p_p_:|test clear() | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_1_3_6_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tteesstt cclleeaarr(()) ********** | │ │ │ │ │ -|****** ....//tteesstt//tteesstt__bblloooomm__ffiilltteerr..ccpppp::113366 ****** | │ │ │ │ │ -|sha1_hash k("\x01\x00\x02\x00 "); | │ │ │ │ │ -| TEST_CHECK(!filter.find(k)); | │ │ │ │ │ -| filter.set(k); | │ │ │ │ │ -| TEST_CHECK(filter.find(k)); | │ │ │ │ │ -| | │ │ │ │ │ -| std::uint8_t compare[4] = { 0x16, 0xff, 0x55, 0xaa}; | │ │ │ │ │ -| | │ │ │ │ │ -| bits_out = filter.to_string(); | │ │ │ │ │ -| TEST_EQUAL(memcmp(compare, bits_out.c_str(), 4), 0); | │ │ │ │ │ -|} | │ │ │ │ │ -| | │ │ │ │ │ -|} // anonymous namespace | │ │ │ │ │ -| | │ │ │ │ │ -|TORRENT_TEST(bloom_filter) | │ │ │ │ │ -|{ | │ │ │ │ │ -| test_set_and_get(); | │ │ │ │ │ -| test_set_bits(); | │ │ │ │ │ -| test_count_zeroes(); | │ │ │ │ │ -| test_to_from_string(); | │ │ │ │ │ -| | │ │ │ │ │ -|_}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_t_e_s_t_/_t_e_s_t___t_r_a_n_s_f_e_r_._c_p_p_:_1_6_6_ _|_t_h_e_s_e_ _s_e_t_t_i_n_g_s___p_a_c_k_ _t_e_s_t_s_ _b_e_l_o_n_g_ _i_n_ _t_h_e_i_r_ _o_w_n_ _t_e_s_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tthheessee sseettttiinnggss__ppaacckk tteessttss bbeelloonngg iinn tthheeiirr oowwnn tteesstt ********** | │ │ │ │ │ -|****** ....//tteesstt//tteesstt__ttrraannssffeerr..ccpppp::116666 ****** | │ │ │ │ │ -|// to the time it will take to complete the test | │ │ │ │ │ -| pack.set_int(settings_pack::min_reconnect_time, 0); | │ │ │ │ │ -| pack.set_int(settings_pack::stop_tracker_timeout, 1); | │ │ │ │ │ -| pack.set_bool(settings_pack::announce_to_all_trackers, true); | │ │ │ │ │ -| pack.set_bool(settings_pack::announce_to_all_tiers, true); | │ │ │ │ │ -| | │ │ │ │ │ -| // make sure we announce to both http and udp trackers | │ │ │ │ │ -| pack.set_bool(settings_pack::prefer_udp_trackers, false); | │ │ │ │ │ -| pack.set_bool(settings_pack::enable_outgoing_utp, false); | │ │ │ │ │ -| pack.set_bool(settings_pack::enable_incoming_utp, false); | │ │ │ │ │ -| pack.set_bool(settings_pack::enable_lsd, false); | │ │ │ │ │ -| pack.set_bool(settings_pack::enable_natpmp, false); | │ │ │ │ │ -| pack.set_bool(settings_pack::enable_upnp, false); | │ │ │ │ │ -| pack.set_bool(settings_pack::enable_dht, false); | │ │ │ │ │ -| | │ │ │ │ │ -| pack.set_int(settings_pack::out_enc_policy, settings_pack::pe_disabled); | │ │ │ │ │ -| pack.set_int(settings_pack::in_enc_policy, settings_pack::pe_disabled); | │ │ │ │ │ -| | │ │ │ │ │ -| pack.set_bool(settings_pack::allow_multiple_connections_per_ip, false); | │ │ │ │ │ -| | │ │ │ │ │ -|pack.set_int(settings_pack::unchoke_slots_limit, 0); | │ │ │ │ │ -|ses1.apply_settings(pack); | │ │ │ │ │ -| TEST_CHECK(ses1.get_settings().get_int(settings_pack::unchoke_slots_limit) == 0); | │ │ │ │ │ -| | │ │ │ │ │ -| pack.set_int(settings_pack::unchoke_slots_limit, -1); | │ │ │ │ │ -| ses1.apply_settings(pack); | │ │ │ │ │ -| TEST_CHECK(ses1.get_settings().get_int(settings_pack::unchoke_slots_limit) == -1); | │ │ │ │ │ -| | │ │ │ │ │ -| pack.set_int(settings_pack::unchoke_slots_limit, 8); | │ │ │ │ │ -| ses1.apply_settings(pack); | │ │ │ │ │ -| TEST_CHECK(ses1.get_settings().get_int(settings_pack::unchoke_slots_limit) == 8); | │ │ │ │ │ -| | │ │ │ │ │ -| ses2.apply_settings(pack); | │ │ │ │ │ -| | │ │ │ │ │ -| torrent_handle tor1; | │ │ │ │ │ -| torrent_handle tor2; | │ │ │ │ │ -| | │ │ │ │ │ -| create_directory("tmp1_transfer", ec); | │ │ │ │ │ -| std::ofstream file("tmp1_transfer/temporary"); | │ │ │ │ │ -| std::shared_ptr t = ::create_torrent(&file, "temporary", 32 * 1024, 13, false); | │ │ │ │ │ -| file.close(); | │ │ │ │ │ -| | │ │ │ │ │ -| TEST_CHECK(exists(combine_path("tmp1_transfer", "temporary"))); | │ │ │ │ │ -| | │ │ │ │ │ -| add_torrent_params params; | │ │ │ │ │ -| params.storage_mode = storage_mode; | │ │ │ │ │ -| params.flags &= ~torrent_flags::paused; | │ │ │ │ │ -| params.flags &= ~torrent_flags::auto_managed; | │ │ │ │ │ -| | │ │ │ │ │ -| wait_for_listen(ses1, "ses1"); | │ │ │ │ │ -|_ _w_a_i_t___f_o_r___l_i_s_t_e_n_(_s_e_s_2_,_ _"_s_e_s_2_"_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_t_e_s_t_/_t_e_s_t___u_p_n_p_._c_p_p_:_1_5_6_ _ _ _ _ _|_s_t_o_r_e_ _t_h_e_ _l_o_g_ _a_n_d_ _v_e_r_i_f_y_ _t_h_a_t_ _s_o_m_e_ _k_e_y_ _m_e_s_s_a_g_e_s_ _a_r_e_ _t_h_e_r_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** ssttoorree tthhee lloogg aanndd vveerriiffyy tthhaatt ssoommee kkeeyy mmeessssaaggeess aarree tthheerree ********** | │ │ │ │ │ -|****** ....//tteesstt//tteesstt__uuppnnpp..ccpppp::115566 ****** | │ │ │ │ │ -|, portmap_protocol const protocol, error_code const& err | │ │ │ │ │ -| , portmap_transport, aux::listen_socket_handle const&) override | │ │ │ │ │ -| { | │ │ │ │ │ -| callback_info info = {mapping, port, err}; | │ │ │ │ │ -| callbacks.push_back(info); | │ │ │ │ │ -| std::cout << "mapping: " << static_cast(mapping) | │ │ │ │ │ -| << ", port: " << port << ", IP: " << ip | │ │ │ │ │ -| << ", proto: " << static_cast(protocol) | │ │ │ │ │ -| << ", error: \"" << err.message() << "\"\n"; | │ │ │ │ │ -| } | │ │ │ │ │ -| #ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ -| bool should_log_portmap(portmap_transport) const override | │ │ │ │ │ -| { | │ │ │ │ │ -| return true; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| void log_portmap(portmap_transport, char const* msg | │ │ │ │ │ -| , aux::listen_socket_handle const&) const override | │ │ │ │ │ -| { | │ │ │ │ │ -| std::cout << "UPnP: " << msg << std::endl; | │ │ │ │ │ -|} | │ │ │ │ │ -|#endif | │ │ │ │ │ -| }; | │ │ │ │ │ -| | │ │ │ │ │ -|ip_interface pick_upnp_interface() | │ │ │ │ │ -|{ | │ │ │ │ │ -| lt::io_context ios; | │ │ │ │ │ -| error_code ec; | │ │ │ │ │ -| std::vector const routes = enum_routes(ios, ec); | │ │ │ │ │ -| if (ec) | │ │ │ │ │ -| { | │ │ │ │ │ -| std::cerr << "failed to enumerate routes: " << ec.message() << '\n'; | │ │ │ │ │ -| TEST_CHECK(false); | │ │ │ │ │ -| return {}; | │ │ │ │ │ -| } | │ │ │ │ │ -| std::vector const ifs = enum_net_interfaces(ios, ec); | │ │ │ │ │ -| if (ec) | │ │ │ │ │ -| { | │ │ │ │ │ -| std::cerr << "failed to enumerate network interfaces: " << ec.message() << '\n'; | │ │ │ │ │ -| TEST_CHECK(false); | │ │ │ │ │ -| return {}; | │ │ │ │ │ -| } | │ │ │ │ │ -| int idx = 0; | │ │ │ │ │ -| for (auto const& face : ifs) | │ │ │ │ │ -| { | │ │ │ │ │ -| if (!face.interface_address.is_v4()) continue; | │ │ │ │ │ -| std::cout << " - " << idx | │ │ │ │ │ -| << ' ' << face.interface_address.to_string() | │ │ │ │ │ -| << ' ' << int(static_cast(face.state)) | │ │ │ │ │ -| << ' ' << static_cast(face.flags) | │ │ │ │ │ -|_ _ _ _<_<_ _'_ _'_ _<_<_ _f_a_c_e_._n_a_m_e_ _<_<_ _'_\_n_'_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |relevance 0|_._._/_t_e_s_t_/_t_e_s_t___p_e_e_r___l_i_s_t_._c_p_p_: |test erasing peers | │ │ │ │ │ |_ _ _ _ _ _ _ _ _ _ _ _|_1_2_4_1_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** tteesstt eerraassiinngg ppeeeerrss ********** | │ │ │ │ │ |_**_**_**_ _.._.._//_tt_ee_ss_tt_//_tt_ee_ss_tt____pp_ee_ee_rr____ll_ii_ss_tt_.._cc_pp_pp_::_11_22_44_11_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |relevance 0|_._._/_t_e_s_t_/_t_e_s_t___p_e_e_r___l_i_s_t_._c_p_p_: |test update_peer_port with allow_multiple_connections_per_ip and without | │ │ │ │ │ |_ _ _ _ _ _ _ _ _ _ _ _|_1_2_4_2_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** tteesstt uuppddaattee__ppeeeerr__ppoorrtt wwiitthh aallllooww__mmuullttiippllee__ccoonnnneeccttiioonnss__ppeerr__iipp aanndd wwiitthhoouutt ********** | │ │ │ │ │ @@ -5249,55 +5040,283 @@ │ │ │ │ │ |_ _ _ _ _ _ _ _ _ _ _ _|_1_2_4_8_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** tteesstt ccoonnnneeccttiioonn__cclloosseedd ********** | │ │ │ │ │ |_**_**_**_ _.._.._//_tt_ee_ss_tt_//_tt_ee_ss_tt____pp_ee_ee_rr____ll_ii_ss_tt_.._cc_pp_pp_::_11_22_44_88_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |relevance 0|_._._/_t_e_s_t_/_t_e_s_t___p_e_e_r___l_i_s_t_._c_p_p_: |connect candidates recalculation when incrementing failcount | │ │ │ │ │ |_ _ _ _ _ _ _ _ _ _ _ _|_1_2_4_9_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** ccoonnnneecctt ccaannddiiddaatteess rreeccaallccuullaattiioonn wwhheenn iinnccrreemmeennttiinngg ffaaiillccoouunntt ********** | │ │ │ │ │ |_**_**_**_ _.._.._//_tt_ee_ss_tt_//_tt_ee_ss_tt____pp_ee_ee_rr____ll_ii_ss_tt_.._cc_pp_pp_::_11_22_44_99_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_t_e_s_t_/ |test sending invalid requests (out of bound piece index, offsets and sizes) | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_t_e_s_t___f_a_s_t___e_x_t_e_n_s_i_o_n_._c_p_p_:_1_1_3_5_ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tteesstt sseennddiinngg iinnvvaalliidd rreeqquueessttss ((oouutt ooff bboouunndd ppiieeccee iinnddeexx,, ooffffsseettss aanndd ssiizzeess)) ********** | │ │ │ │ │ -|_**_**_**_ _.._.._//_tt_ee_ss_tt_//_tt_ee_ss_tt____ff_aa_ss_tt____ee_xx_tt_ee_nn_ss_ii_oo_nn_.._cc_pp_pp_::_11_11_33_55_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_t_e_s_t_/_t_e_s_t___d_h_t_._c_p_p_:_4_7_2_ _ _ _ _ _ _|_c_h_e_c_k_ _t_o_ _m_a_k_e_ _s_u_r_e_ _t_h_e_ _"_b_e_s_t_"_ _i_t_e_m_s_ _a_r_e_ _s_t_o_r_e_d_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** cchheecckk ttoo mmaakkee ssuurree tthhee ""bbeesstt"" iitteemmss aarree ssttoorreedd ********** | │ │ │ │ │ -|****** ....//tteesstt//tteesstt__ddhhtt..ccpppp::447722 ****** | │ │ │ │ │ -|, msg_args().target(items[j].target)); | │ │ │ │ │ +|relevance 0|_._._/_t_e_s_t_/ |test the case where we have > 120 samples (and have the base delay actually be updated) | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_t_e_s_t___t_i_m_e_s_t_a_m_p___h_i_s_t_o_r_y_._c_p_p_:_5_4_ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tteesstt tthhee ccaassee wwhheerree wwee hhaavvee >> 112200 ssaammpplleess ((aanndd hhaavvee tthhee bbaassee ddeellaayy aaccttuuaallllyy bbee uuppddaatteedd)) ********** | │ │ │ │ │ +|_**_**_**_ _.._.._//_tt_ee_ss_tt_//_tt_ee_ss_tt____tt_ii_mm_ee_ss_tt_aa_mm_pp____hh_ii_ss_tt_oo_rr_yy_.._cc_pp_pp_::_55_44_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_t_e_s_t_/ |test the case where a sample is lower than the history entry but not lower than the base | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_t_e_s_t___t_i_m_e_s_t_a_m_p___h_i_s_t_o_r_y_._c_p_p_:_5_5_ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tteesstt tthhee ccaassee wwhheerree aa ssaammppllee iiss lloowweerr tthhaann tthhee hhiissttoorryy eennttrryy bbuutt nnoott lloowweerr tthhaann tthhee bbaassee ********** | │ │ │ │ │ +|****** ....//tteesstt//tteesstt__ttiimmeessttaammpp__hhiissttoorryy..ccpppp::5555 ****** | │ │ │ │ │ +|#include "libtorrent/aux_/timestamp_history.hpp" | │ │ │ │ │ | | │ │ │ │ │ -| key_desc_t const desc[] = | │ │ │ │ │ -| { | │ │ │ │ │ -| { "r", bdecode_node::dict_t, 0, key_desc_t::parse_children }, | │ │ │ │ │ -| { "v", bdecode_node::dict_t, 0, 0}, | │ │ │ │ │ -| { "id", bdecode_node::string_t, 20, key_desc_t::last_child}, | │ │ │ │ │ -| { "y", bdecode_node::string_t, 1, 0}, | │ │ │ │ │ -| }; | │ │ │ │ │ +|TORRENT_TEST(timestamp_history) | │ │ │ │ │ +|{ | │ │ │ │ │ +| using namespace lt; | │ │ │ │ │ | | │ │ │ │ │ -| bdecode_node parsed[4]; | │ │ │ │ │ -| char error_string[200]; | │ │ │ │ │ +| aux::timestamp_history h; | │ │ │ │ │ +| TEST_EQUAL(h.add_sample(0x32, false), 0); | │ │ │ │ │ +| TEST_EQUAL(h.base(), 0x32); | │ │ │ │ │ +| TEST_EQUAL(h.add_sample(0x33, false), 0x1); | │ │ │ │ │ +| TEST_EQUAL(h.base(), 0x32); | │ │ │ │ │ +| TEST_EQUAL(h.add_sample(0x3433, false), 0x3401); | │ │ │ │ │ +| TEST_EQUAL(h.base(), 0x32); | │ │ │ │ │ +| TEST_EQUAL(h.add_sample(0x30, false), 0); | │ │ │ │ │ +| TEST_EQUAL(h.base(), 0x30); | │ │ │ │ │ | | │ │ │ │ │ -| int ret = verify_message(response, desc, parsed, error_string); | │ │ │ │ │ -| if (ret) | │ │ │ │ │ +| // test that wrapping of the timestamp is properly handled | │ │ │ │ │ +| h.add_sample(0xfffffff3, false); | │ │ │ │ │ +| TEST_EQUAL(h.base(), 0xfffffff3); | │ │ │ │ │ +| | │ │ │ │ │ +|_}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_t_e_s_t_/_t_e_s_t___m_e_r_k_l_e___t_r_e_e_._c_p_p_: |use structured bindings in C++17 | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_2_3_3_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** uussee ssttrruuccttuurreedd bbiinnddiinnggss iinn CC++++1177 ********** | │ │ │ │ │ +|****** ....//tteesstt//tteesstt__mmeerrkkllee__ttrreeee..ccpppp::223333 ****** | │ │ │ │ │ +|mask[std::size_t(i)] = true; | │ │ │ │ │ +| t.load_sparse_tree(span(f).subspan(first_piece, num_pieces), mask, empty_verified); | │ │ │ │ │ +| int const end_piece_layer = first_piece + merkle_num_leafs(num_pieces); | │ │ │ │ │ +| for (int i = 0; i < end_piece_layer; ++i) | │ │ │ │ │ | { | │ │ │ │ │ -| items_num.insert(items_num.begin(), j); | │ │ │ │ │ +| TEST_CHECK(t.has_node(i)); | │ │ │ │ │ +| TEST_CHECK(t.compare_node(i, f[i])); | │ │ │ │ │ +| } | │ │ │ │ │ +| for (int i = end_piece_layer; i < num_nodes; ++i) | │ │ │ │ │ +| { | │ │ │ │ │ +| TEST_CHECK(!t.has_node(i)); | │ │ │ │ │ | } | │ │ │ │ │ | } | │ │ │ │ │ -| | │ │ │ │ │ -|TEST_EQUAL(items_num.size(), 4); | │ │ │ │ │ |} | │ │ │ │ │ | | │ │ │ │ │ -|int sum_distance_exp(int s, node_entry const& e, node_id const& ref) | │ │ │ │ │ +|namespace { | │ │ │ │ │ +|void test_roundtrip(aux::merkle_tree const& t | │ │ │ │ │ +| , int const block_count | │ │ │ │ │ +| , int const blocks_per_piece) | │ │ │ │ │ |{ | │ │ │ │ │ -| return s + distance_exp(e.id, ref); | │ │ │ │ │ -|} | │ │ │ │ │ +|aux::vector mask; | │ │ │ │ │ +|std::vector tree; | │ │ │ │ │ +| std::tie(tree, mask) = t.build_sparse_vector(); | │ │ │ │ │ | | │ │ │ │ │ -|std::vector g_got_peers; | │ │ │ │ │ +| aux::merkle_tree t2(block_count, blocks_per_piece, f[0].data()); | │ │ │ │ │ +| t2.load_sparse_tree(tree, mask, empty_verified); | │ │ │ │ │ | | │ │ │ │ │ -|void get_peers_cb(std::vector const& peers) | │ │ │ │ │ -|{ | │ │ │ │ │ -| g_got_peers.insert(g_got_peers.end(), peers.begin(), peers.end()); | │ │ │ │ │ -|} | │ │ │ │ │ +| TEST_CHECK(t.build_vector() == t2.build_vector()); | │ │ │ │ │ +| for (int i = 0; i < int(t.size()); ++i) | │ │ │ │ │ +| { | │ │ │ │ │ +| TEST_EQUAL(t[i], t2[i]); | │ │ │ │ │ +| TEST_EQUAL(t.has_node(i), t2.has_node(i)); | │ │ │ │ │ +| | │ │ │ │ │ +| if (!t.has_node(i)) | │ │ │ │ │ +| TEST_CHECK(t[i].is_all_zeros()); | │ │ │ │ │ +| if (!t2.has_node(i)) | │ │ │ │ │ +| TEST_CHECK(t2[i].is_all_zeros()); | │ │ │ │ │ +| | │ │ │ │ │ +| TEST_CHECK(t.compare_node(i, t2[i])); | │ │ │ │ │ +| TEST_CHECK(t2.compare_node(i, t[i])); | │ │ │ │ │ +| } | │ │ │ │ │ +|} | │ │ │ │ │ +|} | │ │ │ │ │ +| | │ │ │ │ │ +|TORRENT_TEST(roundtrip_empty_tree) | │ │ │ │ │ +|{ | │ │ │ │ │ +| aux::merkle_tree t(num_blocks, 1, f[0].data()); | │ │ │ │ │ +| test_roundtrip(t, num_blocks, 1); | │ │ │ │ │ +|} | │ │ │ │ │ +| | │ │ │ │ │ +|_T_O_R_R_E_N_T___T_E_S_T_(_r_o_u_n_d_t_r_i_p___f_u_l_l___t_r_e_e_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_t_e_s_t_/_t_e_s_t___m_e_r_k_l_e___t_r_e_e_._c_p_p_: |add test for load_piece_layer() | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_9_3_8_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** aadddd tteesstt ffoorr llooaadd__ppiieeccee__llaayyeerr(()) ********** | │ │ │ │ │ +|_**_**_**_ _.._.._//_tt_ee_ss_tt_//_tt_ee_ss_tt____mm_ee_rr_kk_ll_ee____tt_rr_ee_ee_.._cc_pp_pp_::_99_33_88_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_t_e_s_t_/_t_e_s_t___m_e_r_k_l_e___t_r_e_e_._c_p_p_: |add test for add_hashes() with an odd number of blocks | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_9_3_9_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** aadddd tteesstt ffoorr aadddd__hhaasshheess(()) wwiitthh aann oodddd nnuummbbeerr ooff bblloocckkss ********** | │ │ │ │ │ +|_**_**_**_ _.._.._//_tt_ee_ss_tt_//_tt_ee_ss_tt____mm_ee_rr_kk_ll_ee____tt_rr_ee_ee_.._cc_pp_pp_::_99_33_99_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_t_e_s_t_/_t_e_s_t___m_e_r_k_l_e___t_r_e_e_._c_p_p_: |add test for set_block() (setting the last block) with an odd number of blocks | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_9_4_0_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** aadddd tteesstt ffoorr sseett__bblloocckk(()) ((sseettttiinngg tthhee llaasstt bblloocckk)) wwiitthh aann oodddd nnuummbbeerr ooff bblloocckkss ********** | │ │ │ │ │ +|****** ....//tteesstt//tteesstt__mmeerrkkllee__ttrreeee..ccpppp::994400 ****** | │ │ │ │ │ +| for (int i = 0; i < 7; ++i) | │ │ │ │ │ +| TEST_EQUAL(t[i], f[i]); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| // use a proof that ties the first piece node 3 (since we don't need it all | │ │ │ │ │ +| // the way to the root). | │ │ │ │ │ +| auto const result = t.add_hashes(127, pdiff(1), range(f, 127, 4), build_proof(f, 31, 3)); | │ │ │ │ │ +| TEST_CHECK(result); | │ │ │ │ │ +| | │ │ │ │ │ +| auto const& res = *result; | │ │ │ │ │ +| TEST_EQUAL(res.passed.size(), 0); | │ │ │ │ │ +| TEST_EQUAL(res.failed.size(), 0); | │ │ │ │ │ +| | │ │ │ │ │ +| for (int i = 127; i < 127 + 4; ++i) | │ │ │ │ │ +| TEST_CHECK(t[i] == f[i]); | │ │ │ │ │ +| | │ │ │ │ │ +| TEST_CHECK(t.verified_leafs() == none_set(num_blocks)); | │ │ │ │ │ +|} | │ │ │ │ │ +| | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_t_e_s_t_/_t_e_s_t___f_i_l_e___s_t_o_r_a_g_e_._c_p_p_:|test file attributes | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_1_2_0_8_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tteesstt ffiillee aattttrriibbuutteess ********** | │ │ │ │ │ +|_**_**_**_ _.._.._//_tt_ee_ss_tt_//_tt_ee_ss_tt____ff_ii_ll_ee____ss_tt_oo_rr_aa_gg_ee_.._cc_pp_pp_::_11_22_00_88_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_t_e_s_t_/_t_e_s_t___f_i_l_e___s_t_o_r_a_g_e_._c_p_p_:|test symlinks | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_1_2_0_9_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tteesstt ssyymmlliinnkkss ********** | │ │ │ │ │ +|_**_**_**_ _.._.._//_tt_ee_ss_tt_//_tt_ee_ss_tt____ff_ii_ll_ee____ss_tt_oo_rr_aa_gg_ee_.._cc_pp_pp_::_11_22_00_99_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_t_e_s_t_/_t_e_s_t___s_s_l_._c_p_p_:_4_0_7_ _ _ _ _ _ _|_t_e_s_t_ _u_s_i_n_g_ _a_ _s_i_g_n_e_d_ _c_e_r_t_i_f_i_c_a_t_e_ _w_i_t_h_ _t_h_e_ _w_r_o_n_g_ _i_n_f_o_-_h_a_s_h_ _i_n_ _D_N_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tteesstt uussiinngg aa ssiiggnneedd cceerrttiiffiiccaattee wwiitthh tthhee wwrroonngg iinnffoo--hhaasshh iinn DDNN ********** | │ │ │ │ │ +|****** ....//tteesstt//tteesstt__ssssll..ccpppp::440077 ****** | │ │ │ │ │ +|// in verifying peers | │ │ │ │ │ +| ctx.set_verify_mode(context::verify_none, ec); | │ │ │ │ │ +| if (ec) | │ │ │ │ │ +| { | │ │ │ │ │ +| std::printf("Failed to set SSL verify mode: %s\n" | │ │ │ │ │ +| , ec.message().c_str()); | │ │ │ │ │ +| TEST_CHECK(!ec); | │ │ │ │ │ +| return false; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| std::string certificate = combine_path("..", combine_path("ssl", "peer_certificate.pem")); | │ │ │ │ │ +| std::string private_key = combine_path("..", combine_path("ssl", "peer_private_key.pem")); | │ │ │ │ │ +| std::string dh_params = combine_path("..", combine_path("ssl", "dhparams.pem")); | │ │ │ │ │ +| | │ │ │ │ │ +| if (flags & invalid_certificate) | │ │ │ │ │ +| { | │ │ │ │ │ +| certificate = combine_path("..", combine_path("ssl", "invalid_peer_certificate.pem")); | │ │ │ │ │ +| private_key = combine_path("..", combine_path("ssl", "invalid_peer_private_key.pem")); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| | │ │ │ │ │ +|if (flags & (valid_certificate | invalid_certificate)) | │ │ │ │ │ +| { | │ │ │ │ │ +| std::printf("set_password_callback\n"); | │ │ │ │ │ +| ctx.set_password_callback( | │ │ │ │ │ +| [](std::size_t, context::password_purpose) { return "test"; } | │ │ │ │ │ +| , ec); | │ │ │ │ │ +| if (ec) | │ │ │ │ │ +| { | │ │ │ │ │ +| std::printf("Failed to set certificate passphrase: %s\n" | │ │ │ │ │ +| , ec.message().c_str()); | │ │ │ │ │ +| TEST_CHECK(!ec); | │ │ │ │ │ +| return false; | │ │ │ │ │ +| } | │ │ │ │ │ +| std::printf("use_certificate_file \"%s\"\n", certificate.c_str()); | │ │ │ │ │ +| ctx.use_certificate_file(certificate, context::pem, ec); | │ │ │ │ │ +| if (ec) | │ │ │ │ │ +| { | │ │ │ │ │ +| std::printf("Failed to set certificate file: %s\n" | │ │ │ │ │ +| , ec.message().c_str()); | │ │ │ │ │ +| TEST_CHECK(!ec); | │ │ │ │ │ +| return false; | │ │ │ │ │ +| } | │ │ │ │ │ +| std::printf("use_private_key_file \"%s\"\n", private_key.c_str()); | │ │ │ │ │ +| ctx.use_private_key_file(private_key, context::pem, ec); | │ │ │ │ │ +| if (ec) | │ │ │ │ │ +| { | │ │ │ │ │ +| std::printf("Failed to set private key: %s\n" | │ │ │ │ │ +| , ec.message().c_str()); | │ │ │ │ │ +| TEST_CHECK(!ec); | │ │ │ │ │ +|_ _ _ _r_e_t_u_r_n_ _f_a_l_s_e_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_t_e_s_t_/_t_e_s_t___s_s_l_._c_p_p_:_5_0_9_ _ _ _ _ _ _|_a_l_s_o_ _t_e_s_t_ _u_s_i_n_g_ _a_ _h_a_s_h_ _t_h_a_t_ _r_e_f_e_r_s_ _t_o_ _a_ _v_a_l_i_d_ _t_o_r_r_e_n_t_ _b_u_t_ _t_h_a_t_ _d_i_f_f_e_r_s_ _f_r_o_m_ _t_h_e_ _S_N_I_ _h_a_s_h_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** aallssoo tteesstt uussiinngg aa hhaasshh tthhaatt rreeffeerrss ttoo aa vvaalliidd ttoorrrreenntt bbuutt tthhaatt ddiiffffeerrss ffrroomm tthhee SSNNII hhaasshh ********** | │ │ │ │ │ +|****** ....//tteesstt//tteesstt__ssssll..ccpppp::550099 ****** | │ │ │ │ │ +|print_alerts(ses1, "ses1", true, true, &on_alert); | │ │ │ │ │ +| if (ec) | │ │ │ │ │ +| { | │ │ │ │ │ +| std::printf("Failed SSL handshake: %s\n" | │ │ │ │ │ +| , ec.message().c_str()); | │ │ │ │ │ +| return false; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| char handshake[] = "\x13" "BitTorrent protocol\0\0\0\0\0\0\0\x04" | │ │ │ │ │ +| " " // space for info-hash | │ │ │ │ │ +| "aaaaaaaaaaaaaaaaaaaa" // peer-id | │ │ │ │ │ +| "\0\0\0\x01\x02"; // interested | │ │ │ │ │ +| | │ │ │ │ │ +| // fill in the info-hash | │ │ │ │ │ +| if (flags & valid_bittorrent_hash) | │ │ │ │ │ +| { | │ │ │ │ │ +| std::memcpy(handshake + 28, &t->info_hashes().v1[0], 20); | │ │ │ │ │ +| } | │ │ │ │ │ +| else | │ │ │ │ │ +| { | │ │ │ │ │ +|std::generate(handshake + 28, handshake + 48, &rand); | │ │ │ │ │ +|} | │ │ │ │ │ +| | │ │ │ │ │ +| // fill in the peer-id | │ │ │ │ │ +| std::generate(handshake + 48, handshake + 68, &rand); | │ │ │ │ │ +| | │ │ │ │ │ +| std::printf("bittorrent handshake\n"); | │ │ │ │ │ +| boost::asio::write(ssl_sock, boost::asio::buffer(handshake, (sizeof(handshake) - 1)), ec); | │ │ │ │ │ +| print_alerts(ses1, "ses1", true, true, &on_alert); | │ │ │ │ │ +| if (ec) | │ │ │ │ │ +| { | │ │ │ │ │ +| std::printf("failed to write bittorrent handshake: %s\n" | │ │ │ │ │ +| , ec.message().c_str()); | │ │ │ │ │ +| return false; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| char buf[68]; | │ │ │ │ │ +| std::printf("read bittorrent handshake\n"); | │ │ │ │ │ +| boost::asio::read(ssl_sock, boost::asio::buffer(buf, sizeof(buf)), ec); | │ │ │ │ │ +| print_alerts(ses1, "ses1", true, true, &on_alert); | │ │ │ │ │ +| if (ec) | │ │ │ │ │ +| { | │ │ │ │ │ +| std::printf("failed to read bittorrent handshake: %s\n" | │ │ │ │ │ +| , ec.message().c_str()); | │ │ │ │ │ +| return false; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| if (memcmp(buf, "\x13" "BitTorrent protocol", 20) != 0) | │ │ │ │ │ +| { | │ │ │ │ │ +| std::printf("invalid bittorrent handshake\n"); | │ │ │ │ │ +|_ _ _r_e_t_u_r_n_ _f_a_l_s_e_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_t_e_s_t_/_t_e_s_t___d_h_t_._c_p_p_:_4_7_2_ _ _ _ _ _ _|_c_h_e_c_k_ _t_o_ _m_a_k_e_ _s_u_r_e_ _t_h_e_ _"_b_e_s_t_"_ _i_t_e_m_s_ _a_r_e_ _s_t_o_r_e_d_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** cchheecckk ttoo mmaakkee ssuurree tthhee ""bbeesstt"" iitteemmss aarree ssttoorreedd ********** | │ │ │ │ │ +|****** ....//tteesstt//tteesstt__ddhhtt..ccpppp::447722 ****** | │ │ │ │ │ +|, msg_args().target(items[j].target)); | │ │ │ │ │ +| | │ │ │ │ │ +| key_desc_t const desc[] = | │ │ │ │ │ +| { | │ │ │ │ │ +| { "r", bdecode_node::dict_t, 0, key_desc_t::parse_children }, | │ │ │ │ │ +| { "v", bdecode_node::dict_t, 0, 0}, | │ │ │ │ │ +| { "id", bdecode_node::string_t, 20, key_desc_t::last_child}, | │ │ │ │ │ +| { "y", bdecode_node::string_t, 1, 0}, | │ │ │ │ │ +| }; | │ │ │ │ │ +| | │ │ │ │ │ +| bdecode_node parsed[4]; | │ │ │ │ │ +| char error_string[200]; | │ │ │ │ │ +| | │ │ │ │ │ +| int ret = verify_message(response, desc, parsed, error_string); | │ │ │ │ │ +| if (ret) | │ │ │ │ │ +| { | │ │ │ │ │ +| items_num.insert(items_num.begin(), j); | │ │ │ │ │ +| } | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +|TEST_EQUAL(items_num.size(), 4); | │ │ │ │ │ +|} | │ │ │ │ │ +| | │ │ │ │ │ +|int sum_distance_exp(int s, node_entry const& e, node_id const& ref) | │ │ │ │ │ +|{ | │ │ │ │ │ +| return s + distance_exp(e.id, ref); | │ │ │ │ │ +|} | │ │ │ │ │ +| | │ │ │ │ │ +|std::vector g_got_peers; | │ │ │ │ │ +| | │ │ │ │ │ +|void get_peers_cb(std::vector const& peers) | │ │ │ │ │ +|{ | │ │ │ │ │ +| g_got_peers.insert(g_got_peers.end(), peers.begin(), peers.end()); | │ │ │ │ │ +|} | │ │ │ │ │ | | │ │ │ │ │ |std::vector g_got_items; | │ │ │ │ │ |dht::item g_put_item; | │ │ │ │ │ |int g_put_count; | │ │ │ │ │ | | │ │ │ │ │ |void get_mutable_item_cb(dht::item const& i, bool a) | │ │ │ │ │ |{ | │ │ │ │ │ @@ -5601,151 +5620,176 @@ │ │ │ │ │ |template | │ │ │ │ │ |void test_unfinished_pieces(Fun f) | │ │ │ │ │ |{ | │ │ │ │ │ | // create a torrent and complete files | │ │ │ │ │ | std::shared_ptr ti = generate_torrent(true, true); | │ │ │ │ │ | | │ │ │ │ │ |_ _a_d_d___t_o_r_r_e_n_t___p_a_r_a_m_s_ _p_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_t_e_s_t_/_t_e_s_t___s_s_l_._c_p_p_:_4_0_7_ _ _ _ _ _ _|_t_e_s_t_ _u_s_i_n_g_ _a_ _s_i_g_n_e_d_ _c_e_r_t_i_f_i_c_a_t_e_ _w_i_t_h_ _t_h_e_ _w_r_o_n_g_ _i_n_f_o_-_h_a_s_h_ _i_n_ _D_N_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tteesstt uussiinngg aa ssiiggnneedd cceerrttiiffiiccaattee wwiitthh tthhee wwrroonngg iinnffoo--hhaasshh iinn DDNN ********** | │ │ │ │ │ -|****** ....//tteesstt//tteesstt__ssssll..ccpppp::440077 ****** | │ │ │ │ │ -|// in verifying peers | │ │ │ │ │ -| ctx.set_verify_mode(context::verify_none, ec); | │ │ │ │ │ -| if (ec) | │ │ │ │ │ -| { | │ │ │ │ │ -| std::printf("Failed to set SSL verify mode: %s\n" | │ │ │ │ │ -| , ec.message().c_str()); | │ │ │ │ │ -| TEST_CHECK(!ec); | │ │ │ │ │ -| return false; | │ │ │ │ │ -| } | │ │ │ │ │ +|relevance 0|_._._/_t_e_s_t_/_t_e_s_t___f_l_a_g_s_._c_p_p_:_1_6_3 |change to a different test setup. currently always paused. test_set_after_add(torrent_flags::paused); test_unset_after_add | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_(_t_o_r_r_e_n_t___f_l_a_g_s_:_:_p_a_u_s_e_d_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** cchhaannggee ttoo aa ddiiffffeerreenntt tteesstt sseettuupp.. ccuurrrreennttllyy aallwwaayyss ppaauusseedd.. tteesstt__sseett__aafftteerr__aadddd((ttoorrrreenntt__ffllaaggss::::ppaauusseedd));; tteesstt__uunnsseett__aafftteerr__aadddd((ttoorrrreenntt__ffllaaggss::::ppaauusseedd));; ********** | │ │ │ │ │ +|****** ....//tteesstt//tteesstt__ffllaaggss..ccpppp::116633 ****** | │ │ │ │ │ +|{ | │ │ │ │ │ +| // share-mode | │ │ │ │ │ +| test_add_and_get_flags(torrent_flags::share_mode); | │ │ │ │ │ +| test_set_after_add(torrent_flags::share_mode); | │ │ │ │ │ +| test_unset_after_add(torrent_flags::share_mode); | │ │ │ │ │ +|} | │ │ │ │ │ +|#endif | │ │ │ │ │ | | │ │ │ │ │ -| std::string certificate = combine_path("..", combine_path("ssl", "peer_certificate.pem")); | │ │ │ │ │ -| std::string private_key = combine_path("..", combine_path("ssl", "peer_private_key.pem")); | │ │ │ │ │ -| std::string dh_params = combine_path("..", combine_path("ssl", "dhparams.pem")); | │ │ │ │ │ +|TORRENT_TEST(flag_apply_ip_filter) | │ │ │ │ │ +|{ | │ │ │ │ │ +| // apply-ip-filter | │ │ │ │ │ +| test_add_and_get_flags(torrent_flags::apply_ip_filter); | │ │ │ │ │ +| test_set_after_add(torrent_flags::apply_ip_filter); | │ │ │ │ │ +| test_unset_after_add(torrent_flags::apply_ip_filter); | │ │ │ │ │ +|} | │ │ │ │ │ | | │ │ │ │ │ -| if (flags & invalid_certificate) | │ │ │ │ │ -| { | │ │ │ │ │ -| certificate = combine_path("..", combine_path("ssl", "invalid_peer_certificate.pem")); | │ │ │ │ │ -| private_key = combine_path("..", combine_path("ssl", "invalid_peer_private_key.pem")); | │ │ │ │ │ -| } | │ │ │ │ │ +|TORRENT_TEST(flag_paused) | │ │ │ │ │ +|{ | │ │ │ │ │ +| // paused | │ │ │ │ │ +| test_add_and_get_flags(torrent_flags::paused); | │ │ │ │ │ +|} | │ │ │ │ │ | | │ │ │ │ │ +|TORRENT_TEST(flag_auto_managed) | │ │ │ │ │ +|{ | │ │ │ │ │ +| // auto-managed | │ │ │ │ │ +| test_add_and_get_flags(torrent_flags::auto_managed); | │ │ │ │ │ +| test_set_after_add(torrent_flags::auto_managed); | │ │ │ │ │ +| test_unset_after_add(torrent_flags::auto_managed); | │ │ │ │ │ +|} | │ │ │ │ │ | | │ │ │ │ │ -|if (flags & (valid_certificate | invalid_certificate)) | │ │ │ │ │ -| { | │ │ │ │ │ -| std::printf("set_password_callback\n"); | │ │ │ │ │ -| ctx.set_password_callback( | │ │ │ │ │ -| [](std::size_t, context::password_purpose) { return "test"; } | │ │ │ │ │ -| , ec); | │ │ │ │ │ -| if (ec) | │ │ │ │ │ -| { | │ │ │ │ │ -| std::printf("Failed to set certificate passphrase: %s\n" | │ │ │ │ │ -| , ec.message().c_str()); | │ │ │ │ │ -| TEST_CHECK(!ec); | │ │ │ │ │ -| return false; | │ │ │ │ │ -| } | │ │ │ │ │ -| std::printf("use_certificate_file \"%s\"\n", certificate.c_str()); | │ │ │ │ │ -| ctx.use_certificate_file(certificate, context::pem, ec); | │ │ │ │ │ -| if (ec) | │ │ │ │ │ -| { | │ │ │ │ │ -| std::printf("Failed to set certificate file: %s\n" | │ │ │ │ │ -| , ec.message().c_str()); | │ │ │ │ │ -| TEST_CHECK(!ec); | │ │ │ │ │ -| return false; | │ │ │ │ │ -| } | │ │ │ │ │ -| std::printf("use_private_key_file \"%s\"\n", private_key.c_str()); | │ │ │ │ │ -| ctx.use_private_key_file(private_key, context::pem, ec); | │ │ │ │ │ -| if (ec) | │ │ │ │ │ -| { | │ │ │ │ │ -| std::printf("Failed to set private key: %s\n" | │ │ │ │ │ -| , ec.message().c_str()); | │ │ │ │ │ -| TEST_CHECK(!ec); | │ │ │ │ │ -|_ _ _ _r_e_t_u_r_n_ _f_a_l_s_e_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_t_e_s_t_/_t_e_s_t___s_s_l_._c_p_p_:_5_0_9_ _ _ _ _ _ _|_a_l_s_o_ _t_e_s_t_ _u_s_i_n_g_ _a_ _h_a_s_h_ _t_h_a_t_ _r_e_f_e_r_s_ _t_o_ _a_ _v_a_l_i_d_ _t_o_r_r_e_n_t_ _b_u_t_ _t_h_a_t_ _d_i_f_f_e_r_s_ _f_r_o_m_ _t_h_e_ _S_N_I_ _h_a_s_h_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** aallssoo tteesstt uussiinngg aa hhaasshh tthhaatt rreeffeerrss ttoo aa vvaalliidd ttoorrrreenntt bbuutt tthhaatt ddiiffffeerrss ffrroomm tthhee SSNNII hhaasshh ********** | │ │ │ │ │ -|****** ....//tteesstt//tteesstt__ssssll..ccpppp::550099 ****** | │ │ │ │ │ -|print_alerts(ses1, "ses1", true, true, &on_alert); | │ │ │ │ │ -| if (ec) | │ │ │ │ │ -| { | │ │ │ │ │ -| std::printf("Failed SSL handshake: %s\n" | │ │ │ │ │ -| , ec.message().c_str()); | │ │ │ │ │ -| return false; | │ │ │ │ │ -| } | │ │ │ │ │ +|// super seeding mode is automatically turned off if we're not a seed | │ │ │ │ │ +|// since the posix_disk_io is not threaded, this will happen immediately | │ │ │ │ │ +|#if TORRENT_HAVE_MMAP | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_SUPERSEEDING | │ │ │ │ │ +|TORRENT_TEST(flag_super_seeding) | │ │ │ │ │ +|{ | │ │ │ │ │ +| // super-seeding | │ │ │ │ │ +| test_add_and_get_flags(torrent_flags::super_seeding); | │ │ │ │ │ +| test_unset_after_add(torrent_flags::super_seeding); | │ │ │ │ │ +| test_set_after_add(torrent_flags::super_seeding); | │ │ │ │ │ +|} | │ │ │ │ │ +|#endif | │ │ │ │ │ +|#endif | │ │ │ │ │ | | │ │ │ │ │ -| char handshake[] = "\x13" "BitTorrent protocol\0\0\0\0\0\0\0\x04" | │ │ │ │ │ -| " " // space for info-hash | │ │ │ │ │ -| "aaaaaaaaaaaaaaaaaaaa" // peer-id | │ │ │ │ │ -| "\0\0\0\x01\x02"; // interested | │ │ │ │ │ +|TORRENT_TEST(flag_sequential_download) | │ │ │ │ │ +|{ | │ │ │ │ │ +| // sequential-download | │ │ │ │ │ +| test_add_and_get_flags(torrent_flags::sequential_download); | │ │ │ │ │ +| test_set_after_add(torrent_flags::sequential_download); | │ │ │ │ │ +| test_unset_after_add(torrent_flags::sequential_download); | │ │ │ │ │ +|_}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_t_e_s_t_/_t_e_s_t___f_l_a_g_s_._c_p_p_:_2_0_5 |this test is flaky, since the torrent will become ready before asking for the flags, and by then stop_when_ready will have been | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_c_l_e_a_r_e_d_ _t_e_s_t___a_d_d___a_n_d___g_e_t___f_l_a_g_s_(_t_o_r_r_e_n_t___f_l_a_g_s_:_:_s_t_o_p___w_h_e_n___r_e_a_d_y_)_;_ _s_e_t_t_i_n_g_ _s_t_o_p_-_w_h_e_n_-_r_e_a_d_y_ _w_h_e_n_ _a_l_r_e_a_d_y_ _s_t_o_p_p_e_d_ _h_a_s_ _n_o_ _e_f_f_e_c_t_._ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tthhiiss tteesstt iiss ffllaakkyy,, ssiinnccee tthhee ttoorrrreenntt wwiillll bbeeccoommee rreeaaddyy bbeeffoorree aasskkiinngg ffoorr tthhee ffllaaggss,, aanndd bbyy tthheenn ssttoopp__wwhheenn__rreeaaddyy wwiillll hhaavvee bbeeeenn cclleeaarreedd tteesstt__aadddd__aanndd__ggeett__ffllaaggss | │ │ │ │ │ +|((ttoorrrreenntt__ffllaaggss::::ssttoopp__wwhheenn__rreeaaddyy));; sseettttiinngg ssttoopp--wwhheenn--rreeaaddyy wwhheenn aallrreeaaddyy ssttooppppeedd hhaass nnoo eeffffeecctt.. ********** | │ │ │ │ │ +|_**_**_**_ _.._.._//_tt_ee_ss_tt_//_tt_ee_ss_tt____ff_ll_aa_gg_ss_.._cc_pp_pp_::_22_00_55_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_t_e_s_t_/_t_e_s_t___f_l_a_g_s_._c_p_p_:_2_0_9_ _ _ _ _|_c_h_a_n_g_e_ _t_o_ _a_ _d_i_f_f_e_r_e_n_t_ _t_e_s_t_ _s_e_t_u_p_._ _c_u_r_r_e_n_t_l_y_ _a_l_w_a_y_s_ _p_a_u_s_e_d_._ _t_e_s_t___s_e_t___a_f_t_e_r___a_d_d_(_t_o_r_r_e_n_t___f_l_a_g_s_:_:_s_t_o_p___w_h_e_n___r_e_a_d_y_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** cchhaannggee ttoo aa ddiiffffeerreenntt tteesstt sseettuupp.. ccuurrrreennttllyy aallwwaayyss ppaauusseedd.. tteesstt__sseett__aafftteerr__aadddd((ttoorrrreenntt__ffllaaggss::::ssttoopp__wwhheenn__rreeaaddyy));; ********** | │ │ │ │ │ +|****** ....//tteesstt//tteesstt__ffllaaggss..ccpppp::220099 ****** | │ │ │ │ │ +|test_set_after_add(torrent_flags::super_seeding); | │ │ │ │ │ +|} | │ │ │ │ │ +|#endif | │ │ │ │ │ +|#endif | │ │ │ │ │ | | │ │ │ │ │ -| // fill in the info-hash | │ │ │ │ │ -| if (flags & valid_bittorrent_hash) | │ │ │ │ │ -| { | │ │ │ │ │ -| std::memcpy(handshake + 28, &t->info_hashes().v1[0], 20); | │ │ │ │ │ -| } | │ │ │ │ │ -| else | │ │ │ │ │ -| { | │ │ │ │ │ -|std::generate(handshake + 28, handshake + 48, &rand); | │ │ │ │ │ +|TORRENT_TEST(flag_sequential_download) | │ │ │ │ │ +|{ | │ │ │ │ │ +| // sequential-download | │ │ │ │ │ +| test_add_and_get_flags(torrent_flags::sequential_download); | │ │ │ │ │ +| test_set_after_add(torrent_flags::sequential_download); | │ │ │ │ │ +| test_unset_after_add(torrent_flags::sequential_download); | │ │ │ │ │ |} | │ │ │ │ │ | | │ │ │ │ │ -| // fill in the peer-id | │ │ │ │ │ -| std::generate(handshake + 48, handshake + 68, &rand); | │ │ │ │ │ +|// the stop when ready flag will be cleared when the torrent is ready to start | │ │ │ │ │ +|// downloading. | │ │ │ │ │ +|// since the posix_disk_io is not threaded, this will happen immediately | │ │ │ │ │ +|#if TORRENT_HAVE_MMAP | │ │ │ │ │ +|TORRENT_TEST(flag_stop_when_ready) | │ │ │ │ │ +|{ | │ │ │ │ │ +| // stop-when-ready | │ │ │ │ │ +|test_unset_after_add(torrent_flags::stop_when_ready); | │ │ │ │ │ +|} | │ │ │ │ │ +|#endif | │ │ │ │ │ | | │ │ │ │ │ -| std::printf("bittorrent handshake\n"); | │ │ │ │ │ -| boost::asio::write(ssl_sock, boost::asio::buffer(handshake, (sizeof(handshake) - 1)), ec); | │ │ │ │ │ -| print_alerts(ses1, "ses1", true, true, &on_alert); | │ │ │ │ │ -| if (ec) | │ │ │ │ │ -| { | │ │ │ │ │ -| std::printf("failed to write bittorrent handshake: %s\n" | │ │ │ │ │ -| , ec.message().c_str()); | │ │ │ │ │ -| return false; | │ │ │ │ │ -| } | │ │ │ │ │ +|TORRENT_TEST(flag_disable_dht) | │ │ │ │ │ +|{ | │ │ │ │ │ +| test_add_and_get_flags(torrent_flags::disable_dht); | │ │ │ │ │ +| test_set_after_add(torrent_flags::disable_dht); | │ │ │ │ │ +| test_unset_after_add(torrent_flags::disable_dht); | │ │ │ │ │ +|} | │ │ │ │ │ | | │ │ │ │ │ -| char buf[68]; | │ │ │ │ │ -| std::printf("read bittorrent handshake\n"); | │ │ │ │ │ -| boost::asio::read(ssl_sock, boost::asio::buffer(buf, sizeof(buf)), ec); | │ │ │ │ │ -| print_alerts(ses1, "ses1", true, true, &on_alert); | │ │ │ │ │ -| if (ec) | │ │ │ │ │ -| { | │ │ │ │ │ -| std::printf("failed to read bittorrent handshake: %s\n" | │ │ │ │ │ -| , ec.message().c_str()); | │ │ │ │ │ -| return false; | │ │ │ │ │ -| } | │ │ │ │ │ | | │ │ │ │ │ -| if (memcmp(buf, "\x13" "BitTorrent protocol", 20) != 0) | │ │ │ │ │ -| { | │ │ │ │ │ -| std::printf("invalid bittorrent handshake\n"); | │ │ │ │ │ -|_ _ _r_e_t_u_r_n_ _f_a_l_s_e_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_t_e_s_t_/ |test the case where we have > 120 samples (and have the base delay actually be updated) | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_t_e_s_t___t_i_m_e_s_t_a_m_p___h_i_s_t_o_r_y_._c_p_p_:_5_4_ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tteesstt tthhee ccaassee wwhheerree wwee hhaavvee >> 112200 ssaammpplleess ((aanndd hhaavvee tthhee bbaassee ddeellaayy aaccttuuaallllyy bbee uuppddaatteedd)) ********** | │ │ │ │ │ -|_**_**_**_ _.._.._//_tt_ee_ss_tt_//_tt_ee_ss_tt____tt_ii_mm_ee_ss_tt_aa_mm_pp____hh_ii_ss_tt_oo_rr_yy_.._cc_pp_pp_::_55_44_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_t_e_s_t_/ |test the case where a sample is lower than the history entry but not lower than the base | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_t_e_s_t___t_i_m_e_s_t_a_m_p___h_i_s_t_o_r_y_._c_p_p_:_5_5_ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tteesstt tthhee ccaassee wwhheerree aa ssaammppllee iiss lloowweerr tthhaann tthhee hhiissttoorryy eennttrryy bbuutt nnoott lloowweerr tthhaann tthhee bbaassee ********** | │ │ │ │ │ -|****** ....//tteesstt//tteesstt__ttiimmeessttaammpp__hhiissttoorryy..ccpppp::5555 ****** | │ │ │ │ │ -|#include "libtorrent/aux_/timestamp_history.hpp" | │ │ │ │ │ +|TORRENT_TEST(flag_disable_lsd) | │ │ │ │ │ +|{ | │ │ │ │ │ +| test_add_and_get_flags(torrent_flags::disable_lsd); | │ │ │ │ │ +| test_set_after_add(torrent_flags::disable_lsd); | │ │ │ │ │ +| test_unset_after_add(torrent_flags::disable_lsd); | │ │ │ │ │ +|} | │ │ │ │ │ | | │ │ │ │ │ -|TORRENT_TEST(timestamp_history) | │ │ │ │ │ +|TORRENT_TEST(flag_disable_pex) | │ │ │ │ │ |{ | │ │ │ │ │ -| using namespace lt; | │ │ │ │ │ +| test_add_and_get_flags(torrent_flags::disable_pex); | │ │ │ │ │ +| test_set_after_add(torrent_flags::disable_pex); | │ │ │ │ │ +| test_unset_after_add(torrent_flags::disable_pex); | │ │ │ │ │ +|_}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_t_e_s_t_/_t_e_s_t___t_r_a_n_s_f_e_r_._c_p_p_:_1_6_6_ _|_t_h_e_s_e_ _s_e_t_t_i_n_g_s___p_a_c_k_ _t_e_s_t_s_ _b_e_l_o_n_g_ _i_n_ _t_h_e_i_r_ _o_w_n_ _t_e_s_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tthheessee sseettttiinnggss__ppaacckk tteessttss bbeelloonngg iinn tthheeiirr oowwnn tteesstt ********** | │ │ │ │ │ +|****** ....//tteesstt//tteesstt__ttrraannssffeerr..ccpppp::116666 ****** | │ │ │ │ │ +|// to the time it will take to complete the test | │ │ │ │ │ +| pack.set_int(settings_pack::min_reconnect_time, 0); | │ │ │ │ │ +| pack.set_int(settings_pack::stop_tracker_timeout, 1); | │ │ │ │ │ +| pack.set_bool(settings_pack::announce_to_all_trackers, true); | │ │ │ │ │ +| pack.set_bool(settings_pack::announce_to_all_tiers, true); | │ │ │ │ │ | | │ │ │ │ │ -| aux::timestamp_history h; | │ │ │ │ │ -| TEST_EQUAL(h.add_sample(0x32, false), 0); | │ │ │ │ │ -| TEST_EQUAL(h.base(), 0x32); | │ │ │ │ │ -| TEST_EQUAL(h.add_sample(0x33, false), 0x1); | │ │ │ │ │ -| TEST_EQUAL(h.base(), 0x32); | │ │ │ │ │ -| TEST_EQUAL(h.add_sample(0x3433, false), 0x3401); | │ │ │ │ │ -| TEST_EQUAL(h.base(), 0x32); | │ │ │ │ │ -| TEST_EQUAL(h.add_sample(0x30, false), 0); | │ │ │ │ │ -| TEST_EQUAL(h.base(), 0x30); | │ │ │ │ │ +| // make sure we announce to both http and udp trackers | │ │ │ │ │ +| pack.set_bool(settings_pack::prefer_udp_trackers, false); | │ │ │ │ │ +| pack.set_bool(settings_pack::enable_outgoing_utp, false); | │ │ │ │ │ +| pack.set_bool(settings_pack::enable_incoming_utp, false); | │ │ │ │ │ +| pack.set_bool(settings_pack::enable_lsd, false); | │ │ │ │ │ +| pack.set_bool(settings_pack::enable_natpmp, false); | │ │ │ │ │ +| pack.set_bool(settings_pack::enable_upnp, false); | │ │ │ │ │ +| pack.set_bool(settings_pack::enable_dht, false); | │ │ │ │ │ | | │ │ │ │ │ -| // test that wrapping of the timestamp is properly handled | │ │ │ │ │ -| h.add_sample(0xfffffff3, false); | │ │ │ │ │ -| TEST_EQUAL(h.base(), 0xfffffff3); | │ │ │ │ │ +| pack.set_int(settings_pack::out_enc_policy, settings_pack::pe_disabled); | │ │ │ │ │ +| pack.set_int(settings_pack::in_enc_policy, settings_pack::pe_disabled); | │ │ │ │ │ | | │ │ │ │ │ -|_}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +| pack.set_bool(settings_pack::allow_multiple_connections_per_ip, false); | │ │ │ │ │ +| | │ │ │ │ │ +|pack.set_int(settings_pack::unchoke_slots_limit, 0); | │ │ │ │ │ +|ses1.apply_settings(pack); | │ │ │ │ │ +| TEST_CHECK(ses1.get_settings().get_int(settings_pack::unchoke_slots_limit) == 0); | │ │ │ │ │ +| | │ │ │ │ │ +| pack.set_int(settings_pack::unchoke_slots_limit, -1); | │ │ │ │ │ +| ses1.apply_settings(pack); | │ │ │ │ │ +| TEST_CHECK(ses1.get_settings().get_int(settings_pack::unchoke_slots_limit) == -1); | │ │ │ │ │ +| | │ │ │ │ │ +| pack.set_int(settings_pack::unchoke_slots_limit, 8); | │ │ │ │ │ +| ses1.apply_settings(pack); | │ │ │ │ │ +| TEST_CHECK(ses1.get_settings().get_int(settings_pack::unchoke_slots_limit) == 8); | │ │ │ │ │ +| | │ │ │ │ │ +| ses2.apply_settings(pack); | │ │ │ │ │ +| | │ │ │ │ │ +| torrent_handle tor1; | │ │ │ │ │ +| torrent_handle tor2; | │ │ │ │ │ +| | │ │ │ │ │ +| create_directory("tmp1_transfer", ec); | │ │ │ │ │ +| std::ofstream file("tmp1_transfer/temporary"); | │ │ │ │ │ +| std::shared_ptr t = ::create_torrent(&file, "temporary", 32 * 1024, 13, false); | │ │ │ │ │ +| file.close(); | │ │ │ │ │ +| | │ │ │ │ │ +| TEST_CHECK(exists(combine_path("tmp1_transfer", "temporary"))); | │ │ │ │ │ +| | │ │ │ │ │ +| add_torrent_params params; | │ │ │ │ │ +| params.storage_mode = storage_mode; | │ │ │ │ │ +| params.flags &= ~torrent_flags::paused; | │ │ │ │ │ +| params.flags &= ~torrent_flags::auto_managed; | │ │ │ │ │ +| | │ │ │ │ │ +| wait_for_listen(ses1, "ses1"); | │ │ │ │ │ +|_ _w_a_i_t___f_o_r___l_i_s_t_e_n_(_s_e_s_2_,_ _"_s_e_s_2_"_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |relevance 0|_._._/_t_e_s_t_/ |test files with different piece size (negative test) | │ │ │ │ │ |_ _ _ _ _ _ _ _ _ _ _ _|_t_e_s_t___r_e_s_o_l_v_e___l_i_n_k_s_._c_p_p_:_9_5_ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** tteesstt ffiilleess wwiitthh ddiiffffeerreenntt ppiieeccee ssiizzee ((nneeggaattiivvee tteesstt)) ********** | │ │ │ │ │ |****** ....//tteesstt//tteesstt__rreessoollvvee__lliinnkkss..ccpppp::9955 ****** | │ │ │ │ │ |{ "test2", "test1_pad_files", 0}, | │ │ │ │ │ | { "test3", "test1_pad_files", 0}, | │ │ │ │ │ | { "test2", "test1_single", 0}, | │ │ │ │ │ @@ -5818,371 +5862,748 @@ │ │ │ │ │ | auto const num_matches = std::size_t(std::count_if(links.begin(), links.end() | │ │ │ │ │ | , std::bind(&resolve_links::link_t::ti, _1))); | │ │ │ │ │ | | │ │ │ │ │ | // some debug output in case the test fails | │ │ │ │ │ | if (num_matches > e.expected_matches) | │ │ │ │ │ | { | │ │ │ │ │ |_ _ _ _f_i_l_e___s_t_o_r_a_g_e_ _c_o_n_s_t_&_ _f_s_ _=_ _t_i_1_-_>_f_i_l_e_s_(_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_t_e_s_t_/_t_e_s_t___f_l_a_g_s_._c_p_p_:_1_6_3 |change to a different test setup. currently always paused. test_set_after_add(torrent_flags::paused); test_unset_after_add | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_(_t_o_r_r_e_n_t___f_l_a_g_s_:_:_p_a_u_s_e_d_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** cchhaannggee ttoo aa ddiiffffeerreenntt tteesstt sseettuupp.. ccuurrrreennttllyy aallwwaayyss ppaauusseedd.. tteesstt__sseett__aafftteerr__aadddd((ttoorrrreenntt__ffllaaggss::::ppaauusseedd));; tteesstt__uunnsseett__aafftteerr__aadddd((ttoorrrreenntt__ffllaaggss::::ppaauusseedd));; ********** | │ │ │ │ │ -|****** ....//tteesstt//tteesstt__ffllaaggss..ccpppp::116633 ****** | │ │ │ │ │ -|{ | │ │ │ │ │ -| // share-mode | │ │ │ │ │ -| test_add_and_get_flags(torrent_flags::share_mode); | │ │ │ │ │ -| test_set_after_add(torrent_flags::share_mode); | │ │ │ │ │ -| test_unset_after_add(torrent_flags::share_mode); | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_t_e_s_t_/_t_e_s_t___u_p_n_p_._c_p_p_:_1_5_6_ _ _ _ _ _|_s_t_o_r_e_ _t_h_e_ _l_o_g_ _a_n_d_ _v_e_r_i_f_y_ _t_h_a_t_ _s_o_m_e_ _k_e_y_ _m_e_s_s_a_g_e_s_ _a_r_e_ _t_h_e_r_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** ssttoorree tthhee lloogg aanndd vveerriiffyy tthhaatt ssoommee kkeeyy mmeessssaaggeess aarree tthheerree ********** | │ │ │ │ │ +|****** ....//tteesstt//tteesstt__uuppnnpp..ccpppp::115566 ****** | │ │ │ │ │ +|, portmap_protocol const protocol, error_code const& err | │ │ │ │ │ +| , portmap_transport, aux::listen_socket_handle const&) override | │ │ │ │ │ +| { | │ │ │ │ │ +| callback_info info = {mapping, port, err}; | │ │ │ │ │ +| callbacks.push_back(info); | │ │ │ │ │ +| std::cout << "mapping: " << static_cast(mapping) | │ │ │ │ │ +| << ", port: " << port << ", IP: " << ip | │ │ │ │ │ +| << ", proto: " << static_cast(protocol) | │ │ │ │ │ +| << ", error: \"" << err.message() << "\"\n"; | │ │ │ │ │ +| } | │ │ │ │ │ +| #ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ +| bool should_log_portmap(portmap_transport) const override | │ │ │ │ │ +| { | │ │ │ │ │ +| return true; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| void log_portmap(portmap_transport, char const* msg | │ │ │ │ │ +| , aux::listen_socket_handle const&) const override | │ │ │ │ │ +| { | │ │ │ │ │ +| std::cout << "UPnP: " << msg << std::endl; | │ │ │ │ │ |} | │ │ │ │ │ |#endif | │ │ │ │ │ +| }; | │ │ │ │ │ | | │ │ │ │ │ -|TORRENT_TEST(flag_apply_ip_filter) | │ │ │ │ │ +|ip_interface pick_upnp_interface() | │ │ │ │ │ |{ | │ │ │ │ │ -| // apply-ip-filter | │ │ │ │ │ -| test_add_and_get_flags(torrent_flags::apply_ip_filter); | │ │ │ │ │ -| test_set_after_add(torrent_flags::apply_ip_filter); | │ │ │ │ │ -| test_unset_after_add(torrent_flags::apply_ip_filter); | │ │ │ │ │ -|} | │ │ │ │ │ +| lt::io_context ios; | │ │ │ │ │ +| error_code ec; | │ │ │ │ │ +| std::vector const routes = enum_routes(ios, ec); | │ │ │ │ │ +| if (ec) | │ │ │ │ │ +| { | │ │ │ │ │ +| std::cerr << "failed to enumerate routes: " << ec.message() << '\n'; | │ │ │ │ │ +| TEST_CHECK(false); | │ │ │ │ │ +| return {}; | │ │ │ │ │ +| } | │ │ │ │ │ +| std::vector const ifs = enum_net_interfaces(ios, ec); | │ │ │ │ │ +| if (ec) | │ │ │ │ │ +| { | │ │ │ │ │ +| std::cerr << "failed to enumerate network interfaces: " << ec.message() << '\n'; | │ │ │ │ │ +| TEST_CHECK(false); | │ │ │ │ │ +| return {}; | │ │ │ │ │ +| } | │ │ │ │ │ +| int idx = 0; | │ │ │ │ │ +| for (auto const& face : ifs) | │ │ │ │ │ +| { | │ │ │ │ │ +| if (!face.interface_address.is_v4()) continue; | │ │ │ │ │ +| std::cout << " - " << idx | │ │ │ │ │ +| << ' ' << face.interface_address.to_string() | │ │ │ │ │ +| << ' ' << int(static_cast(face.state)) | │ │ │ │ │ +| << ' ' << static_cast(face.flags) | │ │ │ │ │ +|_ _ _ _<_<_ _'_ _'_ _<_<_ _f_a_c_e_._n_a_m_e_ _<_<_ _'_\_n_'_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_t_e_s_t_/_t_e_s_t___t_r_a_c_k_e_r_._c_p_p_:_6_0_ _ _ _|_t_e_s_t_ _s_c_r_a_p_e_ _r_e_q_u_e_s_t_s_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tteesstt ssccrraappee rreeqquueessttss ********** | │ │ │ │ │ +|_**_**_**_ _.._.._//_tt_ee_ss_tt_//_tt_ee_ss_tt____tt_rr_aa_cc_kk_ee_rr_.._cc_pp_pp_::_66_00_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_t_e_s_t_/_t_e_s_t___t_r_a_c_k_e_r_._c_p_p_:_6_1_ _ _ _|_t_e_s_t_ _p_a_r_s_e_ _p_e_e_r_s_6_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tteesstt ppaarrssee ppeeeerrss66 ********** | │ │ │ │ │ +|_**_**_**_ _.._.._//_tt_ee_ss_tt_//_tt_ee_ss_tt____tt_rr_aa_cc_kk_ee_rr_.._cc_pp_pp_::_66_11_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_t_e_s_t_/_t_e_s_t___t_r_a_c_k_e_r_._c_p_p_:_6_2_ _ _ _|_t_e_s_t_ _p_a_r_s_e_ _t_r_a_c_k_e_r_-_i_d_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tteesstt ppaarrssee ttrraacckkeerr--iidd ********** | │ │ │ │ │ +|_**_**_**_ _.._.._//_tt_ee_ss_tt_//_tt_ee_ss_tt____tt_rr_aa_cc_kk_ee_rr_.._cc_pp_pp_::_66_22_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_t_e_s_t_/_t_e_s_t___t_r_a_c_k_e_r_._c_p_p_:_6_3_ _ _ _|_t_e_s_t_ _p_a_r_s_e_ _f_a_i_l_u_r_e_-_r_e_a_s_o_n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tteesstt ppaarrssee ffaaiilluurree--rreeaassoonn ********** | │ │ │ │ │ +|_**_**_**_ _.._.._//_tt_ee_ss_tt_//_tt_ee_ss_tt____tt_rr_aa_cc_kk_ee_rr_.._cc_pp_pp_::_66_33_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_t_e_s_t_/_t_e_s_t___t_r_a_c_k_e_r_._c_p_p_:_6_4 |test all failure paths, including invalid bencoding not a dictionary no files entry in scrape response no info-hash entry in scrape | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_r_e_s_p_o_n_s_e_ _m_a_l_f_o_r_m_e_d_ _p_e_e_r_s_ _i_n_ _p_e_e_r_ _l_i_s_t_ _o_f_ _d_i_c_t_i_o_n_a_r_i_e_s_ _u_n_e_v_e_n_ _n_u_m_b_e_r_ _o_f_ _b_y_t_e_s_ _i_n_ _p_e_e_r_s_ _a_n_d_ _p_e_e_r_s_6_ _s_t_r_i_n_g_ _r_e_s_p_o_n_s_e_s_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tteesstt aallll ffaaiilluurree ppaatthhss,, iinncclluuddiinngg iinnvvaalliidd bbeennccooddiinngg nnoott aa ddiiccttiioonnaarryy nnoo ffiilleess eennttrryy iinn ssccrraappee rreessppoonnssee nnoo iinnffoo--hhaasshh eennttrryy iinn ssccrraappee rreessppoonnssee mmaallffoorrmmeedd ppeeeerrss iinn ppeeeerr lliisstt| │ │ │ │ │ +|ooff ddiiccttiioonnaarriieess uunneevveenn nnuummbbeerr ooff bbyytteess iinn ppeeeerrss aanndd ppeeeerrss66 ssttrriinngg rreessppoonnsseess ********** | │ │ │ │ │ +|****** ....//tteesstt//tteesstt__ttrraacckkeerr..ccpppp::6644 ****** | │ │ │ │ │ +|#include "test_utils.hpp" | │ │ │ │ │ +|#include "udp_tracker.hpp" | │ │ │ │ │ +|#include "settings.hpp" | │ │ │ │ │ +|#include "test_utils.hpp" | │ │ │ │ │ +|#include "libtorrent/alert.hpp" | │ │ │ │ │ +|#include "libtorrent/peer_info.hpp" // for peer_list_entry | │ │ │ │ │ +|#include "libtorrent/alert_types.hpp" | │ │ │ │ │ +|#include "libtorrent/session.hpp" | │ │ │ │ │ +|#include "libtorrent/session_params.hpp" | │ │ │ │ │ +|#include "libtorrent/error_code.hpp" | │ │ │ │ │ +|#include "libtorrent/tracker_manager.hpp" | │ │ │ │ │ +|#include "libtorrent/http_tracker_connection.hpp" // for parse_tracker_response | │ │ │ │ │ +|#include "libtorrent/torrent_info.hpp" | │ │ │ │ │ +|#include "libtorrent/announce_entry.hpp" | │ │ │ │ │ +|#include "libtorrent/torrent.hpp" | │ │ │ │ │ +|#include "libtorrent/aux_/path.hpp" | │ │ │ │ │ +|#include "libtorrent/socket_io.hpp" | │ │ │ │ │ | | │ │ │ │ │ -|TORRENT_TEST(flag_paused) | │ │ │ │ │ +|using namespace lt; | │ │ │ │ │ +| | │ │ │ │ │ +| | │ │ │ │ │ +|TORRENT_TEST(parse_hostname_peers) | │ │ │ │ │ |{ | │ │ │ │ │ -| // paused | │ │ │ │ │ -| test_add_and_get_flags(torrent_flags::paused); | │ │ │ │ │ +| char const response[] = "d5:peersld7:peer id20:aaaaaaaaaaaaaaaaaaaa" | │ │ │ │ │ +| "2:ip13:test_hostname4:porti1000eed" | │ │ │ │ │ +| "7:peer id20:bbbbabaababababababa2:ip12:another_host4:porti1001eeee"; | │ │ │ │ │ +| error_code ec; | │ │ │ │ │ +| tracker_response resp = parse_tracker_response(response | │ │ │ │ │ +| , ec, {}, sha1_hash()); | │ │ │ │ │ +| | │ │ │ │ │ +| TEST_EQUAL(ec, error_code()); | │ │ │ │ │ +| TEST_EQUAL(resp.peers.size(), 2); | │ │ │ │ │ +| if (resp.peers.size() == 2) | │ │ │ │ │ +| { | │ │ │ │ │ +| peer_entry const& e0 = resp.peers[0]; | │ │ │ │ │ +| peer_entry const& e1 = resp.peers[1]; | │ │ │ │ │ +| TEST_EQUAL(e0.hostname, "test_hostname"); | │ │ │ │ │ +| TEST_EQUAL(e0.port, 1000); | │ │ │ │ │ +| TEST_EQUAL(e0.pid, peer_id("aaaaaaaaaaaaaaaaaaaa")); | │ │ │ │ │ +| | │ │ │ │ │ +| TEST_EQUAL(e1.hostname, "another_host"); | │ │ │ │ │ +| TEST_EQUAL(e1.port, 1001); | │ │ │ │ │ +| TEST_EQUAL(e1.pid, peer_id("bbbbabaababababababa")); | │ │ │ │ │ +| } | │ │ │ │ │ |} | │ │ │ │ │ | | │ │ │ │ │ -|TORRENT_TEST(flag_auto_managed) | │ │ │ │ │ +|TORRENT_TEST(parse_peers4) | │ │ │ │ │ |{ | │ │ │ │ │ -| // auto-managed | │ │ │ │ │ -| test_add_and_get_flags(torrent_flags::auto_managed); | │ │ │ │ │ -| test_set_after_add(torrent_flags::auto_managed); | │ │ │ │ │ -| test_unset_after_add(torrent_flags::auto_managed); | │ │ │ │ │ +| char const response[] = "d5:peers12:\x01\x02\x03\x04\x30\x10" | │ │ │ │ │ +| "\x09\x08\x07\x06\x20\x10" "e"; | │ │ │ │ │ +|_ _e_r_r_o_r___c_o_d_e_ _e_c_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_t_e_s_t_/_t_e_s_t___b_l_o_o_m___f_i_l_t_e_r_._c_p_p_:|test size() | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_1_3_5_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tteesstt ssiizzee(()) ********** | │ │ │ │ │ +|_**_**_**_ _.._.._//_tt_ee_ss_tt_//_tt_ee_ss_tt____bb_ll_oo_oo_mm____ff_ii_ll_tt_ee_rr_.._cc_pp_pp_::_11_33_55_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_t_e_s_t_/_t_e_s_t___b_l_o_o_m___f_i_l_t_e_r_._c_p_p_:|test clear() | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_1_3_6_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tteesstt cclleeaarr(()) ********** | │ │ │ │ │ +|****** ....//tteesstt//tteesstt__bblloooomm__ffiilltteerr..ccpppp::113366 ****** | │ │ │ │ │ +|sha1_hash k("\x01\x00\x02\x00 "); | │ │ │ │ │ +| TEST_CHECK(!filter.find(k)); | │ │ │ │ │ +| filter.set(k); | │ │ │ │ │ +| TEST_CHECK(filter.find(k)); | │ │ │ │ │ +| | │ │ │ │ │ +| std::uint8_t compare[4] = { 0x16, 0xff, 0x55, 0xaa}; | │ │ │ │ │ +| | │ │ │ │ │ +| bits_out = filter.to_string(); | │ │ │ │ │ +| TEST_EQUAL(memcmp(compare, bits_out.c_str(), 4), 0); | │ │ │ │ │ |} | │ │ │ │ │ | | │ │ │ │ │ -|// super seeding mode is automatically turned off if we're not a seed | │ │ │ │ │ -|// since the posix_disk_io is not threaded, this will happen immediately | │ │ │ │ │ -|#if TORRENT_HAVE_MMAP | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_SUPERSEEDING | │ │ │ │ │ -|TORRENT_TEST(flag_super_seeding) | │ │ │ │ │ +|} // anonymous namespace | │ │ │ │ │ +| | │ │ │ │ │ +|TORRENT_TEST(bloom_filter) | │ │ │ │ │ |{ | │ │ │ │ │ -| // super-seeding | │ │ │ │ │ -| test_add_and_get_flags(torrent_flags::super_seeding); | │ │ │ │ │ -| test_unset_after_add(torrent_flags::super_seeding); | │ │ │ │ │ -| test_set_after_add(torrent_flags::super_seeding); | │ │ │ │ │ -|} | │ │ │ │ │ -|#endif | │ │ │ │ │ +| test_set_and_get(); | │ │ │ │ │ +| test_set_bits(); | │ │ │ │ │ +| test_count_zeroes(); | │ │ │ │ │ +| test_to_from_string(); | │ │ │ │ │ +| | │ │ │ │ │ +|_}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_a_l_e_r_t_._c_p_p_:_4_0_4_ _ _ _ _ _ _ _ _ _ _|_m_o_v_e_ _t_h_i_s_ _f_i_e_l_d_ _i_n_t_o_ _t_r_a_c_k_e_r___a_l_e_r_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** mmoovvee tthhiiss ffiieelldd iinnttoo ttrraacckkeerr__aalleerrtt ********** | │ │ │ │ │ +|****** ....//ssrrcc//aalleerrtt..ccpppp::440044 ****** | │ │ │ │ │ +| return torrent_alert::message() + ": state changed to: " | │ │ │ │ │ +| + state_str[state]; | │ │ │ │ │ |#endif | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -|TORRENT_TEST(flag_sequential_download) | │ │ │ │ │ +| tracker_error_alert::tracker_error_alert(aux::stack_allocator& alloc | │ │ │ │ │ +| , torrent_handle const& h, tcp::endpoint const& ep, int times | │ │ │ │ │ +| , protocol_version v, string_view u, operation_t const operation | │ │ │ │ │ +| , error_code const& e | │ │ │ │ │ +| , string_view m) | │ │ │ │ │ +| : tracker_alert(alloc, h, ep, u) | │ │ │ │ │ +| , times_in_row(times) | │ │ │ │ │ +| , error(e) | │ │ │ │ │ +| , op(operation) | │ │ │ │ │ +| , m_msg_idx(alloc.copy_string(m)) | │ │ │ │ │ +|#if TORRENT_ABI_VERSION == 1 | │ │ │ │ │ +| , status_code(e && e.category() == http_category() ? e.value() : -1) | │ │ │ │ │ +| , msg(m) | │ │ │ │ │ +|#endif | │ │ │ │ │ +|, version(v) | │ │ │ │ │ |{ | │ │ │ │ │ -| // sequential-download | │ │ │ │ │ -| test_add_and_get_flags(torrent_flags::sequential_download); | │ │ │ │ │ -| test_set_after_add(torrent_flags::sequential_download); | │ │ │ │ │ -| test_unset_after_add(torrent_flags::sequential_download); | │ │ │ │ │ -|_}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_t_e_s_t_/_t_e_s_t___f_l_a_g_s_._c_p_p_:_2_0_5 |this test is flaky, since the torrent will become ready before asking for the flags, and by then stop_when_ready will have been | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_c_l_e_a_r_e_d_ _t_e_s_t___a_d_d___a_n_d___g_e_t___f_l_a_g_s_(_t_o_r_r_e_n_t___f_l_a_g_s_:_:_s_t_o_p___w_h_e_n___r_e_a_d_y_)_;_ _s_e_t_t_i_n_g_ _s_t_o_p_-_w_h_e_n_-_r_e_a_d_y_ _w_h_e_n_ _a_l_r_e_a_d_y_ _s_t_o_p_p_e_d_ _h_a_s_ _n_o_ _e_f_f_e_c_t_._ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tthhiiss tteesstt iiss ffllaakkyy,, ssiinnccee tthhee ttoorrrreenntt wwiillll bbeeccoommee rreeaaddyy bbeeffoorree aasskkiinngg ffoorr tthhee ffllaaggss,, aanndd bbyy tthheenn ssttoopp__wwhheenn__rreeaaddyy wwiillll hhaavvee bbeeeenn cclleeaarreedd tteesstt__aadddd__aanndd__ggeett__ffllaaggss | │ │ │ │ │ -|((ttoorrrreenntt__ffllaaggss::::ssttoopp__wwhheenn__rreeaaddyy));; sseettttiinngg ssttoopp--wwhheenn--rreeaaddyy wwhheenn aallrreeaaddyy ssttooppppeedd hhaass nnoo eeffffeecctt.. ********** | │ │ │ │ │ -|_**_**_**_ _.._.._//_tt_ee_ss_tt_//_tt_ee_ss_tt____ff_ll_aa_gg_ss_.._cc_pp_pp_::_22_00_55_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_t_e_s_t_/_t_e_s_t___f_l_a_g_s_._c_p_p_:_2_0_9_ _ _ _ _|_c_h_a_n_g_e_ _t_o_ _a_ _d_i_f_f_e_r_e_n_t_ _t_e_s_t_ _s_e_t_u_p_._ _c_u_r_r_e_n_t_l_y_ _a_l_w_a_y_s_ _p_a_u_s_e_d_._ _t_e_s_t___s_e_t___a_f_t_e_r___a_d_d_(_t_o_r_r_e_n_t___f_l_a_g_s_:_:_s_t_o_p___w_h_e_n___r_e_a_d_y_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** cchhaannggee ttoo aa ddiiffffeerreenntt tteesstt sseettuupp.. ccuurrrreennttllyy aallwwaayyss ppaauusseedd.. tteesstt__sseett__aafftteerr__aadddd((ttoorrrreenntt__ffllaaggss::::ssttoopp__wwhheenn__rreeaaddyy));; ********** | │ │ │ │ │ -|****** ....//tteesstt//tteesstt__ffllaaggss..ccpppp::220099 ****** | │ │ │ │ │ -|test_set_after_add(torrent_flags::super_seeding); | │ │ │ │ │ -|} | │ │ │ │ │ +| TORRENT_ASSERT(!u.empty()); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| char const* tracker_error_alert::failure_reason() const | │ │ │ │ │ +| { | │ │ │ │ │ +| return m_alloc.get().ptr(m_msg_idx); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| std::string tracker_error_alert::message() const | │ │ │ │ │ +| { | │ │ │ │ │ +|#ifdef TORRENT_DISABLE_ALERT_MSG | │ │ │ │ │ +| return {}; | │ │ │ │ │ +|#else | │ │ │ │ │ +| char ret[400]; | │ │ │ │ │ +| std::snprintf(ret, sizeof(ret), "%s %s %s \"%s\" (%d)" | │ │ │ │ │ +| , tracker_alert::message().c_str() | │ │ │ │ │ +| , version == protocol_version::V1 ? "v1" : "v2" | │ │ │ │ │ +| , convert_from_native(error.message()).c_str(), error_message() | │ │ │ │ │ +| , times_in_row); | │ │ │ │ │ +| return ret; | │ │ │ │ │ |#endif | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| tracker_warning_alert::tracker_warning_alert(aux::stack_allocator& alloc | │ │ │ │ │ +| , torrent_handle const& h, tcp::endpoint const& ep | │ │ │ │ │ +| , string_view u, protocol_version v, string_view m) | │ │ │ │ │ +| : tracker_alert(alloc, h, ep, u) | │ │ │ │ │ +| , m_msg_idx(alloc.copy_string(m)) | │ │ │ │ │ +|_#_i_f_ _T_O_R_R_E_N_T___A_B_I___V_E_R_S_I_O_N_ _=_=_ _1_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_a_l_e_r_t_._c_p_p_:_4_3_8_ _ _ _ _ _ _ _ _ _ _|_m_o_v_e_ _t_h_i_s_ _i_n_t_o_ _t_r_a_c_k_e_r___a_l_e_r_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** mmoovvee tthhiiss iinnttoo ttrraacckkeerr__aalleerrtt ********** | │ │ │ │ │ +|****** ....//ssrrcc//aalleerrtt..ccpppp::443388 ****** | │ │ │ │ │ +|return {}; | │ │ │ │ │ +|#else | │ │ │ │ │ +| char ret[400]; | │ │ │ │ │ +| std::snprintf(ret, sizeof(ret), "%s %s %s \"%s\" (%d)" | │ │ │ │ │ +| , tracker_alert::message().c_str() | │ │ │ │ │ +| , version == protocol_version::V1 ? "v1" : "v2" | │ │ │ │ │ +| , convert_from_native(error.message()).c_str(), error_message() | │ │ │ │ │ +| , times_in_row); | │ │ │ │ │ +| return ret; | │ │ │ │ │ |#endif | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -|TORRENT_TEST(flag_sequential_download) | │ │ │ │ │ +| tracker_warning_alert::tracker_warning_alert(aux::stack_allocator& alloc | │ │ │ │ │ +| , torrent_handle const& h, tcp::endpoint const& ep | │ │ │ │ │ +| , string_view u, protocol_version v, string_view m) | │ │ │ │ │ +| : tracker_alert(alloc, h, ep, u) | │ │ │ │ │ +| , m_msg_idx(alloc.copy_string(m)) | │ │ │ │ │ +|#if TORRENT_ABI_VERSION == 1 | │ │ │ │ │ +| , msg(m) | │ │ │ │ │ +|#endif | │ │ │ │ │ +|, version(v) | │ │ │ │ │ |{ | │ │ │ │ │ -| // sequential-download | │ │ │ │ │ -| test_add_and_get_flags(torrent_flags::sequential_download); | │ │ │ │ │ -| test_set_after_add(torrent_flags::sequential_download); | │ │ │ │ │ -| test_unset_after_add(torrent_flags::sequential_download); | │ │ │ │ │ -|} | │ │ │ │ │ +| TORRENT_ASSERT(!u.empty()); | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -|// the stop when ready flag will be cleared when the torrent is ready to start | │ │ │ │ │ -|// downloading. | │ │ │ │ │ -|// since the posix_disk_io is not threaded, this will happen immediately | │ │ │ │ │ -|#if TORRENT_HAVE_MMAP | │ │ │ │ │ -|TORRENT_TEST(flag_stop_when_ready) | │ │ │ │ │ -|{ | │ │ │ │ │ -| // stop-when-ready | │ │ │ │ │ -|test_unset_after_add(torrent_flags::stop_when_ready); | │ │ │ │ │ -|} | │ │ │ │ │ +| char const* tracker_warning_alert::warning_message() const | │ │ │ │ │ +| { | │ │ │ │ │ +| return m_alloc.get().ptr(m_msg_idx); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| std::string tracker_warning_alert::message() const | │ │ │ │ │ +| { | │ │ │ │ │ +|#ifdef TORRENT_DISABLE_ALERT_MSG | │ │ │ │ │ +| return {}; | │ │ │ │ │ +|#else | │ │ │ │ │ +| return tracker_alert::message() + (version == protocol_version::V1 ? " v1" : " v2") + " warning: " + warning_message(); | │ │ │ │ │ |#endif | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -|TORRENT_TEST(flag_disable_dht) | │ │ │ │ │ -|{ | │ │ │ │ │ -| test_add_and_get_flags(torrent_flags::disable_dht); | │ │ │ │ │ -| test_set_after_add(torrent_flags::disable_dht); | │ │ │ │ │ -| test_unset_after_add(torrent_flags::disable_dht); | │ │ │ │ │ -|} | │ │ │ │ │ +| scrape_reply_alert::scrape_reply_alert(aux::stack_allocator& alloc | │ │ │ │ │ +| , torrent_handle const& h, tcp::endpoint const& ep | │ │ │ │ │ +| , int incomp, int comp, string_view u, protocol_version const v) | │ │ │ │ │ +| : tracker_alert(alloc, h, ep, u) | │ │ │ │ │ +| , incomplete(incomp) | │ │ │ │ │ +|_ _ _,_ _c_o_m_p_l_e_t_e_(_c_o_m_p_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_a_l_e_r_t_._c_p_p_:_4_6_4_ _ _ _ _ _ _ _ _ _ _|_m_o_v_e_ _t_h_i_s_ _i_n_t_o_ _t_r_a_c_k_e_r___a_l_e_r_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** mmoovvee tthhiiss iinnttoo ttrraacckkeerr__aalleerrtt ********** | │ │ │ │ │ +|****** ....//ssrrcc//aalleerrtt..ccpppp::446644 ****** | │ │ │ │ │ +|char const* tracker_warning_alert::warning_message() const | │ │ │ │ │ +| { | │ │ │ │ │ +| return m_alloc.get().ptr(m_msg_idx); | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ +| std::string tracker_warning_alert::message() const | │ │ │ │ │ +| { | │ │ │ │ │ +|#ifdef TORRENT_DISABLE_ALERT_MSG | │ │ │ │ │ +| return {}; | │ │ │ │ │ +|#else | │ │ │ │ │ +| return tracker_alert::message() + (version == protocol_version::V1 ? " v1" : " v2") + " warning: " + warning_message(); | │ │ │ │ │ +|#endif | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -|TORRENT_TEST(flag_disable_lsd) | │ │ │ │ │ +| scrape_reply_alert::scrape_reply_alert(aux::stack_allocator& alloc | │ │ │ │ │ +| , torrent_handle const& h, tcp::endpoint const& ep | │ │ │ │ │ +| , int incomp, int comp, string_view u, protocol_version const v) | │ │ │ │ │ +| : tracker_alert(alloc, h, ep, u) | │ │ │ │ │ +| , incomplete(incomp) | │ │ │ │ │ +| , complete(comp) | │ │ │ │ │ +|, version(v) | │ │ │ │ │ |{ | │ │ │ │ │ -| test_add_and_get_flags(torrent_flags::disable_lsd); | │ │ │ │ │ -| test_set_after_add(torrent_flags::disable_lsd); | │ │ │ │ │ -| test_unset_after_add(torrent_flags::disable_lsd); | │ │ │ │ │ -|} | │ │ │ │ │ +| TORRENT_ASSERT(!u.empty()); | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -|TORRENT_TEST(flag_disable_pex) | │ │ │ │ │ -|{ | │ │ │ │ │ -| test_add_and_get_flags(torrent_flags::disable_pex); | │ │ │ │ │ -| test_set_after_add(torrent_flags::disable_pex); | │ │ │ │ │ -| test_unset_after_add(torrent_flags::disable_pex); | │ │ │ │ │ -|_}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_t_e_s_t_/_t_e_s_t___m_e_r_k_l_e___t_r_e_e_._c_p_p_: |use structured bindings in C++17 | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_2_3_3_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** uussee ssttrruuccttuurreedd bbiinnddiinnggss iinn CC++++1177 ********** | │ │ │ │ │ -|****** ....//tteesstt//tteesstt__mmeerrkkllee__ttrreeee..ccpppp::223333 ****** | │ │ │ │ │ -|mask[std::size_t(i)] = true; | │ │ │ │ │ -| t.load_sparse_tree(span(f).subspan(first_piece, num_pieces), mask, empty_verified); | │ │ │ │ │ -| int const end_piece_layer = first_piece + merkle_num_leafs(num_pieces); | │ │ │ │ │ -| for (int i = 0; i < end_piece_layer; ++i) | │ │ │ │ │ -| { | │ │ │ │ │ -| TEST_CHECK(t.has_node(i)); | │ │ │ │ │ -| TEST_CHECK(t.compare_node(i, f[i])); | │ │ │ │ │ -| } | │ │ │ │ │ -| for (int i = end_piece_layer; i < num_nodes; ++i) | │ │ │ │ │ -| { | │ │ │ │ │ -| TEST_CHECK(!t.has_node(i)); | │ │ │ │ │ -| } | │ │ │ │ │ +| std::string scrape_reply_alert::message() const | │ │ │ │ │ +| { | │ │ │ │ │ +|#ifdef TORRENT_DISABLE_ALERT_MSG | │ │ │ │ │ +| return {}; | │ │ │ │ │ +|#else | │ │ │ │ │ +| char ret[400]; | │ │ │ │ │ +| std::snprintf(ret, sizeof(ret), "%s %s scrape reply: %d %d" | │ │ │ │ │ +| , tracker_alert::message().c_str() | │ │ │ │ │ +| , version == protocol_version::V1 ? "v1" : "v2" | │ │ │ │ │ +| , incomplete, complete); | │ │ │ │ │ +| return ret; | │ │ │ │ │ +|#endif | │ │ │ │ │ | } | │ │ │ │ │ -|} | │ │ │ │ │ | | │ │ │ │ │ -|namespace { | │ │ │ │ │ -|void test_roundtrip(aux::merkle_tree const& t | │ │ │ │ │ -| , int const block_count | │ │ │ │ │ -| , int const blocks_per_piece) | │ │ │ │ │ +| scrape_failed_alert::scrape_failed_alert(aux::stack_allocator& alloc | │ │ │ │ │ +| , torrent_handle const& h, tcp::endpoint const& ep | │ │ │ │ │ +| , string_view u, protocol_version const v, error_code const& e) | │ │ │ │ │ +| : tracker_alert(alloc, h, ep, u) | │ │ │ │ │ +| , error(e) | │ │ │ │ │ +| , m_msg_idx() | │ │ │ │ │ +|#if TORRENT_ABI_VERSION == 1 | │ │ │ │ │ +| , msg(convert_from_native(e.message())) | │ │ │ │ │ +|_#_e_n_d_i_f_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_a_l_e_r_t_._c_p_p_:_4_9_3_ _ _ _ _ _ _ _ _ _ _|_m_o_v_e_ _t_h_i_s_ _i_n_t_o_ _t_r_a_c_k_e_r___a_l_e_r_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** mmoovvee tthhiiss iinnttoo ttrraacckkeerr__aalleerrtt ********** | │ │ │ │ │ +|****** ....//ssrrcc//aalleerrtt..ccpppp::449933 ****** | │ │ │ │ │ +|return {}; | │ │ │ │ │ +|#else | │ │ │ │ │ +| char ret[400]; | │ │ │ │ │ +| std::snprintf(ret, sizeof(ret), "%s %s scrape reply: %d %d" | │ │ │ │ │ +| , tracker_alert::message().c_str() | │ │ │ │ │ +| , version == protocol_version::V1 ? "v1" : "v2" | │ │ │ │ │ +| , incomplete, complete); | │ │ │ │ │ +| return ret; | │ │ │ │ │ +|#endif | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| scrape_failed_alert::scrape_failed_alert(aux::stack_allocator& alloc | │ │ │ │ │ +| , torrent_handle const& h, tcp::endpoint const& ep | │ │ │ │ │ +| , string_view u, protocol_version const v, error_code const& e) | │ │ │ │ │ +| : tracker_alert(alloc, h, ep, u) | │ │ │ │ │ +| , error(e) | │ │ │ │ │ +| , m_msg_idx() | │ │ │ │ │ +|#if TORRENT_ABI_VERSION == 1 | │ │ │ │ │ +| , msg(convert_from_native(e.message())) | │ │ │ │ │ +|#endif | │ │ │ │ │ +|, version(v) | │ │ │ │ │ |{ | │ │ │ │ │ -|aux::vector mask; | │ │ │ │ │ -|std::vector tree; | │ │ │ │ │ -| std::tie(tree, mask) = t.build_sparse_vector(); | │ │ │ │ │ +| TORRENT_ASSERT(!u.empty()); | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -| aux::merkle_tree t2(block_count, blocks_per_piece, f[0].data()); | │ │ │ │ │ -| t2.load_sparse_tree(tree, mask, empty_verified); | │ │ │ │ │ +| scrape_failed_alert::scrape_failed_alert(aux::stack_allocator& alloc | │ │ │ │ │ +| , torrent_handle const& h, tcp::endpoint const& ep | │ │ │ │ │ +| , string_view u, string_view m) | │ │ │ │ │ +| : tracker_alert(alloc, h, ep, u) | │ │ │ │ │ +| , error(errors::tracker_failure) | │ │ │ │ │ +| , m_msg_idx(alloc.copy_string(m)) | │ │ │ │ │ +|#if TORRENT_ABI_VERSION == 1 | │ │ │ │ │ +| , msg(m) | │ │ │ │ │ +|#endif | │ │ │ │ │ +| { | │ │ │ │ │ +| TORRENT_ASSERT(!u.empty()); | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -| TEST_CHECK(t.build_vector() == t2.build_vector()); | │ │ │ │ │ -| for (int i = 0; i < int(t.size()); ++i) | │ │ │ │ │ +| char const* scrape_failed_alert::error_message() const | │ │ │ │ │ | { | │ │ │ │ │ -| TEST_EQUAL(t[i], t2[i]); | │ │ │ │ │ -| TEST_EQUAL(t.has_node(i), t2.has_node(i)); | │ │ │ │ │ +| if (m_msg_idx == aux::allocation_slot()) return ""; | │ │ │ │ │ +| else return m_alloc.get().ptr(m_msg_idx); | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -| if (!t.has_node(i)) | │ │ │ │ │ -| TEST_CHECK(t[i].is_all_zeros()); | │ │ │ │ │ -| if (!t2.has_node(i)) | │ │ │ │ │ -| TEST_CHECK(t2[i].is_all_zeros()); | │ │ │ │ │ +| std::string scrape_failed_alert::message() const | │ │ │ │ │ +| { | │ │ │ │ │ +|#ifdef TORRENT_DISABLE_ALERT_MSG | │ │ │ │ │ +| return {}; | │ │ │ │ │ +|#else | │ │ │ │ │ +| return tracker_alert::message() + " scrape failed: " + error_message(); | │ │ │ │ │ +|_#_e_n_d_i_f_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_a_l_e_r_t_._c_p_p_:_5_3_2_ _ _ _ _ _ _ _ _ _ _|_m_o_v_e_ _t_h_i_s_ _f_i_e_l_d_ _i_n_t_o_ _t_r_a_c_k_e_r___a_l_e_r_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** mmoovvee tthhiiss ffiieelldd iinnttoo ttrraacckkeerr__aalleerrtt ********** | │ │ │ │ │ +|****** ....//ssrrcc//aalleerrtt..ccpppp::553322 ****** | │ │ │ │ │ +|char const* scrape_failed_alert::error_message() const | │ │ │ │ │ +| { | │ │ │ │ │ +| if (m_msg_idx == aux::allocation_slot()) return ""; | │ │ │ │ │ +| else return m_alloc.get().ptr(m_msg_idx); | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -| TEST_CHECK(t.compare_node(i, t2[i])); | │ │ │ │ │ -| TEST_CHECK(t2.compare_node(i, t[i])); | │ │ │ │ │ +| std::string scrape_failed_alert::message() const | │ │ │ │ │ +| { | │ │ │ │ │ +|#ifdef TORRENT_DISABLE_ALERT_MSG | │ │ │ │ │ +| return {}; | │ │ │ │ │ +|#else | │ │ │ │ │ +| return tracker_alert::message() + " scrape failed: " + error_message(); | │ │ │ │ │ +|#endif | │ │ │ │ │ | } | │ │ │ │ │ -|} | │ │ │ │ │ -|} | │ │ │ │ │ | | │ │ │ │ │ -|TORRENT_TEST(roundtrip_empty_tree) | │ │ │ │ │ +| tracker_reply_alert::tracker_reply_alert(aux::stack_allocator& alloc | │ │ │ │ │ +| , torrent_handle const& h, tcp::endpoint const& ep | │ │ │ │ │ +| , int np, protocol_version v, string_view u) | │ │ │ │ │ +| : tracker_alert(alloc, h, ep, u) | │ │ │ │ │ +| , num_peers(np) | │ │ │ │ │ +|, version(v) | │ │ │ │ │ |{ | │ │ │ │ │ -| aux::merkle_tree t(num_blocks, 1, f[0].data()); | │ │ │ │ │ -| test_roundtrip(t, num_blocks, 1); | │ │ │ │ │ -|} | │ │ │ │ │ +| TORRENT_ASSERT(!u.empty()); | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -|_T_O_R_R_E_N_T___T_E_S_T_(_r_o_u_n_d_t_r_i_p___f_u_l_l___t_r_e_e_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_t_e_s_t_/_t_e_s_t___m_e_r_k_l_e___t_r_e_e_._c_p_p_: |add test for load_piece_layer() | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_9_3_8_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** aadddd tteesstt ffoorr llooaadd__ppiieeccee__llaayyeerr(()) ********** | │ │ │ │ │ -|_**_**_**_ _.._.._//_tt_ee_ss_tt_//_tt_ee_ss_tt____mm_ee_rr_kk_ll_ee____tt_rr_ee_ee_.._cc_pp_pp_::_99_33_88_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_t_e_s_t_/_t_e_s_t___m_e_r_k_l_e___t_r_e_e_._c_p_p_: |add test for add_hashes() with an odd number of blocks | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_9_3_9_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** aadddd tteesstt ffoorr aadddd__hhaasshheess(()) wwiitthh aann oodddd nnuummbbeerr ooff bblloocckkss ********** | │ │ │ │ │ -|_**_**_**_ _.._.._//_tt_ee_ss_tt_//_tt_ee_ss_tt____mm_ee_rr_kk_ll_ee____tt_rr_ee_ee_.._cc_pp_pp_::_99_33_99_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_t_e_s_t_/_t_e_s_t___m_e_r_k_l_e___t_r_e_e_._c_p_p_: |add test for set_block() (setting the last block) with an odd number of blocks | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_9_4_0_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** aadddd tteesstt ffoorr sseett__bblloocckk(()) ((sseettttiinngg tthhee llaasstt bblloocckk)) wwiitthh aann oodddd nnuummbbeerr ooff bblloocckkss ********** | │ │ │ │ │ -|****** ....//tteesstt//tteesstt__mmeerrkkllee__ttrreeee..ccpppp::994400 ****** | │ │ │ │ │ -| for (int i = 0; i < 7; ++i) | │ │ │ │ │ -| TEST_EQUAL(t[i], f[i]); | │ │ │ │ │ +| std::string tracker_reply_alert::message() const | │ │ │ │ │ +| { | │ │ │ │ │ +|#ifdef TORRENT_DISABLE_ALERT_MSG | │ │ │ │ │ +| return {}; | │ │ │ │ │ +|#else | │ │ │ │ │ +| char ret[400]; | │ │ │ │ │ +| std::snprintf(ret, sizeof(ret), "%s %s received peers: %d" | │ │ │ │ │ +| , tracker_alert::message().c_str() | │ │ │ │ │ +| , version == protocol_version::V1 ? "v1" : "v2" | │ │ │ │ │ +| , num_peers); | │ │ │ │ │ +| return ret; | │ │ │ │ │ +|#endif | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -| // use a proof that ties the first piece node 3 (since we don't need it all | │ │ │ │ │ -| // the way to the root). | │ │ │ │ │ -| auto const result = t.add_hashes(127, pdiff(1), range(f, 127, 4), build_proof(f, 31, 3)); | │ │ │ │ │ -| TEST_CHECK(result); | │ │ │ │ │ +| dht_reply_alert::dht_reply_alert(aux::stack_allocator& alloc | │ │ │ │ │ +| , torrent_handle const& h | │ │ │ │ │ +| , int np) | │ │ │ │ │ +| : tracker_alert(alloc, h, {}, "") | │ │ │ │ │ +| , num_peers(np) | │ │ │ │ │ +| {} | │ │ │ │ │ | | │ │ │ │ │ -| auto const& res = *result; | │ │ │ │ │ -| TEST_EQUAL(res.passed.size(), 0); | │ │ │ │ │ -| TEST_EQUAL(res.failed.size(), 0); | │ │ │ │ │ +| std::string dht_reply_alert::message() const | │ │ │ │ │ +| { | │ │ │ │ │ +|#ifdef TORRENT_DISABLE_ALERT_MSG | │ │ │ │ │ +| return {}; | │ │ │ │ │ +|_#_e_l_s_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_a_l_e_r_t_._c_p_p_:_5_7_6_ _ _ _ _ _ _ _ _ _ _|_m_o_v_e_ _t_h_i_s_ _t_o_ _t_r_a_c_k_e_r___a_l_e_r_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** mmoovvee tthhiiss ttoo ttrraacckkeerr__aalleerrtt ********** | │ │ │ │ │ +|****** ....//ssrrcc//aalleerrtt..ccpppp::557766 ****** | │ │ │ │ │ +|, num_peers(np) | │ │ │ │ │ +| {} | │ │ │ │ │ | | │ │ │ │ │ -| for (int i = 127; i < 127 + 4; ++i) | │ │ │ │ │ -| TEST_CHECK(t[i] == f[i]); | │ │ │ │ │ +| std::string dht_reply_alert::message() const | │ │ │ │ │ +| { | │ │ │ │ │ +|#ifdef TORRENT_DISABLE_ALERT_MSG | │ │ │ │ │ +| return {}; | │ │ │ │ │ +|#else | │ │ │ │ │ +| char ret[400]; | │ │ │ │ │ +| std::snprintf(ret, sizeof(ret), "%s received DHT peers: %d" | │ │ │ │ │ +| , tracker_alert::message().c_str(), num_peers); | │ │ │ │ │ +| return ret; | │ │ │ │ │ +|#endif | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -| TEST_CHECK(t.verified_leafs() == none_set(num_blocks)); | │ │ │ │ │ -|} | │ │ │ │ │ +| tracker_announce_alert::tracker_announce_alert(aux::stack_allocator& alloc | │ │ │ │ │ +| , torrent_handle const& h, tcp::endpoint const& ep, string_view u | │ │ │ │ │ +| , protocol_version const v, event_t const e) | │ │ │ │ │ +| : tracker_alert(alloc, h, ep, u) | │ │ │ │ │ +| , event(e) | │ │ │ │ │ +|, version(v) | │ │ │ │ │ +|{ | │ │ │ │ │ +| TORRENT_ASSERT(!u.empty()); | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_s_r_c_/_p_e_e_r___c_o_n_n_e_c_t_i_o_n_._c_p_p_: |this should be the global download rate | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_1_0_9_1_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tthhiiss sshhoouulldd bbee tthhee gglloobbaall ddoowwnnllooaadd rraattee ********** | │ │ │ │ │ -|****** ....//ssrrcc//ppeeeerr__ccoonnnneeccttiioonn..ccpppp::11009911 ****** | │ │ │ │ │ -| int rate = 0; | │ │ │ │ │ +| std::string tracker_announce_alert::message() const | │ │ │ │ │ +| { | │ │ │ │ │ +|#ifdef TORRENT_DISABLE_ALERT_MSG | │ │ │ │ │ +| return {}; | │ │ │ │ │ +|#else | │ │ │ │ │ +| static const char* const event_str[] = {"none", "completed", "started", "stopped", "paused"}; | │ │ │ │ │ +| return tracker_alert::message() | │ │ │ │ │ +| + (version == protocol_version::V1 ? " v1" : " v2") | │ │ │ │ │ +| + " sending announce (" + event_str[static_cast(event)] + ")"; | │ │ │ │ │ +|#endif | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -| // if we haven't received any data recently, the current download rate | │ │ │ │ │ -| // is not representative | │ │ │ │ │ -| if (aux::time_now() - m_last_piece.get(m_connect) > seconds(30) && m_download_rate_peak > 0) | │ │ │ │ │ -| { | │ │ │ │ │ -| rate = m_download_rate_peak; | │ │ │ │ │ -| } | │ │ │ │ │ -| else if (aux::time_now() - m_last_unchoked.get(m_connect) < seconds(5) | │ │ │ │ │ -| && m_statistics.total_payload_upload() < 2 * 0x4000) | │ │ │ │ │ -| { | │ │ │ │ │ -| // if we're have only been unchoked for a short period of time, | │ │ │ │ │ -| // we don't know what rate we can get from this peer. Instead of assuming | │ │ │ │ │ -| // the lowest possible rate, assume the average. | │ │ │ │ │ +| hash_failed_alert::hash_failed_alert( | │ │ │ │ │ +| aux::stack_allocator& alloc | │ │ │ │ │ +| , torrent_handle const& h | │ │ │ │ │ +| , piece_index_t index) | │ │ │ │ │ +| : torrent_alert(alloc, h) | │ │ │ │ │ +| , piece_index(index) | │ │ │ │ │ +| { | │ │ │ │ │ +| TORRENT_ASSERT(index >= piece_index_t(0)); | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -| int peers_with_requests = int(stats_counters()[counters::num_peers_down_requests]); | │ │ │ │ │ -| // avoid division by 0 | │ │ │ │ │ -| if (peers_with_requests == 0) peers_with_requests = 1; | │ │ │ │ │ +| std::string hash_failed_alert::message() const | │ │ │ │ │ +| { | │ │ │ │ │ +|#ifdef TORRENT_DISABLE_ALERT_MSG | │ │ │ │ │ +|_ _ _r_e_t_u_r_n_ _{_}_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_u_t_p___s_t_r_e_a_m_._c_p_p_:_1_4_6_7_ _ _ _ _|_t_h_i_s_ _l_o_o_p_ _i_s_ _n_o_t_ _v_e_r_y_ _e_f_f_i_c_i_e_n_t_._ _I_t_ _c_o_u_l_d_ _b_e_ _f_i_x_e_d_ _b_y_ _h_a_v_i_n_g_ _a_ _s_e_p_a_r_a_t_e_ _l_i_s_t_ _o_f_ _s_e_q_u_e_n_c_e_ _n_u_m_b_e_r_s_ _t_h_a_t_ _n_e_e_d_ _r_e_s_e_n_d_i_n_g_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tthhiiss lloooopp iiss nnoott vveerryy eeffffiicciieenntt.. IItt ccoouulldd bbee ffiixxeedd bbyy hhaavviinngg aa sseeppaarraattee lliisstt ooff sseeqquueennccee nnuummbbeerrss tthhaatt nneeeedd rreesseennddiinngg ********** | │ │ │ │ │ +|****** ....//ssrrcc//uuttpp__ssttrreeaamm..ccpppp::11446677 ****** | │ │ │ │ │ +|#endif | │ │ │ │ │ | | │ │ │ │ │ -|rate = t->statistics().transfer_rate(stat::download_payload) / peers_with_requests; | │ │ │ │ │ -|} | │ │ │ │ │ -| else | │ │ │ │ │ +| if (m_stalled) | │ │ │ │ │ +| { | │ │ │ │ │ +| if (flags & pkt_ack) | │ │ │ │ │ +| defer_ack(); | │ │ │ │ │ +| return false; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| // m_out_eof means we're trying to close the write side of this socket, | │ │ │ │ │ +| // we need to flush all payload before we can send the FIN packet, so don't | │ │ │ │ │ +| // store any payload in the nagle packet | │ │ │ │ │ +| bool const force = (flags & pkt_ack) || (flags & pkt_fin) || m_out_eof; | │ │ │ │ │ +| | │ │ │ │ │ +| // when we want to close the outgoing stream, we need to send the | │ │ │ │ │ +| // remaining nagle packet even though it won't fill a packet. | │ │ │ │ │ +| bool const force_flush_nagle = m_out_eof && m_write_buffer_size; | │ │ │ │ │ +| | │ │ │ │ │ +| // first see if we need to resend any packets | │ │ │ │ │ +| | │ │ │ │ │ +|for (int i = (m_acked_seq_nr + 1) & ACK_MASK; i != m_seq_nr; i = (i + 1) & ACK_MASK) | │ │ │ │ │ +|{ | │ │ │ │ │ +| packet* p = m_outbuf.at(aux::numeric_cast(i)); | │ │ │ │ │ +| if (!p) continue; | │ │ │ │ │ +| if (!p->need_resend) continue; | │ │ │ │ │ +| if (!resend_packet(p)) | │ │ │ │ │ | { | │ │ │ │ │ -| // current download rate in bytes per seconds | │ │ │ │ │ -| rate = m_statistics.transfer_rate(stat::download_payload); | │ │ │ │ │ +| // we couldn't resend the packet. It probably doesn't | │ │ │ │ │ +| // fit in our cwnd. If force is set, we need to continue | │ │ │ │ │ +| // to send our packet anyway, if we don't have force set, | │ │ │ │ │ +| // we might as well return | │ │ │ │ │ +| if (!force) return false; | │ │ │ │ │ +| // resend_packet might have failed | │ │ │ │ │ +| if (state() == state_t::error_wait || state() == state_t::deleting) return false; | │ │ │ │ │ +| if (m_stalled) return false; | │ │ │ │ │ +| break; | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -| // avoid division by zero | │ │ │ │ │ -| if (rate < 50) rate = 50; | │ │ │ │ │ +| // don't fast-resend this packet | │ │ │ │ │ +| if (m_fast_resend_seq_nr == i) | │ │ │ │ │ +| m_fast_resend_seq_nr = (m_fast_resend_seq_nr + 1) & ACK_MASK; | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -| // average of current rate and peak | │ │ │ │ │ -|// rate = (rate + m_download_rate_peak) / 2; | │ │ │ │ │ +| // MTU DISCOVERY | │ │ │ │ │ | | │ │ │ │ │ -| return milliseconds((m_outstanding_bytes + extra_bytes | │ │ │ │ │ -| + m_queued_time_critical * t->block_size() * 1000) / rate); | │ │ │ │ │ +| // under these conditions, the next packet we send should be an MTU probe. | │ │ │ │ │ +| // MTU probes get to use the mid-point packet size, whereas other packets | │ │ │ │ │ +| // use a conservative packet size of the largest known to work. The reason | │ │ │ │ │ +| // for the cwnd condition is to make sure the probe is surrounded by non- | │ │ │ │ │ +| // probes, to be able to distinguish a loss of the probe vs. just loss in | │ │ │ │ │ +|_ _/_/_ _g_e_n_e_r_a_l_._ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_c_r_e_a_t_e___t_o_r_r_e_n_t_._c_p_p_:_6_1_1_ _|_t_h_i_s_ _c_a_n_ _b_e_ _o_p_t_i_m_i_z_e_d_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tthhiiss ccaann bbee ooppttiimmiizzeedd ********** | │ │ │ │ │ +|****** ....//ssrrcc//ccrreeaattee__ttoorrrreenntt..ccpppp::661111 ****** | │ │ │ │ │ +|std::string& attr = e["attr"].string(); | │ │ │ │ │ +| if (flags & file_storage::flag_pad_file) attr += 'p'; | │ │ │ │ │ +| if (flags & file_storage::flag_hidden) attr += 'h'; | │ │ │ │ │ +| if (flags & file_storage::flag_executable) attr += 'x'; | │ │ │ │ │ +| if (include_symlinks && (flags & file_storage::flag_symlink)) attr += 'l'; | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -| void peer_connection::add_stat(std::int64_t const downloaded, std::int64_t const uploaded) | │ │ │ │ │ +| void add_symlink_path(entry& e, std::string symlink_path) | │ │ │ │ │ | { | │ │ │ │ │ -| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ -| m_statistics.add_stat(downloaded, uploaded); | │ │ │ │ │ +| entry& sympath_e = e["symlink path"]; | │ │ │ │ │ +| | │ │ │ │ │ +| std::string const link = lexically_relative("", symlink_path); | │ │ │ │ │ +| for (auto elems = lsplit_path(link); !elems.first.empty(); | │ │ │ │ │ +| elems = lsplit_path(elems.second)) | │ │ │ │ │ +| sympath_e.list().emplace_back(elems.first); | │ │ │ │ │ | } | │ │ │ │ │ +|} | │ │ │ │ │ | | │ │ │ │ │ -| sha1_hash peer_connection::associated_info_hash() const | │ │ │ │ │ +| std::vector create_torrent::generate_buf() const | │ │ │ │ │ | { | │ │ │ │ │ -| std::shared_ptr t = associated_torrent().lock(); | │ │ │ │ │ -| TORRENT_ASSERT(t); | │ │ │ │ │ -| auto const& ih = t->info_hash(); | │ │ │ │ │ -| // if protocol_v2 is set on the peer, this better be a v2 torrent, | │ │ │ │ │ -|_ _ _/_/_ _o_t_h_e_r_w_i_s_e_ _s_o_m_e_t_h_i_n_g_ _i_s_n_'_t_ _r_i_g_h_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_s_r_c_/_p_e_e_r___c_o_n_n_e_c_t_i_o_n_._c_p_p_: |sort the allowed fast set in priority order | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_3_5_2_0_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** ssoorrtt tthhee aalllloowweedd ffaasstt sseett iinn pprriioorriittyy oorrddeerr ********** | │ │ │ │ │ -|****** ....//ssrrcc//ppeeeerr__ccoonnnneeccttiioonn..ccpppp::33552200 ****** | │ │ │ │ │ -| // if the peer has the piece and we want | │ │ │ │ │ -| // to download it, request it | │ │ │ │ │ -| if (index < m_have_piece.end_index() | │ │ │ │ │ -| && m_have_piece[index] | │ │ │ │ │ -| && !t->has_piece_passed(index) | │ │ │ │ │ -| && t->valid_metadata() | │ │ │ │ │ -| && t->has_picker() | │ │ │ │ │ -| && t->picker().piece_priority(index) > dont_download) | │ │ │ │ │ +|std::vector ret; | │ │ │ │ │ +|bencode(std::back_inserter(ret), generate()); | │ │ │ │ │ +| return ret; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| entry create_torrent::generate() const | │ │ │ │ │ +| { | │ │ │ │ │ +| if (m_files.num_files() == 0 || m_files.total_size() == 0) | │ │ │ │ │ +| aux::throw_ex(errors::torrent_missing_file_tree); | │ │ │ │ │ +| | │ │ │ │ │ +| // if all v2 hashes are set correctly, generate the v2 parts of the | │ │ │ │ │ +| // torrent | │ │ │ │ │ +| bool const make_v2 = validate_v2_hashes(m_files, m_file_piece_hash); | │ │ │ │ │ +| bool const make_v1 = validate_v1_hashes(m_files, m_piece_hash); | │ │ │ │ │ +| | │ │ │ │ │ +| // if neither v1 nor v2 hashes were set, we can't create a torrent | │ │ │ │ │ +| if (!make_v1 && !make_v2) | │ │ │ │ │ +| aux::throw_ex(errors::invalid_hash_entry); | │ │ │ │ │ +| | │ │ │ │ │ +| TORRENT_ASSERT(m_files.piece_length() > 0); | │ │ │ │ │ +| | │ │ │ │ │ +| entry dict; | │ │ │ │ │ +| | │ │ │ │ │ +| if (!m_urls.empty()) dict["announce"] = m_urls.front().first; | │ │ │ │ │ +| | │ │ │ │ │ +| if (!m_nodes.empty()) | │ │ │ │ │ | { | │ │ │ │ │ -| t->peer_is_interesting(*this); | │ │ │ │ │ -| } | │ │ │ │ │ +| entry& nodes = dict["nodes"]; | │ │ │ │ │ +| entry::list_type& nodes_list = nodes.list(); | │ │ │ │ │ +| for (auto const& n : m_nodes) | │ │ │ │ │ +|_ _ _ _{_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_f_i_l_e___s_t_o_r_a_g_e_._c_p_p_:_4_5_7_ _ _ _|_m_a_y_b_e_ _i_t_ _w_o_u_l_d_ _b_e_ _n_i_c_e_ _t_o_ _h_a_v_e_ _a_ _b_e_t_t_e_r_ _i_n_d_e_x_ _h_e_r_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** mmaayybbee iitt wwoouulldd bbee nniiccee ttoo hhaavvee aa bbeetttteerr iinnddeexx hheerree ********** | │ │ │ │ │ +|****** ....//ssrrcc//ffiillee__ssttoorraaggee..ccpppp::445577 ****** | │ │ │ │ │ +|// find the file iterator and file offset | │ │ │ │ │ +| aux::file_entry target; | │ │ │ │ │ +| target.offset = aux::numeric_cast(offset); | │ │ │ │ │ +| TORRENT_ASSERT(!compare_file_offset(target, m_files.front())); | │ │ │ │ │ +| | │ │ │ │ │ +| auto file_iter = std::upper_bound( | │ │ │ │ │ +| m_files.begin(), m_files.end(), target, compare_file_offset); | │ │ │ │ │ +| | │ │ │ │ │ +| TORRENT_ASSERT(file_iter != m_files.begin()); | │ │ │ │ │ +| --file_iter; | │ │ │ │ │ +| return file_index_t{int(file_iter - m_files.begin())}; | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -| std::vector const& peer_connection::allowed_fast() | │ │ │ │ │ +| file_index_t file_storage::file_index_at_piece(piece_index_t const piece) const | │ │ │ │ │ | { | │ │ │ │ │ -| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ -| std::shared_ptr t = m_torrent.lock(); | │ │ │ │ │ -| TORRENT_ASSERT(t); | │ │ │ │ │ +| return file_index_at_offset(static_cast(piece) * std::int64_t(piece_length())); | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -|return m_allowed_fast; | │ │ │ │ │ -|} | │ │ │ │ │ +| file_index_t file_storage::file_index_for_root(sha256_hash const& root_hash) const | │ │ │ │ │ +| { | │ │ │ │ │ +|for (file_index_t const i : file_range()) | │ │ │ │ │ +|{ | │ │ │ │ │ +| if (root(i) == root_hash) return i; | │ │ │ │ │ +| } | │ │ │ │ │ +| return file_index_t{-1}; | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -| bool peer_connection::can_request_time_critical() const | │ │ │ │ │ +| piece_index_t file_storage::piece_index_at_file(file_index_t f) const | │ │ │ │ │ | { | │ │ │ │ │ -| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ -| if (has_peer_choked() || !is_interesting()) return false; | │ │ │ │ │ -| if (int(m_download_queue.size()) + int(m_request_queue.size()) | │ │ │ │ │ -| > m_desired_queue_size * 2) return false; | │ │ │ │ │ -| if (on_parole()) return false; | │ │ │ │ │ -| if (m_disconnecting) return false; | │ │ │ │ │ -| std::shared_ptr t = m_torrent.lock(); | │ │ │ │ │ -| TORRENT_ASSERT(t); | │ │ │ │ │ -| if (t->upload_mode()) return false; | │ │ │ │ │ +| return piece_index_t{aux::numeric_cast(file_offset(f) / piece_length())}; | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -| // ignore snubbed peers, since they're not likely to return pieces in a | │ │ │ │ │ -| // timely manner anyway | │ │ │ │ │ -| if (m_snubbed) return false; | │ │ │ │ │ -| return true; | │ │ │ │ │ +|#if TORRENT_ABI_VERSION <= 2 | │ │ │ │ │ +| char const* file_storage::file_name_ptr(file_index_t const index) const | │ │ │ │ │ +| { | │ │ │ │ │ +| return m_files[index].name; | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -| bool peer_connection::make_time_critical(piece_block const& block) | │ │ │ │ │ +| int file_storage::file_name_len(file_index_t const index) const | │ │ │ │ │ | { | │ │ │ │ │ -| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ -| auto const rit = std::find_if(m_request_queue.begin() | │ │ │ │ │ -| , m_request_queue.end(), aux::has_block(block)); | │ │ │ │ │ -| if (rit == m_request_queue.end()) return false; | │ │ │ │ │ -|#if TORRENT_USE_ASSERTS | │ │ │ │ │ -| std::shared_ptr t = m_torrent.lock(); | │ │ │ │ │ -| TORRENT_ASSERT(t); | │ │ │ │ │ -|_ _ _T_O_R_R_E_N_T___A_S_S_E_R_T_(_t_-_>_h_a_s___p_i_c_k_e_r_(_)_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_c_h_o_k_e_r_._c_p_p_:_2_5_5_ _ _ _ _ _ _ _ _ _|_m_a_k_e_ _c_o_n_f_i_g_u_r_a_b_l_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** mmaakkee ccoonnffiigguurraabbllee ********** | │ │ │ │ │ -|****** ....//ssrrcc//cchhookkeerr..ccpppp::225555 ****** | │ │ │ │ │ -|// first reset the number of unchoke slots, because we'll calculate | │ │ │ │ │ -| // it purely based on the current state of our peers. | │ │ │ │ │ -| upload_slots = 0; | │ │ │ │ │ +| if (m_files[index].name_len == aux::file_entry::name_is_owned) | │ │ │ │ │ +| return -1; | │ │ │ │ │ +| return m_files[index].name_len; | │ │ │ │ │ +| } | │ │ │ │ │ +|#endif | │ │ │ │ │ | | │ │ │ │ │ -| int rate_threshold = sett.get_int(settings_pack::rate_choker_initial_threshold); | │ │ │ │ │ +| std::vector file_storage::map_block(piece_index_t const piece | │ │ │ │ │ +| , std::int64_t const offset, std::int64_t size) const | │ │ │ │ │ +| { | │ │ │ │ │ +| TORRENT_ASSERT_PRECOND(piece >= piece_index_t{0}); | │ │ │ │ │ +|_ _ _T_O_R_R_E_N_T___A_S_S_E_R_T___P_R_E_C_O_N_D_(_p_i_e_c_e_ _<_ _e_n_d___p_i_e_c_e_(_)_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_f_i_l_e___s_t_o_r_a_g_e_._c_p_p_:_1_2_4_2_ _ _|_t_h_i_s_ _w_o_u_l_d_ _b_e_ _m_o_r_e_ _e_f_f_i_c_i_e_n_t_ _i_f_ _m___p_a_t_h_s_ _w_a_s_ _s_o_r_t_e_d_ _f_i_r_s_t_,_ _s_u_c_h_ _t_h_a_t_ _a_ _l_o_w_e_r_ _p_a_t_h_ _i_n_d_e_x_ _a_l_w_a_y_s_ _m_e_a_n_t_ _s_o_r_t_e_d_-_b_e_f_o_r_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tthhiiss wwoouulldd bbee mmoorree eeffffiicciieenntt iiff mm__ppaatthhss wwaass ssoorrtteedd ffiirrsstt,, ssuucchh tthhaatt aa lloowweerr ppaatthh iinnddeexx aallwwaayyss mmeeaanntt ssoorrtteedd--bbeeffoorree ********** | │ │ │ │ │ +|****** ....//ssrrcc//ffiillee__ssttoorraaggee..ccpppp::11224422 ****** | │ │ │ │ │ +|} | │ │ │ │ │ | | │ │ │ │ │ -| std::sort(peers.begin(), peers.end() | │ │ │ │ │ -| , [](peer_connection const* lhs, peer_connection const* rhs) | │ │ │ │ │ -| { return upload_rate_compare(lhs, rhs); }); | │ │ │ │ │ +| void file_storage::canonicalize_impl(bool const backwards_compatible) | │ │ │ │ │ +| { | │ │ │ │ │ +| TORRENT_ASSERT(piece_length() >= 16 * 1024); | │ │ │ │ │ | | │ │ │ │ │ -| for (auto const* p : peers) | │ │ │ │ │ +| // use this vector to track the new ordering of files | │ │ │ │ │ +| // this allows the use of STL algorithms despite them | │ │ │ │ │ +| // not supporting a custom swap functor | │ │ │ │ │ +| aux::vector new_order(end_file()); | │ │ │ │ │ +| for (auto i : file_range()) | │ │ │ │ │ +| new_order[i] = i; | │ │ │ │ │ +| | │ │ │ │ │ +| // remove any existing pad files | │ │ │ │ │ +| { | │ │ │ │ │ +| auto pad_begin = std::partition(new_order.begin(), new_order.end() | │ │ │ │ │ +| , [this](file_index_t i) { return !m_files[i].pad_file; }); | │ │ │ │ │ +| new_order.erase(pad_begin, new_order.end()); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| | │ │ │ │ │ +|// sort files by path/name | │ │ │ │ │ +| std::sort(new_order.begin(), new_order.end() | │ │ │ │ │ +| , [this](file_index_t l, file_index_t r) | │ │ │ │ │ +| { | │ │ │ │ │ +| // assuming m_paths are unique! | │ │ │ │ │ +| auto const& lf = m_files[l]; | │ │ │ │ │ +| auto const& rf = m_files[r]; | │ │ │ │ │ +| if (lf.path_index != rf.path_index) | │ │ │ │ │ | { | │ │ │ │ │ -| int const rate = int(p->uploaded_in_last_round() | │ │ │ │ │ -| * 1000 / total_milliseconds(unchoke_interval)); | │ │ │ │ │ +| int const ret = path_compare(m_paths[lf.path_index], lf.filename() | │ │ │ │ │ +| , m_paths[rf.path_index], rf.filename()); | │ │ │ │ │ +| if (ret != 0) return ret < 0; | │ │ │ │ │ +| } | │ │ │ │ │ +| return lf.filename() < rf.filename(); | │ │ │ │ │ +| }); | │ │ │ │ │ | | │ │ │ │ │ -| // always have at least 1 unchoke slot | │ │ │ │ │ -| if (rate < rate_threshold) break; | │ │ │ │ │ +| aux::vector new_files; | │ │ │ │ │ +| aux::vector new_file_hashes; | │ │ │ │ │ +| aux::vector new_mtime; | │ │ │ │ │ | | │ │ │ │ │ -| ++upload_slots; | │ │ │ │ │ +| // reserve enough space for the worst case after padding | │ │ │ │ │ +| new_files.reserve(new_order.size() * 2 - 1); | │ │ │ │ │ +| if (!m_file_hashes.empty()) | │ │ │ │ │ +| new_file_hashes.reserve(new_order.size() * 2 - 1); | │ │ │ │ │ +| if (!m_mtime.empty()) | │ │ │ │ │ +| new_mtime.reserve(new_order.size() * 2 - 1); | │ │ │ │ │ | | │ │ │ │ │ -|rate_threshold += 2048; | │ │ │ │ │ -|} | │ │ │ │ │ -| ++upload_slots; | │ │ │ │ │ +| // re-compute offsets and insert pad files as necessary | │ │ │ │ │ +|_ _ _s_t_d_:_:_i_n_t_6_4___t_ _o_f_f_ _=_ _0_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_f_i_l_e___s_t_o_r_a_g_e_._c_p_p_:_1_3_4_5_ _ _|_i_n_ _C_+_+_1_7_ _t_h_i_s_ _c_o_u_l_d_ _b_e_ _s_t_r_i_n_g___v_i_e_w_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** iinn CC++++1177 tthhiiss ccoouulldd bbee ssttrriinngg__vviieeww ********** | │ │ │ │ │ +|****** ....//ssrrcc//ffiillee__ssttoorraaggee..ccpppp::11334455 ****** | │ │ │ │ │ +|add_pad_file(i); | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -| // sorts the peers that are eligible for unchoke by download rate and | │ │ │ │ │ -| // secondary by total upload. The reason for this is, if all torrents are | │ │ │ │ │ -| // being seeded, the download rate will be 0, and the peers we have sent | │ │ │ │ │ -| // the least to should be unchoked | │ │ │ │ │ +| m_files = std::move(new_files); | │ │ │ │ │ +| m_file_hashes = std::move(new_file_hashes); | │ │ │ │ │ +| m_mtime = std::move(new_mtime); | │ │ │ │ │ | | │ │ │ │ │ -| // we use partial sort here, because we only care about the top | │ │ │ │ │ -| // upload_slots peers. | │ │ │ │ │ +| m_total_size = off; | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -| int const slots = std::min(upload_slots, int(peers.size())); | │ │ │ │ │ +| void file_storage::sanitize_symlinks() | │ │ │ │ │ +| { | │ │ │ │ │ +| // symlinks are unusual, this function is optimized assuming there are no | │ │ │ │ │ +| // symbolic links in the torrent. If we find one symbolic link, we'll | │ │ │ │ │ +| // build the hash table of files it's allowed to refer to, but don't pay | │ │ │ │ │ +| // that price up-front. | │ │ │ │ │ +| std::unordered_map file_map; | │ │ │ │ │ +| bool file_map_initialized = false; | │ │ │ │ │ | | │ │ │ │ │ -| if (sett.get_int(settings_pack::seed_choking_algorithm) | │ │ │ │ │ -| == settings_pack::round_robin) | │ │ │ │ │ -| { | │ │ │ │ │ -| int const pieces = sett.get_int(settings_pack::seeding_piece_quota); | │ │ │ │ │ +| // lazily instantiated set of all valid directories a symlink may point to | │ │ │ │ │ +|std::unordered_set dir_map; | │ │ │ │ │ +|bool dir_map_initialized = false; | │ │ │ │ │ | | │ │ │ │ │ -| std::nth_element(peers.begin(), peers.begin() | │ │ │ │ │ -| + slots, peers.end() | │ │ │ │ │ -| , [pieces](peer_connection const* lhs, peer_connection const* rhs) | │ │ │ │ │ -| { return unchoke_compare_rr(lhs, rhs, pieces); }); | │ │ │ │ │ -| } | │ │ │ │ │ -| else if (sett.get_int(settings_pack::seed_choking_algorithm) | │ │ │ │ │ -| == settings_pack::fastest_upload) | │ │ │ │ │ +| // symbolic links that points to directories | │ │ │ │ │ +| std::unordered_map dir_links; | │ │ │ │ │ +| | │ │ │ │ │ +| // we validate symlinks in (potentially) 2 passes over the files. | │ │ │ │ │ +| // remaining symlinks to validate after the first pass | │ │ │ │ │ +| std::vector symlinks_to_validate; | │ │ │ │ │ +| | │ │ │ │ │ +| for (auto const i : file_range()) | │ │ │ │ │ | { | │ │ │ │ │ -| std::nth_element(peers.begin(), peers.begin() | │ │ │ │ │ -| + slots, peers.end() | │ │ │ │ │ -|_ _ _ _ _,_ _[_]_(_p_e_e_r___c_o_n_n_e_c_t_i_o_n_ _c_o_n_s_t_*_ _l_h_s_,_ _p_e_e_r___c_o_n_n_e_c_t_i_o_n_ _c_o_n_s_t_*_ _r_h_s_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +| if (!(file_flags(i) & file_storage::flag_symlink)) continue; | │ │ │ │ │ +| | │ │ │ │ │ +| if (!file_map_initialized) | │ │ │ │ │ +| { | │ │ │ │ │ +| for (auto const j : file_range()) | │ │ │ │ │ +| file_map.insert({internal_file_path(j), j}); | │ │ │ │ │ +| file_map_initialized = true; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| aux::file_entry const& fe = m_files[i]; | │ │ │ │ │ +| TORRENT_ASSERT(fe.symlink_index < int(m_symlinks.size())); | │ │ │ │ │ +| | │ │ │ │ │ +| // symlink targets are only allowed to point to files or directories in | │ │ │ │ │ +| // this torrent. | │ │ │ │ │ +| { | │ │ │ │ │ +| std::string target = m_symlinks[fe.symlink_index]; | │ │ │ │ │ +| | │ │ │ │ │ +| if (is_complete(target)) | │ │ │ │ │ +|_ _ _ _ _{_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_m_e_r_k_l_e___t_r_e_e_._c_p_p_:_1_1_0_ _ _ _ _|_i_n_ _C_+_+_2_0_,_ _u_s_e_ _s_t_d_:_:_i_d_e_n_t_i_t_y_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** iinn CC++++2200,, uussee ssttdd::::iiddeennttiittyy ********** | │ │ │ │ │ |****** ....//ssrrcc//mmeerrkkllee__ttrreeee..ccpppp::111100 ****** | │ │ │ │ │ |allocate_full(); | │ │ │ │ │ | | │ │ │ │ │ | merkle_validate_copy(t, m_tree, root(), m_block_verified); | │ │ │ │ │ | | │ │ │ │ │ @@ -6534,317 +6955,101 @@ │ │ │ │ │ | | │ │ │ │ │ | int merkle_tree::block_layer_start() const | │ │ │ │ │ | { | │ │ │ │ │ | int const num_leafs = merkle_num_leafs(m_num_blocks); | │ │ │ │ │ | TORRENT_ASSERT(num_leafs > 0); | │ │ │ │ │ | return merkle_first_leaf(num_leafs); | │ │ │ │ │ |_ _}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_f_i_l_e___s_t_o_r_a_g_e_._c_p_p_:_4_5_7_ _ _ _|_m_a_y_b_e_ _i_t_ _w_o_u_l_d_ _b_e_ _n_i_c_e_ _t_o_ _h_a_v_e_ _a_ _b_e_t_t_e_r_ _i_n_d_e_x_ _h_e_r_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** mmaayybbee iitt wwoouulldd bbee nniiccee ttoo hhaavvee aa bbeetttteerr iinnddeexx hheerree ********** | │ │ │ │ │ -|****** ....//ssrrcc//ffiillee__ssttoorraaggee..ccpppp::445577 ****** | │ │ │ │ │ -|// find the file iterator and file offset | │ │ │ │ │ -| aux::file_entry target; | │ │ │ │ │ -| target.offset = aux::numeric_cast(offset); | │ │ │ │ │ -| TORRENT_ASSERT(!compare_file_offset(target, m_files.front())); | │ │ │ │ │ -| | │ │ │ │ │ -| auto file_iter = std::upper_bound( | │ │ │ │ │ -| m_files.begin(), m_files.end(), target, compare_file_offset); | │ │ │ │ │ -| | │ │ │ │ │ -| TORRENT_ASSERT(file_iter != m_files.begin()); | │ │ │ │ │ -| --file_iter; | │ │ │ │ │ -| return file_index_t{int(file_iter - m_files.begin())}; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| file_index_t file_storage::file_index_at_piece(piece_index_t const piece) const | │ │ │ │ │ -| { | │ │ │ │ │ -| return file_index_at_offset(static_cast(piece) * std::int64_t(piece_length())); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| file_index_t file_storage::file_index_for_root(sha256_hash const& root_hash) const | │ │ │ │ │ -| { | │ │ │ │ │ -|for (file_index_t const i : file_range()) | │ │ │ │ │ -|{ | │ │ │ │ │ -| if (root(i) == root_hash) return i; | │ │ │ │ │ -| } | │ │ │ │ │ -| return file_index_t{-1}; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| piece_index_t file_storage::piece_index_at_file(file_index_t f) const | │ │ │ │ │ -| { | │ │ │ │ │ -| return piece_index_t{aux::numeric_cast(file_offset(f) / piece_length())}; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -|#if TORRENT_ABI_VERSION <= 2 | │ │ │ │ │ -| char const* file_storage::file_name_ptr(file_index_t const index) const | │ │ │ │ │ -| { | │ │ │ │ │ -| return m_files[index].name; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| int file_storage::file_name_len(file_index_t const index) const | │ │ │ │ │ -| { | │ │ │ │ │ -| if (m_files[index].name_len == aux::file_entry::name_is_owned) | │ │ │ │ │ -| return -1; | │ │ │ │ │ -| return m_files[index].name_len; | │ │ │ │ │ -| } | │ │ │ │ │ -|#endif | │ │ │ │ │ -| | │ │ │ │ │ -| std::vector file_storage::map_block(piece_index_t const piece | │ │ │ │ │ -| , std::int64_t const offset, std::int64_t size) const | │ │ │ │ │ -| { | │ │ │ │ │ -| TORRENT_ASSERT_PRECOND(piece >= piece_index_t{0}); | │ │ │ │ │ -|_ _ _T_O_R_R_E_N_T___A_S_S_E_R_T___P_R_E_C_O_N_D_(_p_i_e_c_e_ _<_ _e_n_d___p_i_e_c_e_(_)_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_f_i_l_e___s_t_o_r_a_g_e_._c_p_p_:_1_2_4_2_ _ _|_t_h_i_s_ _w_o_u_l_d_ _b_e_ _m_o_r_e_ _e_f_f_i_c_i_e_n_t_ _i_f_ _m___p_a_t_h_s_ _w_a_s_ _s_o_r_t_e_d_ _f_i_r_s_t_,_ _s_u_c_h_ _t_h_a_t_ _a_ _l_o_w_e_r_ _p_a_t_h_ _i_n_d_e_x_ _a_l_w_a_y_s_ _m_e_a_n_t_ _s_o_r_t_e_d_-_b_e_f_o_r_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tthhiiss wwoouulldd bbee mmoorree eeffffiicciieenntt iiff mm__ppaatthhss wwaass ssoorrtteedd ffiirrsstt,, ssuucchh tthhaatt aa lloowweerr ppaatthh iinnddeexx aallwwaayyss mmeeaanntt ssoorrtteedd--bbeeffoorree ********** | │ │ │ │ │ -|****** ....//ssrrcc//ffiillee__ssttoorraaggee..ccpppp::11224422 ****** | │ │ │ │ │ -|} | │ │ │ │ │ -| | │ │ │ │ │ -| void file_storage::canonicalize_impl(bool const backwards_compatible) | │ │ │ │ │ -| { | │ │ │ │ │ -| TORRENT_ASSERT(piece_length() >= 16 * 1024); | │ │ │ │ │ -| | │ │ │ │ │ -| // use this vector to track the new ordering of files | │ │ │ │ │ -| // this allows the use of STL algorithms despite them | │ │ │ │ │ -| // not supporting a custom swap functor | │ │ │ │ │ -| aux::vector new_order(end_file()); | │ │ │ │ │ -| for (auto i : file_range()) | │ │ │ │ │ -| new_order[i] = i; | │ │ │ │ │ -| | │ │ │ │ │ -| // remove any existing pad files | │ │ │ │ │ -| { | │ │ │ │ │ -| auto pad_begin = std::partition(new_order.begin(), new_order.end() | │ │ │ │ │ -| , [this](file_index_t i) { return !m_files[i].pad_file; }); | │ │ │ │ │ -| new_order.erase(pad_begin, new_order.end()); | │ │ │ │ │ -| } | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_p_e___c_r_y_p_t_o_._c_p_p_:_6_0_ _ _ _ _ _ _ _|_i_t_ _w_o_u_l_d_ _b_e_ _n_i_c_e_ _t_o_ _g_e_t_ _t_h_e_ _l_i_t_e_r_a_l_ _w_o_r_k_i_n_g_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** iitt wwoouulldd bbee nniiccee ttoo ggeett tthhee lliitteerraall wwoorrkkiinngg ********** | │ │ │ │ │ +|****** ....//ssrrcc//ppee__ccrryyppttoo..ccpppp::6600 ****** | │ │ │ │ │ +|#include | │ │ │ │ │ +|#include | │ │ │ │ │ | | │ │ │ │ │ +|#include "libtorrent/aux_/disable_warnings_push.hpp" | │ │ │ │ │ | | │ │ │ │ │ -|// sort files by path/name | │ │ │ │ │ -| std::sort(new_order.begin(), new_order.end() | │ │ │ │ │ -| , [this](file_index_t l, file_index_t r) | │ │ │ │ │ -| { | │ │ │ │ │ -| // assuming m_paths are unique! | │ │ │ │ │ -| auto const& lf = m_files[l]; | │ │ │ │ │ -| auto const& rf = m_files[r]; | │ │ │ │ │ -| if (lf.path_index != rf.path_index) | │ │ │ │ │ -| { | │ │ │ │ │ -| int const ret = path_compare(m_paths[lf.path_index], lf.filename() | │ │ │ │ │ -| , m_paths[rf.path_index], rf.filename()); | │ │ │ │ │ -| if (ret != 0) return ret < 0; | │ │ │ │ │ -| } | │ │ │ │ │ -| return lf.filename() < rf.filename(); | │ │ │ │ │ -| }); | │ │ │ │ │ +|#include | │ │ │ │ │ +|#include | │ │ │ │ │ | | │ │ │ │ │ -| aux::vector new_files; | │ │ │ │ │ -| aux::vector new_file_hashes; | │ │ │ │ │ -| aux::vector new_mtime; | │ │ │ │ │ +|#include "libtorrent/aux_/disable_warnings_pop.hpp" | │ │ │ │ │ | | │ │ │ │ │ -| // reserve enough space for the worst case after padding | │ │ │ │ │ -| new_files.reserve(new_order.size() * 2 - 1); | │ │ │ │ │ -| if (!m_file_hashes.empty()) | │ │ │ │ │ -| new_file_hashes.reserve(new_order.size() * 2 - 1); | │ │ │ │ │ -| if (!m_mtime.empty()) | │ │ │ │ │ -| new_mtime.reserve(new_order.size() * 2 - 1); | │ │ │ │ │ +|#include "libtorrent/random.hpp" | │ │ │ │ │ +|#include "libtorrent/aux_/alloca.hpp" | │ │ │ │ │ +|#include "libtorrent/pe_crypto.hpp" | │ │ │ │ │ +|#include "libtorrent/hasher.hpp" | │ │ │ │ │ | | │ │ │ │ │ -| // re-compute offsets and insert pad files as necessary | │ │ │ │ │ -|_ _ _s_t_d_:_:_i_n_t_6_4___t_ _o_f_f_ _=_ _0_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_f_i_l_e___s_t_o_r_a_g_e_._c_p_p_:_1_3_4_5_ _ _|_i_n_ _C_+_+_1_7_ _t_h_i_s_ _c_o_u_l_d_ _b_e_ _s_t_r_i_n_g___v_i_e_w_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** iinn CC++++1177 tthhiiss ccoouulldd bbee ssttrriinngg__vviieeww ********** | │ │ │ │ │ -|****** ....//ssrrcc//ffiillee__ssttoorraaggee..ccpppp::11334455 ****** | │ │ │ │ │ -|add_pad_file(i); | │ │ │ │ │ -| } | │ │ │ │ │ +|namespace libtorrent { | │ │ │ │ │ | | │ │ │ │ │ -| m_files = std::move(new_files); | │ │ │ │ │ -| m_file_hashes = std::move(new_file_hashes); | │ │ │ │ │ -| m_mtime = std::move(new_mtime); | │ │ │ │ │ +| namespace mp = boost::multiprecision; | │ │ │ │ │ | | │ │ │ │ │ -| m_total_size = off; | │ │ │ │ │ +| namespace { | │ │ │ │ │ +|key_t const dh_prime | │ │ │ │ │ +|("0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63|36210000000000090563"); │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -| void file_storage::sanitize_symlinks() | │ │ │ │ │ -| { | │ │ │ │ │ -| // symlinks are unusual, this function is optimized assuming there are no | │ │ │ │ │ -| // symbolic links in the torrent. If we find one symbolic link, we'll | │ │ │ │ │ -| // build the hash table of files it's allowed to refer to, but don't pay | │ │ │ │ │ -| // that price up-front. | │ │ │ │ │ -| std::unordered_map file_map; | │ │ │ │ │ -| bool file_map_initialized = false; | │ │ │ │ │ -| | │ │ │ │ │ -| // lazily instantiated set of all valid directories a symlink may point to | │ │ │ │ │ -|std::unordered_set dir_map; | │ │ │ │ │ -|bool dir_map_initialized = false; | │ │ │ │ │ -| | │ │ │ │ │ -| // symbolic links that points to directories | │ │ │ │ │ -| std::unordered_map dir_links; | │ │ │ │ │ -| | │ │ │ │ │ -| // we validate symlinks in (potentially) 2 passes over the files. | │ │ │ │ │ -| // remaining symlinks to validate after the first pass | │ │ │ │ │ -| std::vector symlinks_to_validate; | │ │ │ │ │ -| | │ │ │ │ │ -| for (auto const i : file_range()) | │ │ │ │ │ -| { | │ │ │ │ │ -| if (!(file_flags(i) & file_storage::flag_symlink)) continue; | │ │ │ │ │ -| | │ │ │ │ │ -| if (!file_map_initialized) | │ │ │ │ │ -| { | │ │ │ │ │ -| for (auto const j : file_range()) | │ │ │ │ │ -| file_map.insert({internal_file_path(j), j}); | │ │ │ │ │ -| file_map_initialized = true; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| aux::file_entry const& fe = m_files[i]; | │ │ │ │ │ -| TORRENT_ASSERT(fe.symlink_index < int(m_symlinks.size())); | │ │ │ │ │ -| | │ │ │ │ │ -| // symlink targets are only allowed to point to files or directories in | │ │ │ │ │ -| // this torrent. | │ │ │ │ │ -| { | │ │ │ │ │ -| std::string target = m_symlinks[fe.symlink_index]; | │ │ │ │ │ -| | │ │ │ │ │ -| if (is_complete(target)) | │ │ │ │ │ -|_ _ _ _ _{_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_h_a_s_h___p_i_c_k_e_r_._c_p_p_:_3_0_9_ _ _ _ _|_u_s_e_ _s_t_r_u_c_t_u_r_e_d_ _b_i_n_d_i_n_g_s_ _i_n_ _C_+_+_1_7_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** uussee ssttrruuccttuurreedd bbiinnddiinnggss iinn CC++++1177 ********** | │ │ │ │ │ -|****** ....//ssrrcc//hhaasshh__ppiicckkeerr..ccpppp::330099 ****** | │ │ │ │ │ -|, int const offset, sha256_hash const& h) | │ │ │ │ │ +| std::array export_key(key_t const& k) | │ │ │ │ │ | { | │ │ │ │ │ -| TORRENT_ASSERT(offset >= 0); | │ │ │ │ │ -| auto const f = m_files.file_index_at_piece(piece); | │ │ │ │ │ -| | │ │ │ │ │ -| if (m_files.pad_file_at(f)) | │ │ │ │ │ -| return { set_block_hash_result::result::success, 0, 0 }; | │ │ │ │ │ -| | │ │ │ │ │ -| auto& merkle_tree = m_merkle_trees[f]; | │ │ │ │ │ -| piece_index_t const file_first_piece = m_files.piece_index_at_file(f); | │ │ │ │ │ -| std::int64_t const block_offset = static_cast(piece) * std::int64_t(m_files.piece_length()) | │ │ │ │ │ -| + offset - m_files.file_offset(f); | │ │ │ │ │ -| int const block_index = aux::numeric_cast(block_offset / default_block_size); | │ │ │ │ │ -| | │ │ │ │ │ -| if (h.is_all_zeros()) | │ │ │ │ │ -| { | │ │ │ │ │ -| TORRENT_ASSERT_FAIL(); | │ │ │ │ │ -| return set_block_hash_result::block_hash_failed(); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -|aux::merkle_tree::set_block_result result; | │ │ │ │ │ -|int leafs_index; | │ │ │ │ │ -| int leafs_size; | │ │ │ │ │ -| std::tie(result, leafs_index, leafs_size) = merkle_tree.set_block(block_index, h); | │ │ │ │ │ -| | │ │ │ │ │ -| if (result == aux::merkle_tree::set_block_result::unknown) | │ │ │ │ │ -| return set_block_hash_result::unknown(); | │ │ │ │ │ -| if (result == aux::merkle_tree::set_block_result::block_hash_failed) | │ │ │ │ │ -| return set_block_hash_result::block_hash_failed(); | │ │ │ │ │ +| std::array ret; | │ │ │ │ │ +| auto* begin = reinterpret_cast(ret.data()); | │ │ │ │ │ +|_ _ _s_t_d_:_:_u_i_n_t_8___t_*_ _e_n_d_ _=_ _m_p_:_:_e_x_p_o_r_t___b_i_t_s_(_k_,_ _b_e_g_i_n_,_ _8_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_p_e___c_r_y_p_t_o_._c_p_p_:_7_1_ _ _ _ _ _ _ _|_i_t_ _w_o_u_l_d_ _b_e_ _n_i_c_e_ _t_o_ _b_e_ _a_b_l_e_ _t_o_ _e_x_p_o_r_t_ _t_o_ _a_ _f_i_x_e_d_ _w_i_d_t_h_ _f_i_e_l_d_,_ _s_o_ _w_e_ _w_o_u_l_d_n_'_t_ _h_a_v_e_ _t_o_ _s_h_i_f_t_ _i_t_ _l_a_t_e_r_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** iitt wwoouulldd bbee nniiccee ttoo bbee aabbllee ttoo eexxppoorrtt ttoo aa ffiixxeedd wwiiddtthh ffiieelldd,, ssoo wwee wwoouullddnn''tt hhaavvee ttoo sshhiifftt iitt llaatteerr ********** | │ │ │ │ │ +|****** ....//ssrrcc//ppee__ccrryyppttoo..ccpppp::7711 ****** | │ │ │ │ │ +|#include "libtorrent/random.hpp" | │ │ │ │ │ +|#include "libtorrent/aux_/alloca.hpp" | │ │ │ │ │ +|#include "libtorrent/pe_crypto.hpp" | │ │ │ │ │ +|#include "libtorrent/hasher.hpp" | │ │ │ │ │ | | │ │ │ │ │ -| auto const status = (result == aux::merkle_tree::set_block_result::hash_failed) | │ │ │ │ │ -| ? set_block_hash_result::result::piece_hash_failed | │ │ │ │ │ -| : set_block_hash_result::result::success; | │ │ │ │ │ +|namespace libtorrent { | │ │ │ │ │ | | │ │ │ │ │ -| int const blocks_per_piece = m_files.piece_length() / default_block_size; | │ │ │ │ │ +| namespace mp = boost::multiprecision; | │ │ │ │ │ | | │ │ │ │ │ -| return { status | │ │ │ │ │ -| , int(leafs_index - static_cast(piece - file_first_piece) * blocks_per_piece) | │ │ │ │ │ -| , std::min(leafs_size, m_files.file_num_pieces(f) * blocks_per_piece - leafs_index) }; | │ │ │ │ │ +| namespace { | │ │ │ │ │ +| key_t const dh_prime | │ │ │ │ │ +| | │ │ │ │ │ +|("0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63|36210000000000090563"); │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -| void hash_picker::hashes_rejected(hash_request const& req) | │ │ │ │ │ +| std::array export_key(key_t const& k) | │ │ │ │ │ | { | │ │ │ │ │ -| TORRENT_ASSERT(req.base == m_piece_layer && req.index % 512 == 0); | │ │ │ │ │ -| | │ │ │ │ │ -| for (int i = req.index; i < req.index + req.count; i += 512) | │ │ │ │ │ -| { | │ │ │ │ │ -| m_piece_hash_requested[req.file][i / 512].last_request = min_time(); | │ │ │ │ │ -| --m_piece_hash_requested[req.file][i / 512].num_requests; | │ │ │ │ │ -|_ _ _}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_t_o_r_r_e_n_t___i_n_f_o_._c_p_p_:_8_7_5_ _ _ _|_t_h_i_s_ _s_h_o_u_l_d_ _b_e_ _c_o_n_s_i_d_e_r_e_d_ _a_ _f_a_i_l_u_r_e_,_ _a_n_d_ _t_h_e_ _._t_o_r_r_e_n_t_ _f_i_l_e_ _r_e_j_e_c_t_e_d_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tthhiiss sshhoouulldd bbee ccoonnssiiddeerreedd aa ffaaiilluurree,, aanndd tthhee ..ttoorrrreenntt ffiillee rreejjeecctteedd ********** | │ │ │ │ │ -|****** ....//ssrrcc//ttoorrrreenntt__iinnffoo..ccpppp::887755 ****** | │ │ │ │ │ -|std::string ext = extension(filename); | │ │ │ │ │ -| int cnt = 0; | │ │ │ │ │ -| for (;;) | │ │ │ │ │ -| { | │ │ │ │ │ -| ++cnt; | │ │ │ │ │ -| char new_ext[50]; | │ │ │ │ │ -| std::snprintf(new_ext, sizeof(new_ext), ".%d%s", cnt, ext.c_str()); | │ │ │ │ │ -| filename = base + new_ext; | │ │ │ │ │ -| | │ │ │ │ │ -| boost::crc_optimal<32, 0x1EDC6F41, 0xFFFFFFFF, 0xFFFFFFFF, true, true> crc; | │ │ │ │ │ -| process_string_lowercase(crc, filename); | │ │ │ │ │ -| std::uint32_t const new_hash = crc.checksum(); | │ │ │ │ │ -| if (files.find(new_hash) == files.end()) | │ │ │ │ │ -| { | │ │ │ │ │ -| files.insert({new_hash, {i, 0}}); | │ │ │ │ │ -| break; | │ │ │ │ │ -| } | │ │ │ │ │ -| ++num_collisions; | │ │ │ │ │ -| if (num_collisions > 100) | │ │ │ │ │ -| { | │ │ │ │ │ -|} | │ │ │ │ │ -|} | │ │ │ │ │ +| std::array ret; | │ │ │ │ │ +| auto* begin = reinterpret_cast(ret.data()); | │ │ │ │ │ +| std::uint8_t* end = mp::export_bits(k, begin, 8); | │ │ │ │ │ | | │ │ │ │ │ -| copy_on_write(); | │ │ │ │ │ -| m_files.rename_file(i, filename); | │ │ │ │ │ +|if (end < begin + 96) | │ │ │ │ │ +|{ | │ │ │ │ │ +| int const len = int(end - begin); | │ │ │ │ │ +|#if defined __GNUC__ && __GNUC__ == 12 | │ │ │ │ │ +|#pragma GCC diagnostic push | │ │ │ │ │ +|#pragma GCC diagnostic ignored "-Wstringop-overflow" | │ │ │ │ │ +|#endif | │ │ │ │ │ +| std::memmove(begin + 96 - len, begin, aux::numeric_cast(len)); | │ │ │ │ │ +|#if defined __GNUC__ && __GNUC__ == 12 | │ │ │ │ │ +|#pragma GCC diagnostic pop | │ │ │ │ │ +|#endif | │ │ │ │ │ +| std::memset(begin, 0, aux::numeric_cast(96 - len)); | │ │ │ │ │ | } | │ │ │ │ │ +| return ret; | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -| void torrent_info::remap_files(file_storage const& f) | │ │ │ │ │ -| { | │ │ │ │ │ -| INVARIANT_CHECK; | │ │ │ │ │ -| | │ │ │ │ │ -| TORRENT_ASSERT(is_loaded()); | │ │ │ │ │ -| // the new specified file storage must have the exact | │ │ │ │ │ -| // same size as the current file storage | │ │ │ │ │ -| TORRENT_ASSERT(m_files.total_size() == f.total_size()); | │ │ │ │ │ -| | │ │ │ │ │ -| if (m_files.total_size() != f.total_size()) return; | │ │ │ │ │ -| copy_on_write(); | │ │ │ │ │ -| m_files = f; | │ │ │ │ │ -| m_files.set_num_pieces(m_orig_files->num_pieces()); | │ │ │ │ │ -| m_files.set_piece_length(m_orig_files->piece_length()); | │ │ │ │ │ -| } | │ │ │ │ │ +| void rc4_init(const unsigned char* in, std::size_t len, rc4 *state); | │ │ │ │ │ +| std::size_t rc4_encrypt(unsigned char *out, std::size_t outlen, rc4 *state); | │ │ │ │ │ | | │ │ │ │ │ -|#if TORRENT_ABI_VERSION == 1 | │ │ │ │ │ -| // standard constructor that parses a torrent file | │ │ │ │ │ -| torrent_info::torrent_info(entry const& torrent_file) | │ │ │ │ │ -| { | │ │ │ │ │ -| std::vector tmp; | │ │ │ │ │ -| std::back_insert_iterator> out(tmp); | │ │ │ │ │ -|_ _ _b_e_n_c_o_d_e_(_o_u_t_,_ _t_o_r_r_e_n_t___f_i_l_e_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_s_e_s_s_i_o_n_._c_p_p_:_5_4_0_ _ _ _ _ _ _ _ _|_I_n_ _C_+_+_1_7_._ _u_s_e_ _i_f_ _c_o_n_s_t_e_x_p_r_ _i_n_s_t_e_a_d_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** IInn CC++++1177.. uussee iiff ccoonnsstteexxpprr iinnsstteeaadd ********** | │ │ │ │ │ -|****** ....//ssrrcc//sseessssiioonn..ccpppp::554400 ****** | │ │ │ │ │ -|{} | │ │ │ │ │ -| session_proxy::session_proxy(session_proxy const&) = default; | │ │ │ │ │ -| session_proxy& session_proxy::operator=(session_proxy const&) & = default; | │ │ │ │ │ -| session_proxy::session_proxy(session_proxy&&) noexcept = default; | │ │ │ │ │ -| session_proxy& session_proxy::operator=(session_proxy&&) & noexcept = default; | │ │ │ │ │ -| session_proxy::~session_proxy() | │ │ │ │ │ +| // Set the prime P and the generator, generate local public key | │ │ │ │ │ +| dh_key_exchange::dh_key_exchange() | │ │ │ │ │ | { | │ │ │ │ │ -| if (m_thread && m_thread.use_count() == 1) | │ │ │ │ │ -| { | │ │ │ │ │ -|#if defined TORRENT_ASIO_DEBUGGING | │ │ │ │ │ -| wait_for_asio_handlers(); | │ │ │ │ │ -|#endif | │ │ │ │ │ -| m_thread->join(); | │ │ │ │ │ -| } | │ │ │ │ │ -| } | │ │ │ │ │ +| aux::array random_key; | │ │ │ │ │ +| aux::random_bytes({reinterpret_cast(random_key.data()) | │ │ │ │ │ +| , static_cast(random_key.size())}); | │ │ │ │ │ | | │ │ │ │ │ -| TORRENT_EXPORT std::unique_ptr default_disk_io_constructor( | │ │ │ │ │ -| io_context& ios, settings_interface const& sett, counters& cnt) | │ │ │ │ │ -| { | │ │ │ │ │ -|#if TORRENT_HAVE_MMAP || TORRENT_HAVE_MAP_VIEW_OF_FILE | │ │ │ │ │ -|#include "libtorrent/aux_/disable_deprecation_warnings_push.hpp" | │ │ │ │ │ -|if (sizeof(void*) == 8) | │ │ │ │ │ -| return mmap_disk_io_constructor(ios, sett, cnt); | │ │ │ │ │ -| else | │ │ │ │ │ -| return posix_disk_io_constructor(ios, sett, cnt); | │ │ │ │ │ -|#include "libtorrent/aux_/disable_warnings_pop.hpp" | │ │ │ │ │ -|#else | │ │ │ │ │ -| return posix_disk_io_constructor(ios, sett, cnt); | │ │ │ │ │ -|#endif | │ │ │ │ │ -| } | │ │ │ │ │ +| // create local key (random) | │ │ │ │ │ +| mp::import_bits(m_dh_local_secret, random_key.begin(), random_key.end()); | │ │ │ │ │ | | │ │ │ │ │ -|_}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +| // key = (2 ^ secret) % prime | │ │ │ │ │ +|_ _ _m___d_h___l_o_c_a_l___k_e_y_ _=_ _m_p_:_:_p_o_w_m_(_k_e_y___t_(_2_)_,_ _m___d_h___l_o_c_a_l___s_e_c_r_e_t_,_ _d_h___p_r_i_m_e_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_p_a_c_k_e_t___b_u_f_f_e_r_._c_p_p_:_1_5_7_ _ _|_u_s_e_ _c_o_m_p_a_r_e___l_e_s_s___w_r_a_p_ _f_o_r_ _t_h_i_s_ _c_o_m_p_a_r_i_s_o_n_ _a_s_ _w_e_l_l_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** uussee ccoommppaarree__lleessss__wwrraapp ffoorr tthhiiss ccoommppaarriissoonn aass wweellll ********** | │ │ │ │ │ |****** ....//ssrrcc//ppaacckkeett__bbuuffffeerr..ccpppp::115577 ****** | │ │ │ │ │ |{ | │ │ │ │ │ | INVARIANT_CHECK; | │ │ │ │ │ | TORRENT_ASSERT_VAL(size <= 0xffff, size); | │ │ │ │ │ | std::uint32_t new_size = m_capacity == 0 ? 16 : m_capacity; | │ │ │ │ │ @@ -6891,343 +7096,14 @@ │ │ │ │ │ | if (((idx + 1) & 0xffff) == m_last && m_size != 0) | │ │ │ │ │ | { | │ │ │ │ │ | --m_last; | │ │ │ │ │ | for (index_type i = 0; i < m_capacity; ++i, --m_last) | │ │ │ │ │ | if (m_storage[m_last & mask]) break; | │ │ │ │ │ | ++m_last; | │ │ │ │ │ |_ _ _ _m___l_a_s_t_ _&_=_ _0_x_f_f_f_f_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_s_r_c_/ |technically, this isn't supposed to happen, but it seems to sometimes. Some of the accounting is probably wrong in certain cases | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_h_t_t_p___s_e_e_d___c_o_n_n_e_c_t_i_o_n_._c_p_p_:_4_4_1_ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tteecchhnniiccaallllyy,, tthhiiss iissnn''tt ssuuppppoosseedd ttoo hhaappppeenn,, bbuutt iitt sseeeemmss ttoo ssoommeettiimmeess.. SSoommee ooff tthhee aaccccoouunnttiinngg iiss pprroobbaabbllyy wwrroonngg iinn cceerrttaaiinn ccaasseess ********** | │ │ │ │ │ -|****** ....//ssrrcc//hhttttpp__sseeeedd__ccoonnnneeccttiioonn..ccpppp::444411 ****** | │ │ │ │ │ -|// cut out the chunk header from the receive buffer | │ │ │ │ │ -| TORRENT_ASSERT(m_chunk_pos + m_body_start < INT_MAX); | │ │ │ │ │ -| m_recv_buffer.cut(header_size, t->block_size() + 1024, aux::numeric_cast(m_chunk_pos + m_body_start)); | │ │ │ │ │ -| recv_buffer = m_recv_buffer.get(); | │ │ │ │ │ -| recv_buffer = recv_buffer.subspan(m_body_start); | │ │ │ │ │ -| m_chunk_pos += chunk_size; | │ │ │ │ │ -| if (chunk_size == 0) | │ │ │ │ │ -| { | │ │ │ │ │ -| TORRENT_ASSERT(m_recv_buffer.get().size() < m_chunk_pos + m_body_start + 1 | │ │ │ │ │ -| || m_recv_buffer.get()[static_cast(m_chunk_pos + m_body_start)] == 'H' | │ │ │ │ │ -| || (m_parser.chunked_encoding() | │ │ │ │ │ -| && m_recv_buffer.get()[static_cast(m_chunk_pos + m_body_start)] == '\r')); | │ │ │ │ │ -| m_chunk_pos = -1; | │ │ │ │ │ -| } | │ │ │ │ │ -| } | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| int payload = int(bytes_transferred); | │ │ │ │ │ -| if (payload > m_response_left) payload = int(m_response_left); | │ │ │ │ │ -| if (payload > front_request.length) payload = front_request.length; | │ │ │ │ │ -|if (payload > outstanding_bytes()) payload = outstanding_bytes(); | │ │ │ │ │ -|received_bytes(payload, 0); | │ │ │ │ │ -| incoming_piece_fragment(payload); | │ │ │ │ │ -| m_response_left -= payload; | │ │ │ │ │ -| | │ │ │ │ │ -| if (m_parser.status_code() == 503) | │ │ │ │ │ -| { | │ │ │ │ │ -| if (!m_parser.finished()) return; | │ │ │ │ │ -| | │ │ │ │ │ -| int retry_time = std::atoi(std::string(recv_buffer.begin(), recv_buffer.end()).c_str()); | │ │ │ │ │ -| if (retry_time <= 0) retry_time = 60; | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ -| peer_log(peer_log_alert::info, "CONNECT", "retrying in %d seconds", retry_time); | │ │ │ │ │ -|#endif | │ │ │ │ │ -| | │ │ │ │ │ -| received_bytes(0, int(bytes_transferred)); | │ │ │ │ │ -| // temporarily unavailable, retry later | │ │ │ │ │ -| t->retry_web_seed(this, seconds32(retry_time)); | │ │ │ │ │ -| disconnect(error_code(m_parser.status_code(), http_category()), operation_t::bittorrent, failure); | │ │ │ │ │ -| return; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| | │ │ │ │ │ -| // we only received the header, no data | │ │ │ │ │ -| if (recv_buffer.empty()) break; | │ │ │ │ │ -| | │ │ │ │ │ -| if (recv_buffer.size() < front_request.length) break; | │ │ │ │ │ -| | │ │ │ │ │ -| // if the response is chunked, we need to receive the last | │ │ │ │ │ -| // terminating chunk and the tail headers before we can proceed | │ │ │ │ │ -|_ _ _ _i_f_ _(_m___p_a_r_s_e_r_._c_h_u_n_k_e_d___e_n_c_o_d_i_n_g_(_)_ _&_&_ _m___c_h_u_n_k___p_o_s_ _>_=_ _0_)_ _b_r_e_a_k_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_s_r_c_/_p_o_s_i_x___p_a_r_t___f_i_l_e_._c_p_p_:_3_3_7|what do we do if someone is currently reading from the disk from this piece? does it matter? Since we won't actively erase the data | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_f_r_o_m_ _d_i_s_k_,_ _b_u_t_ _i_t_ _m_a_y_ _b_e_ _o_v_e_r_w_r_i_t_t_e_n_ _s_o_o_n_,_ _i_t_'_s_ _p_r_o_b_a_b_l_y_ _n_o_t_ _t_h_a_t_ _b_i_g_ _o_f_ _a_ _d_e_a_l_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** wwhhaatt ddoo wwee ddoo iiff ssoommeeoonnee iiss ccuurrrreennttllyy rreeaaddiinngg ffrroomm tthhee ddiisskk ffrroomm tthhiiss ppiieeccee?? ddooeess iitt mmaatttteerr?? SSiinnccee wwee wwoonn''tt aaccttiivveellyy eerraassee tthhee ddaattaa ffrroomm ddiisskk,, bbuutt iitt mmaayy bbee oovveerrwwrriitttteenn | │ │ │ │ │ -|ssoooonn,, iitt''ss pprroobbaabbllyy nnoott tthhaatt bbiigg ooff aa ddeeaall ********** | │ │ │ │ │ -|****** ....//ssrrcc//ppoossiixx__ppaarrtt__ffiillee..ccpppp::333377 ****** | │ │ │ │ │ -| if (ec) return {}; | │ │ │ │ │ -| | │ │ │ │ │ -|#ifdef TORRENT_WINDOWS | │ │ │ │ │ -| ret = file_pointer(::_wfopen(convert_to_native_path_string(fn).c_str(), L"wb+")); | │ │ │ │ │ -|#else | │ │ │ │ │ -| ret = file_pointer(::fopen(fn.c_str(), "wb+")); | │ │ │ │ │ -|#endif | │ │ │ │ │ -| if (ret.file() == nullptr) | │ │ │ │ │ -| ec.assign(errno, generic_category()); | │ │ │ │ │ -| } | │ │ │ │ │ -| if (ec) return {}; | │ │ │ │ │ -| return ret; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| void posix_part_file::free_piece(piece_index_t const piece) | │ │ │ │ │ -| { | │ │ │ │ │ -| auto const i = m_piece_map.find(piece); | │ │ │ │ │ -| if (i == m_piece_map.end()) return; | │ │ │ │ │ -| | │ │ │ │ │ -| | │ │ │ │ │ -|m_free_slots.push_back(i->second); | │ │ │ │ │ -| m_piece_map.erase(i); | │ │ │ │ │ -| m_dirty_metadata = true; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| void posix_part_file::move_partfile(std::string const& path, error_code& ec) | │ │ │ │ │ -| { | │ │ │ │ │ -| flush_metadata_impl(ec); | │ │ │ │ │ -| if (ec) return; | │ │ │ │ │ -| | │ │ │ │ │ -| if (!m_piece_map.empty()) | │ │ │ │ │ -| { | │ │ │ │ │ -| std::string old_path = combine_path(m_path, m_name); | │ │ │ │ │ -| std::string new_path = combine_path(path, m_name); | │ │ │ │ │ -| | │ │ │ │ │ -| rename(old_path, new_path, ec); | │ │ │ │ │ -| if (ec == boost::system::errc::no_such_file_or_directory) | │ │ │ │ │ -| ec.clear(); | │ │ │ │ │ -| | │ │ │ │ │ -| if (ec) | │ │ │ │ │ -| { | │ │ │ │ │ -| storage_error se; | │ │ │ │ │ -| aux::copy_file(old_path, new_path, se); | │ │ │ │ │ -| ec = se.ec; | │ │ │ │ │ -| if (ec) return; | │ │ │ │ │ -| remove(old_path, ec); | │ │ │ │ │ -| } | │ │ │ │ │ -| } | │ │ │ │ │ -| m_path = path; | │ │ │ │ │ -|_ _}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_p_o_s_i_x___p_a_r_t___f_i_l_e_._c_p_p_:_4_2_5_|_i_n_s_t_e_a_d_ _o_f_ _r_e_b_u_i_l_d_i_n_g_ _t_h_e_ _w_h_o_l_e_ _f_i_l_e_ _h_e_a_d_e_r_ _a_n_d_ _f_l_u_s_h_i_n_g_ _i_t_,_ _u_p_d_a_t_e_ _t_h_e_ _s_l_o_t_ _e_n_t_r_i_e_s_ _a_s_ _w_e_ _g_o_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** iinnsstteeaadd ooff rreebbuuiillddiinngg tthhee wwhhoollee ffiillee hheeaaddeerr aanndd fflluusshhiinngg iitt,, uuppddaattee tthhee sslloott eennttrriieess aass wwee ggoo ********** | │ │ │ │ │ -|****** ....//ssrrcc//ppoossiixx__ppaarrtt__ffiillee..ccpppp::442255 ****** | │ │ │ │ │ -|auto bytes_read = std::fread(buf.get(), 1, std::size_t(block_to_copy), file.file()); | │ │ │ │ │ -| if (int(bytes_read) != block_to_copy) | │ │ │ │ │ -| ec.assign(errno, generic_category()); | │ │ │ │ │ -| | │ │ │ │ │ -| TORRENT_ASSERT(!ec); | │ │ │ │ │ -| if (ec) return; | │ │ │ │ │ -| | │ │ │ │ │ -| f(file_offset, {buf.get(), block_to_copy}); | │ │ │ │ │ -| } | │ │ │ │ │ -| file_offset += block_to_copy; | │ │ │ │ │ -| piece_offset = 0; | │ │ │ │ │ -| size -= block_to_copy; | │ │ │ │ │ -| } | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| void posix_part_file::flush_metadata(error_code& ec) | │ │ │ │ │ -| { | │ │ │ │ │ -| flush_metadata_impl(ec); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -|void posix_part_file::flush_metadata_impl(error_code& ec) | │ │ │ │ │ -|{ | │ │ │ │ │ -| // do we need to flush the metadata? | │ │ │ │ │ -| if (m_dirty_metadata == false) return; | │ │ │ │ │ -| | │ │ │ │ │ -| if (m_piece_map.empty()) | │ │ │ │ │ -| { | │ │ │ │ │ -| // if we don't have any pieces left in the | │ │ │ │ │ -| // part file, remove it | │ │ │ │ │ -| std::string const p = combine_path(m_path, m_name); | │ │ │ │ │ -| remove(p, ec); | │ │ │ │ │ -| | │ │ │ │ │ -| if (ec == boost::system::errc::no_such_file_or_directory) | │ │ │ │ │ -| ec.clear(); | │ │ │ │ │ -| return; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| auto f = open_file(open_mode::read_write, ec); | │ │ │ │ │ -| if (ec) return; | │ │ │ │ │ -| | │ │ │ │ │ -| std::vector header(static_cast(m_header_size)); | │ │ │ │ │ -| | │ │ │ │ │ -| using namespace libtorrent::aux; | │ │ │ │ │ -| | │ │ │ │ │ -| char* ptr = header.data(); | │ │ │ │ │ -| write_uint32(m_max_pieces, ptr); | │ │ │ │ │ -| write_uint32(m_piece_size, ptr); | │ │ │ │ │ -| | │ │ │ │ │ -| for (piece_index_t piece(0); piece < piece_index_t(m_max_pieces); ++piece) | │ │ │ │ │ -| { | │ │ │ │ │ -|_ _ _ _a_u_t_o_ _c_o_n_s_t_ _i_ _=_ _m___p_i_e_c_e___m_a_p_._f_i_n_d_(_p_i_e_c_e_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_u_d_p___s_o_c_k_e_t_._c_p_p_:_6_5_9_ _ _ _ _ _|_p_e_r_h_a_p_s_ _a_n_ _a_t_t_e_m_p_t_ _s_h_o_u_l_d_ _b_e_ _m_a_d_e_ _t_o_ _b_i_n_d_ _m___s_o_c_k_s_5___s_o_c_k_ _t_o_ _t_h_e_ _d_e_v_i_c_e_ _o_f_ _m___l_i_s_t_e_n___s_o_c_k_e_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** ppeerrhhaappss aann aatttteemmpptt sshhoouulldd bbee mmaaddee ttoo bbiinndd mm__ssoocckkss55__ssoocckk ttoo tthhee ddeevviiccee ooff mm__lliisstteenn__ssoocckkeett ********** | │ │ │ │ │ -|****** ....//ssrrcc//uuddpp__ssoocckkeett..ccpppp::665599 ****** | │ │ │ │ │ -|if (ec) | │ │ │ │ │ -| { | │ │ │ │ │ -| if (m_alerts.should_post()) | │ │ │ │ │ -| m_alerts.emplace_alert(m_proxy_addr, operation_t::sock_option, ec); | │ │ │ │ │ -| ec.clear(); | │ │ │ │ │ -| } | │ │ │ │ │ -|#endif | │ │ │ │ │ -|#endif | │ │ │ │ │ -| | │ │ │ │ │ -| tcp::endpoint const bind_ep(m_listen_socket.get_local_endpoint().address(), 0); | │ │ │ │ │ -| m_socks5_sock.bind(bind_ep, ec); | │ │ │ │ │ -| if (ec) | │ │ │ │ │ -| { | │ │ │ │ │ -| if (m_alerts.should_post()) | │ │ │ │ │ -| m_alerts.emplace_alert(m_proxy_addr, operation_t::sock_bind, ec); | │ │ │ │ │ -| ++m_failures; | │ │ │ │ │ -| retry_connection(); | │ │ │ │ │ -| return; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| | │ │ │ │ │ -|ADD_OUTSTANDING_ASYNC("socks5::on_connected"); | │ │ │ │ │ -| m_socks5_sock.async_connect(m_proxy_addr | │ │ │ │ │ -| , std::bind(&socks5::on_connected, self(), _1)); | │ │ │ │ │ -| | │ │ │ │ │ -| ADD_OUTSTANDING_ASYNC("socks5::on_connect_timeout"); | │ │ │ │ │ -| m_timer.expires_after(seconds(10)); | │ │ │ │ │ -| m_timer.async_wait(std::bind(&socks5::on_connect_timeout | │ │ │ │ │ -| , self(), _1)); | │ │ │ │ │ -|} | │ │ │ │ │ -| | │ │ │ │ │ -|void socks5::on_connect_timeout(error_code const& e) | │ │ │ │ │ -|{ | │ │ │ │ │ -| COMPLETE_ASYNC("socks5::on_connect_timeout"); | │ │ │ │ │ -| | │ │ │ │ │ -| if (e == boost::asio::error::operation_aborted) return; | │ │ │ │ │ -| | │ │ │ │ │ -| if (m_abort) return; | │ │ │ │ │ -| | │ │ │ │ │ -| if (m_alerts.should_post()) | │ │ │ │ │ -| m_alerts.emplace_alert(m_proxy_addr, operation_t::connect, errors::timed_out); | │ │ │ │ │ -| | │ │ │ │ │ -| error_code ignore; | │ │ │ │ │ -| m_socks5_sock.close(ignore); | │ │ │ │ │ -| | │ │ │ │ │ -| ++m_failures; | │ │ │ │ │ -| retry_connection(); | │ │ │ │ │ -|} | │ │ │ │ │ -| | │ │ │ │ │ -|void socks5::on_connected(error_code const& e) | │ │ │ │ │ -|_{_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_s_r_c_/_s_t_o_r_a_g_e___u_t_i_l_s_._c_p_p_:_2_3_0 |ideally, if we end up copying files because of a move across volumes, the source should not be deleted until they've all been | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_c_o_p_i_e_d_._ _T_h_a_t_ _w_o_u_l_d_ _l_e_t_ _u_s_ _r_o_l_l_b_a_c_k_ _w_i_t_h_ _h_i_g_h_e_r_ _c_o_n_f_i_d_e_n_c_e_._ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** iiddeeaallllyy,, iiff wwee eenndd uupp ccooppyyiinngg ffiilleess bbeeccaauussee ooff aa mmoovvee aaccrroossss vvoolluummeess,, tthhee ssoouurrccee sshhoouulldd nnoott bbee ddeelleetteedd uunnttiill tthheeyy''vvee aallll bbeeeenn ccooppiieedd.. TThhaatt wwoouulldd lleett uuss rroollllbbaacckk wwiitthh | │ │ │ │ │ -|hhiigghheerr ccoonnffiiddeennccee.. ********** | │ │ │ │ │ -|****** ....//ssrrcc//ssttoorraaggee__uuttiillss..ccpppp::223300 ****** | │ │ │ │ │ -|// later | │ │ │ │ │ -| aux::vector copied_files(std::size_t(f.num_files()), false); | │ │ │ │ │ -| | │ │ │ │ │ -| // track how far we got in case of an error | │ │ │ │ │ -| file_index_t file_index{}; | │ │ │ │ │ -| for (auto const i : f.file_range()) | │ │ │ │ │ -| { | │ │ │ │ │ -| // files moved out to absolute paths are not moved | │ │ │ │ │ -| if (f.file_absolute_path(i)) continue; | │ │ │ │ │ -| | │ │ │ │ │ -| std::string const old_path = combine_path(save_path, f.file_path(i)); | │ │ │ │ │ -| std::string const new_path = combine_path(new_save_path, f.file_path(i)); | │ │ │ │ │ -| | │ │ │ │ │ -| error_code ignore; | │ │ │ │ │ -| if (flags == move_flags_t::dont_replace && exists(new_path, ignore)) | │ │ │ │ │ -| { | │ │ │ │ │ -| if (ret == status_t::no_error) ret = status_t::need_full_check; | │ │ │ │ │ -| continue; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -|move_file(old_path, new_path, ec); | │ │ │ │ │ -| | │ │ │ │ │ -| // if the source file doesn't exist. That's not a problem | │ │ │ │ │ -| // we just ignore that file | │ │ │ │ │ -| if (ec.ec == boost::system::errc::no_such_file_or_directory) | │ │ │ │ │ -| ec.ec.clear(); | │ │ │ │ │ -| else if (ec | │ │ │ │ │ -| && ec.ec != boost::system::errc::invalid_argument | │ │ │ │ │ -| && ec.ec != boost::system::errc::permission_denied) | │ │ │ │ │ -| { | │ │ │ │ │ -| // moving the file failed | │ │ │ │ │ -| // on OSX, the error when trying to rename a file across different | │ │ │ │ │ -| // volumes is EXDEV, which will make it fall back to copying. | │ │ │ │ │ -| ec.ec.clear(); | │ │ │ │ │ -| copy_file(old_path, new_path, ec); | │ │ │ │ │ -| if (!ec) copied_files[i] = true; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| if (ec) | │ │ │ │ │ -| { | │ │ │ │ │ -| ec.file(i); | │ │ │ │ │ -| file_index = i; | │ │ │ │ │ -| break; | │ │ │ │ │ -| } | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| if (!ec && move_partfile) | │ │ │ │ │ -| { | │ │ │ │ │ -| error_code e; | │ │ │ │ │ -| move_partfile(new_save_path, e); | │ │ │ │ │ -|_ _ _ _i_f_ _(_e_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_s_r_c_/_s_t_o_r_a_g_e___u_t_i_l_s_._c_p_p_:_5_3_8 |it would seem reasonable to, instead, set the have_pieces bits for the pieces representing these files, and resume with the normal | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_l_o_g_i_c_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** iitt wwoouulldd sseeeemm rreeaassoonnaabbllee ttoo,, iinnsstteeaadd,, sseett tthhee hhaavvee__ppiieecceess bbiittss ffoorr tthhee ppiieecceess rreepprreesseennttiinngg tthheessee ffiilleess,, aanndd rreessuummee wwiitthh tthhee nnoorrmmaall llooggiicc ********** | │ │ │ │ │ -|****** ....//ssrrcc//ssttoorraaggee__uuttiillss..ccpppp::553388 ****** | │ │ │ │ │ -|continue; | │ │ │ │ │ -| | │ │ │ │ │ -| std::int64_t const size = get_filesize(stat, file_index, fs | │ │ │ │ │ -| , save_path, ec); | │ │ │ │ │ -| if (size < 0) return false; | │ │ │ │ │ -| | │ │ │ │ │ -| if (size < fs.file_size(file_index)) | │ │ │ │ │ -| { | │ │ │ │ │ -| ec.ec = errors::mismatching_file_size; | │ │ │ │ │ -| ec.file(file_index); | │ │ │ │ │ -| ec.operation = operation_t::check_resume; | │ │ │ │ │ -| return false; | │ │ │ │ │ -| } | │ │ │ │ │ -| } | │ │ │ │ │ -| return true; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_MUTABLE_TORRENTS | │ │ │ │ │ -| // always trigger a full recheck when we pull in files from other | │ │ │ │ │ -| // torrents, via hard links | │ │ │ │ │ -|if (added_files) return false; | │ │ │ │ │ -|#endif | │ │ │ │ │ -| | │ │ │ │ │ -| // parse have bitmask. Verify that the files we expect to have | │ │ │ │ │ -| // actually do exist | │ │ │ │ │ -| piece_index_t const end_piece = std::min(rd.have_pieces.end_index(), fs.end_piece()); | │ │ │ │ │ -| for (piece_index_t i(0); i < end_piece; ++i) | │ │ │ │ │ -| { | │ │ │ │ │ -| if (rd.have_pieces.get_bit(i) == false) continue; | │ │ │ │ │ -| | │ │ │ │ │ -| std::vector f = fs.map_block(i, 0, 1); | │ │ │ │ │ -| TORRENT_ASSERT(!f.empty()); | │ │ │ │ │ -| | │ │ │ │ │ -| file_index_t const file_index = f[0].file_index; | │ │ │ │ │ -| | │ │ │ │ │ -| // files with priority zero may not have been saved to disk at their | │ │ │ │ │ -| // expected location, but is likely to be in a partfile. Just exempt it | │ │ │ │ │ -| // from checking | │ │ │ │ │ -| if (file_index < file_priority.end_index() | │ │ │ │ │ -| && file_priority[file_index] == dont_download) | │ │ │ │ │ -| continue; | │ │ │ │ │ -| | │ │ │ │ │ -| if (fs.pad_file_at(file_index)) continue; | │ │ │ │ │ -| | │ │ │ │ │ -| if (get_filesize(stat, file_index, fs, save_path, ec) < 0) | │ │ │ │ │ -| return false; | │ │ │ │ │ -| | │ │ │ │ │ -| // OK, this file existed, good. Now, skip all remaining pieces in | │ │ │ │ │ -| // this file. We're just sanity-checking whether the files exist | │ │ │ │ │ -| // or not. | │ │ │ │ │ -|_ _ _ _p_e_e_r___r_e_q_u_e_s_t_ _c_o_n_s_t_ _p_r_ _=_ _f_s_._m_a_p___f_i_l_e_(_f_i_l_e___i_n_d_e_x_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_i_p___n_o_t_i_f_i_e_r_._c_p_p_:_4_1_ _ _ _ _ _|_s_i_m_u_l_a_t_o_r_ _s_u_p_p_o_r_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** ssiimmuullaattoorr ssuuppppoorrtt ********** | │ │ │ │ │ |****** ....//ssrrcc//iipp__nnoottiiffiieerr..ccpppp::4411 ****** | │ │ │ │ │ | from this software without specific prior written permission. | │ │ │ │ │ | | │ │ │ │ │ |THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | │ │ │ │ │ |AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | │ │ │ │ │ @@ -7273,1123 +7149,14 @@ │ │ │ │ │ | | │ │ │ │ │ |#if (TORRENT_USE_SYSTEMCONFIGURATION || TORRENT_USE_SC_NETWORK_REACHABILITY) && \ | │ │ │ │ │ | !defined TORRENT_BUILD_SIMULATOR | │ │ │ │ │ | | │ │ │ │ │ |// common utilities for Mac and iOS | │ │ │ │ │ |template void CFRefRetain(T h) { CFRetain(h); } | │ │ │ │ │ |_t_e_m_p_l_a_t_e_ _<_t_y_p_e_n_a_m_e_ _T_>_ _v_o_i_d_ _C_F_R_e_f_R_e_l_e_a_s_e_(_T_ _h_)_ _{_ _C_F_R_e_l_e_a_s_e_(_h_)_;_ _}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_u_t_p___s_t_r_e_a_m_._c_p_p_:_1_4_6_7_ _ _ _ _|_t_h_i_s_ _l_o_o_p_ _i_s_ _n_o_t_ _v_e_r_y_ _e_f_f_i_c_i_e_n_t_._ _I_t_ _c_o_u_l_d_ _b_e_ _f_i_x_e_d_ _b_y_ _h_a_v_i_n_g_ _a_ _s_e_p_a_r_a_t_e_ _l_i_s_t_ _o_f_ _s_e_q_u_e_n_c_e_ _n_u_m_b_e_r_s_ _t_h_a_t_ _n_e_e_d_ _r_e_s_e_n_d_i_n_g_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tthhiiss lloooopp iiss nnoott vveerryy eeffffiicciieenntt.. IItt ccoouulldd bbee ffiixxeedd bbyy hhaavviinngg aa sseeppaarraattee lliisstt ooff sseeqquueennccee nnuummbbeerrss tthhaatt nneeeedd rreesseennddiinngg ********** | │ │ │ │ │ -|****** ....//ssrrcc//uuttpp__ssttrreeaamm..ccpppp::11446677 ****** | │ │ │ │ │ -|#endif | │ │ │ │ │ -| | │ │ │ │ │ -| if (m_stalled) | │ │ │ │ │ -| { | │ │ │ │ │ -| if (flags & pkt_ack) | │ │ │ │ │ -| defer_ack(); | │ │ │ │ │ -| return false; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| // m_out_eof means we're trying to close the write side of this socket, | │ │ │ │ │ -| // we need to flush all payload before we can send the FIN packet, so don't | │ │ │ │ │ -| // store any payload in the nagle packet | │ │ │ │ │ -| bool const force = (flags & pkt_ack) || (flags & pkt_fin) || m_out_eof; | │ │ │ │ │ -| | │ │ │ │ │ -| // when we want to close the outgoing stream, we need to send the | │ │ │ │ │ -| // remaining nagle packet even though it won't fill a packet. | │ │ │ │ │ -| bool const force_flush_nagle = m_out_eof && m_write_buffer_size; | │ │ │ │ │ -| | │ │ │ │ │ -| // first see if we need to resend any packets | │ │ │ │ │ -| | │ │ │ │ │ -|for (int i = (m_acked_seq_nr + 1) & ACK_MASK; i != m_seq_nr; i = (i + 1) & ACK_MASK) | │ │ │ │ │ -|{ | │ │ │ │ │ -| packet* p = m_outbuf.at(aux::numeric_cast(i)); | │ │ │ │ │ -| if (!p) continue; | │ │ │ │ │ -| if (!p->need_resend) continue; | │ │ │ │ │ -| if (!resend_packet(p)) | │ │ │ │ │ -| { | │ │ │ │ │ -| // we couldn't resend the packet. It probably doesn't | │ │ │ │ │ -| // fit in our cwnd. If force is set, we need to continue | │ │ │ │ │ -| // to send our packet anyway, if we don't have force set, | │ │ │ │ │ -| // we might as well return | │ │ │ │ │ -| if (!force) return false; | │ │ │ │ │ -| // resend_packet might have failed | │ │ │ │ │ -| if (state() == state_t::error_wait || state() == state_t::deleting) return false; | │ │ │ │ │ -| if (m_stalled) return false; | │ │ │ │ │ -| break; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| // don't fast-resend this packet | │ │ │ │ │ -| if (m_fast_resend_seq_nr == i) | │ │ │ │ │ -| m_fast_resend_seq_nr = (m_fast_resend_seq_nr + 1) & ACK_MASK; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| // MTU DISCOVERY | │ │ │ │ │ -| | │ │ │ │ │ -| // under these conditions, the next packet we send should be an MTU probe. | │ │ │ │ │ -| // MTU probes get to use the mid-point packet size, whereas other packets | │ │ │ │ │ -| // use a conservative packet size of the largest known to work. The reason | │ │ │ │ │ -| // for the cwnd condition is to make sure the probe is surrounded by non- | │ │ │ │ │ -| // probes, to be able to distinguish a loss of the probe vs. just loss in | │ │ │ │ │ -|_ _/_/_ _g_e_n_e_r_a_l_._ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_s_r_c_/ |move stats_counter_t out of counters | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_p_e_r_f_o_r_m_a_n_c_e___c_o_u_n_t_e_r_s_._c_p_p_:_4_0_ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** mmoovvee ssttaattss__ccoouunntteerr__tt oouutt ooff ccoouunntteerrss ********** | │ │ │ │ │ -|_**_**_**_ _.._.._//_ss_rr_cc_//_pp_ee_rr_ff_oo_rr_mm_aa_nn_cc_ee____cc_oo_uu_nn_tt_ee_rr_ss_.._cc_pp_pp_::_44_00_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_s_r_c_/ |should bittorrent keep-alive messages have a counter too? | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_p_e_r_f_o_r_m_a_n_c_e___c_o_u_n_t_e_r_s_._c_p_p_:_4_1_ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** sshhoouulldd bbiittttoorrrreenntt kkeeeepp--aalliivvee mmeessssaaggeess hhaavvee aa ccoouunntteerr ttoooo?? ********** | │ │ │ │ │ -|_**_**_**_ _.._.._//_ss_rr_cc_//_pp_ee_rr_ff_oo_rr_mm_aa_nn_cc_ee____cc_oo_uu_nn_tt_ee_rr_ss_.._cc_pp_pp_::_44_11_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_s_r_c_/ |It would be nice if this could be an internal type. default_disk_constructor depends on it now | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_p_e_r_f_o_r_m_a_n_c_e___c_o_u_n_t_e_r_s_._c_p_p_:_4_2_ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** IItt wwoouulldd bbee nniiccee iiff tthhiiss ccoouulldd bbee aann iinntteerrnnaall ttyyppee.. ddeeffaauulltt__ddiisskk__ccoonnssttrruuccttoorr ddeeppeennddss oonn iitt nnooww ********** | │ │ │ │ │ -|****** ....//ssrrcc//ppeerrffoorrmmaannccee__ccoouunntteerrss..ccpppp::4422 ****** | │ │ │ │ │ -|THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | │ │ │ │ │ -|AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | │ │ │ │ │ -|IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | │ │ │ │ │ -|ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | │ │ │ │ │ -|LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | │ │ │ │ │ -|CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | │ │ │ │ │ -|SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | │ │ │ │ │ -|INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | │ │ │ │ │ -|CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | │ │ │ │ │ -|ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | │ │ │ │ │ -|POSSIBILITY OF SUCH DAMAGE. | │ │ │ │ │ -| | │ │ │ │ │ -|*/ | │ │ │ │ │ -| | │ │ │ │ │ -|#include "libtorrent/performance_counters.hpp" | │ │ │ │ │ -|#include "libtorrent/assert.hpp" | │ │ │ │ │ -|#include // for memset | │ │ │ │ │ -| | │ │ │ │ │ -|namespace libtorrent { | │ │ │ │ │ -| | │ │ │ │ │ -|counters::counters() TORRENT_COUNTER_NOEXCEPT | │ │ │ │ │ -|{ | │ │ │ │ │ -|#ifdef ATOMIC_LLONG_LOCK_FREE | │ │ │ │ │ -| for (auto& counter : m_stats_counter) | │ │ │ │ │ -| counter.store(0, std::memory_order_relaxed); | │ │ │ │ │ -|#else | │ │ │ │ │ -| m_stats_counter.fill(0); | │ │ │ │ │ -|#endif | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| counters::counters(counters const& c) TORRENT_COUNTER_NOEXCEPT | │ │ │ │ │ -| { | │ │ │ │ │ -|#ifdef ATOMIC_LLONG_LOCK_FREE | │ │ │ │ │ -| for (int i = 0; i < m_stats_counter.end_index(); ++i) | │ │ │ │ │ -| m_stats_counter[i].store( | │ │ │ │ │ -| c.m_stats_counter[i].load(std::memory_order_relaxed) | │ │ │ │ │ -| , std::memory_order_relaxed); | │ │ │ │ │ -|#else | │ │ │ │ │ -| std::lock_guard l(c.m_mutex); | │ │ │ │ │ -| m_stats_counter = c.m_stats_counter; | │ │ │ │ │ -|#endif | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| counters& counters::operator=(counters const& c) & TORRENT_COUNTER_NOEXCEPT | │ │ │ │ │ -| { | │ │ │ │ │ -| if (&c == this) return *this; | │ │ │ │ │ -|#ifdef ATOMIC_LLONG_LOCK_FREE | │ │ │ │ │ -| for (int i = 0; i < m_stats_counter.end_index(); ++i) | │ │ │ │ │ -| m_stats_counter[i].store( | │ │ │ │ │ -| c.m_stats_counter[i].load(std::memory_order_relaxed) | │ │ │ │ │ -|_ _ _ _ _ _,_ _s_t_d_:_:_m_e_m_o_r_y___o_r_d_e_r___r_e_l_a_x_e_d_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_s_r_c_/_d_i_s_a_b_l_e_d___d_i_s_k___i_o_._c_p_p_: |it would be nice to return a valid hash of zeroes here | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_1_0_6_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** iitt wwoouulldd bbee nniiccee ttoo rreettuurrnn aa vvaalliidd hhaasshh ooff zzeerrooeess hheerree ********** | │ │ │ │ │ -|****** ....//ssrrcc//ddiissaabblleedd__ddiisskk__iioo..ccpppp::110066 ****** | │ │ │ │ │ -|}); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| bool async_write(storage_index_t | │ │ │ │ │ -| , peer_request const& r | │ │ │ │ │ -| , char const*, std::shared_ptr | │ │ │ │ │ -| , std::function handler | │ │ │ │ │ -| , disk_job_flags_t) override | │ │ │ │ │ -| { | │ │ │ │ │ -| TORRENT_ASSERT(r.length <= default_block_size); | │ │ │ │ │ -| TORRENT_UNUSED(r); | │ │ │ │ │ -| | │ │ │ │ │ -| post(m_ios, [h = std::move(handler)] { h(storage_error{}); }); | │ │ │ │ │ -| return false; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| void async_hash(storage_index_t | │ │ │ │ │ -| , piece_index_t piece, span, disk_job_flags_t | │ │ │ │ │ -| , std::function handler) override | │ │ │ │ │ -| { | │ │ │ │ │ -|post(m_ios, [h = std::move(handler), piece] { h(piece, sha1_hash{}, storage_error{}); }); | │ │ │ │ │ -|} | │ │ │ │ │ -| | │ │ │ │ │ -| void async_hash2(storage_index_t, piece_index_t piece, int | │ │ │ │ │ -| , disk_job_flags_t | │ │ │ │ │ -| , std::function handler) override | │ │ │ │ │ -| { | │ │ │ │ │ -| post(m_ios, [h = std::move(handler), piece]() { h(piece, sha256_hash{}, storage_error{}); }); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| void async_move_storage(storage_index_t | │ │ │ │ │ -| , std::string p, move_flags_t | │ │ │ │ │ -| , std::function handler) override | │ │ │ │ │ -| { | │ │ │ │ │ -| post(m_ios, [h = std::move(handler), path = std::move(p)] () mutable | │ │ │ │ │ -| { h(status_t::no_error, std::move(path), storage_error{}); }); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| void async_release_files(storage_index_t, std::function handler) override | │ │ │ │ │ -| { | │ │ │ │ │ -| post(m_ios, [h = std::move(handler)] { h(); }); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| void async_delete_files(storage_index_t | │ │ │ │ │ -| , remove_flags_t, std::function handler) override | │ │ │ │ │ -| { | │ │ │ │ │ -| post(m_ios, [h = std::move(handler)] { h(storage_error{}); }); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| void async_check_files(storage_index_t | │ │ │ │ │ -|_ _ _,_ _a_d_d___t_o_r_r_e_n_t___p_a_r_a_m_s_ _c_o_n_s_t_*_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_s_r_c_/_u_t_p___s_o_c_k_e_t___m_a_n_a_g_e_r_._c_p_p_:|this should not be heap allocated, sockets should be movable | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_2_0_4_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tthhiiss sshhoouulldd nnoott bbee hheeaapp aallllooccaatteedd,, ssoocckkeettss sshhoouulldd bbee mmoovvaabbllee ********** | │ │ │ │ │ -|****** ....//ssrrcc//uuttpp__ssoocckkeett__mmaannaaggeerr..ccpppp::220044 ****** | │ │ │ │ │ -|// UTP_LOGV("incoming packet id:%d source:%s\n", id, print_endpoint(ep).c_str()); | │ │ │ │ │ -| | │ │ │ │ │ -| if (!m_sett.get_bool(settings_pack::enable_incoming_utp)) | │ │ │ │ │ -| return false; | │ │ │ │ │ -| | │ │ │ │ │ -| // if not found, see if it's a SYN packet, if it is, | │ │ │ │ │ -| // create a new utp_stream | │ │ │ │ │ -| if (ph->get_type() == ST_SYN) | │ │ │ │ │ -| { | │ │ │ │ │ -| // possible SYN flood. Just ignore | │ │ │ │ │ -| if (int(m_utp_sockets.size()) > m_sett.get_int(settings_pack::connections_limit) * 2) | │ │ │ │ │ -| return false; | │ │ │ │ │ -| | │ │ │ │ │ -| TORRENT_ASSERT(m_new_connection == -1); | │ │ │ │ │ -| // create the new socket with this ID | │ │ │ │ │ -| m_new_connection = id; | │ │ │ │ │ -| | │ │ │ │ │ -|// UTP_LOGV("not found, new connection id:%d\n", m_new_connection); | │ │ │ │ │ -| | │ │ │ │ │ -|aux::socket_type c(aux::instantiate_connection(m_ios, aux::proxy_settings(), m_ssl_context, this, true, false)); | │ │ │ │ │ -| | │ │ │ │ │ -| utp_stream* str = nullptr; | │ │ │ │ │ -|#ifdef TORRENT_SSL_PEERS | │ │ │ │ │ -| if (is_ssl(c)) | │ │ │ │ │ -| str = &boost::get>(c).next_layer(); | │ │ │ │ │ -| else | │ │ │ │ │ -|#endif | │ │ │ │ │ -| str = boost::get(&c); | │ │ │ │ │ -| | │ │ │ │ │ -| TORRENT_ASSERT(str); | │ │ │ │ │ -| int const mtu = mtu_for_dest(ep.address()); | │ │ │ │ │ -| str->get_impl()->init_mtu(mtu); | │ │ │ │ │ -| str->get_impl()->m_sock = std::move(socket); | │ │ │ │ │ -| bool const ret = str->get_impl()->incoming_packet(p, ep, receive_time); | │ │ │ │ │ -| if (!ret) return false; | │ │ │ │ │ -| m_last_socket = str->get_impl(); | │ │ │ │ │ -| m_cb(std::move(c)); | │ │ │ │ │ -| // the connection most likely changed its connection ID here | │ │ │ │ │ -| // we need to move it to the correct ID | │ │ │ │ │ -| return true; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| if (ph->get_type() == ST_RESET) return false; | │ │ │ │ │ -| | │ │ │ │ │ -| // #error send reset | │ │ │ │ │ -| | │ │ │ │ │ -| return false; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -|_ _v_o_i_d_ _u_t_p___s_o_c_k_e_t___m_a_n_a_g_e_r_:_:_s_u_b_s_c_r_i_b_e___w_r_i_t_a_b_l_e_(_u_t_p___s_o_c_k_e_t___i_m_p_l_*_ _s_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_c_r_e_a_t_e___t_o_r_r_e_n_t_._c_p_p_:_6_1_1_ _|_t_h_i_s_ _c_a_n_ _b_e_ _o_p_t_i_m_i_z_e_d_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tthhiiss ccaann bbee ooppttiimmiizzeedd ********** | │ │ │ │ │ -|****** ....//ssrrcc//ccrreeaattee__ttoorrrreenntt..ccpppp::661111 ****** | │ │ │ │ │ -|std::string& attr = e["attr"].string(); | │ │ │ │ │ -| if (flags & file_storage::flag_pad_file) attr += 'p'; | │ │ │ │ │ -| if (flags & file_storage::flag_hidden) attr += 'h'; | │ │ │ │ │ -| if (flags & file_storage::flag_executable) attr += 'x'; | │ │ │ │ │ -| if (include_symlinks && (flags & file_storage::flag_symlink)) attr += 'l'; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| void add_symlink_path(entry& e, std::string symlink_path) | │ │ │ │ │ -| { | │ │ │ │ │ -| entry& sympath_e = e["symlink path"]; | │ │ │ │ │ -| | │ │ │ │ │ -| std::string const link = lexically_relative("", symlink_path); | │ │ │ │ │ -| for (auto elems = lsplit_path(link); !elems.first.empty(); | │ │ │ │ │ -| elems = lsplit_path(elems.second)) | │ │ │ │ │ -| sympath_e.list().emplace_back(elems.first); | │ │ │ │ │ -| } | │ │ │ │ │ -|} | │ │ │ │ │ -| | │ │ │ │ │ -| std::vector create_torrent::generate_buf() const | │ │ │ │ │ -| { | │ │ │ │ │ -|std::vector ret; | │ │ │ │ │ -|bencode(std::back_inserter(ret), generate()); | │ │ │ │ │ -| return ret; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| entry create_torrent::generate() const | │ │ │ │ │ -| { | │ │ │ │ │ -| if (m_files.num_files() == 0 || m_files.total_size() == 0) | │ │ │ │ │ -| aux::throw_ex(errors::torrent_missing_file_tree); | │ │ │ │ │ -| | │ │ │ │ │ -| // if all v2 hashes are set correctly, generate the v2 parts of the | │ │ │ │ │ -| // torrent | │ │ │ │ │ -| bool const make_v2 = validate_v2_hashes(m_files, m_file_piece_hash); | │ │ │ │ │ -| bool const make_v1 = validate_v1_hashes(m_files, m_piece_hash); | │ │ │ │ │ -| | │ │ │ │ │ -| // if neither v1 nor v2 hashes were set, we can't create a torrent | │ │ │ │ │ -| if (!make_v1 && !make_v2) | │ │ │ │ │ -| aux::throw_ex(errors::invalid_hash_entry); | │ │ │ │ │ -| | │ │ │ │ │ -| TORRENT_ASSERT(m_files.piece_length() > 0); | │ │ │ │ │ -| | │ │ │ │ │ -| entry dict; | │ │ │ │ │ -| | │ │ │ │ │ -| if (!m_urls.empty()) dict["announce"] = m_urls.front().first; | │ │ │ │ │ -| | │ │ │ │ │ -| if (!m_nodes.empty()) | │ │ │ │ │ -| { | │ │ │ │ │ -| entry& nodes = dict["nodes"]; | │ │ │ │ │ -| entry::list_type& nodes_list = nodes.list(); | │ │ │ │ │ -| for (auto const& n : m_nodes) | │ │ │ │ │ -|_ _ _ _{_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_s_r_c_/ |why is this a linked list? | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_u_d_p___t_r_a_c_k_e_r___c_o_n_n_e_c_t_i_o_n_._c_p_p_:_6_3_3_|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** wwhhyy iiss tthhiiss aa lliinnkkeedd lliisstt?? ********** | │ │ │ │ │ -|****** ....//ssrrcc//uuddpp__ttrraacckkeerr__ccoonnnneeccttiioonn..ccpppp::663333 ****** | │ │ │ │ │ -|ipv6_peer_entry e{}; | │ │ │ │ │ -| std::memcpy(e.ip.data(), buf.data(), 16); | │ │ │ │ │ -| buf = buf.subspan(16); | │ │ │ │ │ -| e.port = aux::read_uint16(buf); | │ │ │ │ │ -| resp.peers6.push_back(e); | │ │ │ │ │ -| } | │ │ │ │ │ -| } | │ │ │ │ │ -| else | │ │ │ │ │ -| { | │ │ │ │ │ -| resp.peers4.reserve(static_cast(num_peers)); | │ │ │ │ │ -| for (int i = 0; i < num_peers; ++i) | │ │ │ │ │ -| { | │ │ │ │ │ -| ipv4_peer_entry e{}; | │ │ │ │ │ -| std::memcpy(e.ip.data(), buf.data(), 4); | │ │ │ │ │ -| buf = buf.subspan(4); | │ │ │ │ │ -| e.port = aux::read_uint16(buf); | │ │ │ │ │ -| resp.peers4.push_back(e); | │ │ │ │ │ -| } | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -|std::list
    ip_list; | │ │ │ │ │ -|std::transform(m_endpoints.begin(), m_endpoints.end(), std::back_inserter(ip_list) | │ │ │ │ │ -| , [](tcp::endpoint const& ep) { return ep.address(); } ); | │ │ │ │ │ -| | │ │ │ │ │ -| cb->tracker_response(tracker_req(), m_target.address(), ip_list, resp); | │ │ │ │ │ -| | │ │ │ │ │ -| close(); | │ │ │ │ │ -| return true; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| bool udp_tracker_connection::on_scrape_response(span buf) | │ │ │ │ │ -| { | │ │ │ │ │ -| restart_read_timeout(); | │ │ │ │ │ -| auto const action = static_cast(aux::read_int32(buf)); | │ │ │ │ │ -| std::uint32_t const transaction = aux::read_uint32(buf); | │ │ │ │ │ -| | │ │ │ │ │ -| if (transaction != m_transaction_id) | │ │ │ │ │ -| { | │ │ │ │ │ -| fail(error_code(errors::invalid_tracker_transaction_id), operation_t::bittorrent); | │ │ │ │ │ -| return false; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| if (action == action_t::error) | │ │ │ │ │ -| { | │ │ │ │ │ -| fail(error_code(errors::tracker_failure), operation_t::bittorrent | │ │ │ │ │ -| , std::string(buf.data(), static_cast(buf.size())).c_str()); | │ │ │ │ │ -| return true; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| if (action != action_t::scrape) | │ │ │ │ │ -|_ _ _{_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_c_p_u_i_d_._c_p_p_:_1_3_1_ _ _ _ _ _ _ _ _ _ _|_e_n_a_b_l_e_ _w_h_e_n_ _a_a_r_c_h_6_4_ _i_s_ _r_e_a_l_l_y_ _t_e_s_t_e_d_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** eennaabbllee wwhheenn aaaarrcchh6644 iiss rreeaallllyy tteesstteedd ********** | │ │ │ │ │ -|****** ....//ssrrcc//ccppuuiidd..ccpppp::113311 ****** | │ │ │ │ │ -|bool supports_mmx() noexcept | │ │ │ │ │ -| { | │ │ │ │ │ -|#if TORRENT_HAS_SSE | │ │ │ │ │ -| std::uint32_t cpui[4] = {0}; | │ │ │ │ │ -| cpuid(cpui, 1); | │ │ │ │ │ -| return (cpui[2] & (1 << 23)) != 0; | │ │ │ │ │ -|#else | │ │ │ │ │ -| return false; | │ │ │ │ │ -|#endif | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| bool supports_arm_neon() noexcept | │ │ │ │ │ -| { | │ │ │ │ │ -|#if TORRENT_HAS_ARM_NEON && TORRENT_HAS_AUXV | │ │ │ │ │ -|#if defined __arm__ | │ │ │ │ │ -| //return (getauxval(AT_HWCAP) & HWCAP_NEON); | │ │ │ │ │ -| return (helper_getauxval(16) & (1 << 12)); | │ │ │ │ │ -|#elif defined __aarch64__ | │ │ │ │ │ -| //return (getauxval(AT_HWCAP) & HWCAP_ASIMD); | │ │ │ │ │ -| //return (getauxval(16) & (1 << 1)); | │ │ │ │ │ -|return false; | │ │ │ │ │ -|#endif | │ │ │ │ │ -|#else | │ │ │ │ │ -| return false; | │ │ │ │ │ -|#endif | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| bool supports_arm_crc32c() noexcept | │ │ │ │ │ -| { | │ │ │ │ │ -|#if TORRENT_HAS_ARM_CRC32 && TORRENT_HAS_AUXV | │ │ │ │ │ -|#if defined TORRENT_FORCE_ARM_CRC32 | │ │ │ │ │ -| return true; | │ │ │ │ │ -|#elif defined __arm__ | │ │ │ │ │ -| //return (getauxval(AT_HWCAP2) & HWCAP2_CRC32); | │ │ │ │ │ -| return (helper_getauxval(26) & (1 << 4)); | │ │ │ │ │ -|#elif defined __aarch64__ | │ │ │ │ │ -| //return (getauxval(AT_HWCAP) & HWCAP_CRC32); | │ │ │ │ │ -| return (helper_getauxval(16) & (1 << 7)); | │ │ │ │ │ -|#endif | │ │ │ │ │ -|#else | │ │ │ │ │ -| return false; | │ │ │ │ │ -|#endif | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -|} // anonymous namespace | │ │ │ │ │ -| | │ │ │ │ │ -| bool const sse42_support = supports_sse42(); | │ │ │ │ │ -| bool const mmx_support = supports_mmx(); | │ │ │ │ │ -| bool const arm_neon_support = supports_arm_neon(); | │ │ │ │ │ -| bool const arm_crc32c_support = supports_arm_crc32c(); | │ │ │ │ │ -|_}_ _}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_m_m_a_p___d_i_s_k___i_o_._c_p_p_:_5_7_8_ _ _ _|_i_n_ _t_h_e_ _f_u_t_u_r_e_,_ _p_r_o_p_a_g_a_t_e_ _e_x_c_e_p_t_i_o_n_s_ _b_a_c_k_ _t_o_ _t_h_e_ _h_a_n_d_l_e_r_s_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** iinn tthhee ffuuttuurree,, pprrooppaaggaattee eexxcceeppttiioonnss bbaacckk ttoo tthhee hhaannddlleerrss ********** | │ │ │ │ │ -|****** ....//ssrrcc//mmmmaapp__ddiisskk__iioo..ccpppp::557788 ****** | │ │ │ │ │ -|#if DEBUG_DISK_THREAD | │ │ │ │ │ -| { | │ │ │ │ │ -| std::unique_lock l(m_job_mutex); | │ │ │ │ │ -| | │ │ │ │ │ -| DLOG("perform_job job: %s ( %s%s) piece: %d offset: %d outstanding: %d\n" | │ │ │ │ │ -| , job_action_name[j->action] | │ │ │ │ │ -| , (j->flags & mmap_disk_job::fence) ? "fence ": "" | │ │ │ │ │ -| , (j->flags & mmap_disk_job::force_copy) ? "force_copy ": "" | │ │ │ │ │ -| , static_cast(j->piece), j->d.io.offset | │ │ │ │ │ -| , j->storage ? j->storage->num_outstanding_jobs() : -1); | │ │ │ │ │ -| } | │ │ │ │ │ -|#endif | │ │ │ │ │ -| | │ │ │ │ │ -| std::shared_ptr storage = j->storage; | │ │ │ │ │ -| | │ │ │ │ │ -| TORRENT_ASSERT(static_cast(j->action) < int(job_functions.size())); | │ │ │ │ │ -| | │ │ │ │ │ -| m_stats_counters.inc_stats_counter(counters::num_running_disk_jobs, 1); | │ │ │ │ │ -| | │ │ │ │ │ -| // call disk function | │ │ │ │ │ -|status_t ret = status_t::no_error; | │ │ │ │ │ -|try | │ │ │ │ │ -| { | │ │ │ │ │ -| int const idx = static_cast(j->action); | │ │ │ │ │ -| ret = (this->*(job_functions[static_cast(idx)]))(j); | │ │ │ │ │ -| } | │ │ │ │ │ -| catch (boost::system::system_error const& err) | │ │ │ │ │ -| { | │ │ │ │ │ -| ret = status_t::fatal_disk_error; | │ │ │ │ │ -| j->error.ec = err.code(); | │ │ │ │ │ -| j->error.operation = operation_t::exception; | │ │ │ │ │ -| } | │ │ │ │ │ -| catch (std::bad_alloc const&) | │ │ │ │ │ -| { | │ │ │ │ │ -| ret = status_t::fatal_disk_error; | │ │ │ │ │ -| j->error.ec = errors::no_memory; | │ │ │ │ │ -| j->error.operation = operation_t::exception; | │ │ │ │ │ -| } | │ │ │ │ │ -| catch (std::exception const&) | │ │ │ │ │ -| { | │ │ │ │ │ -| ret = status_t::fatal_disk_error; | │ │ │ │ │ -| j->error.ec = boost::asio::error::fault; | │ │ │ │ │ -| j->error.operation = operation_t::exception; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| // note that -2 errors are OK | │ │ │ │ │ -| TORRENT_ASSERT(ret != status_t::fatal_disk_error | │ │ │ │ │ -| || (j->error.ec && j->error.operation != operation_t::unknown)); | │ │ │ │ │ -| | │ │ │ │ │ -|_ _ _m___s_t_a_t_s___c_o_u_n_t_e_r_s_._i_n_c___s_t_a_t_s___c_o_u_n_t_e_r_(_c_o_u_n_t_e_r_s_:_:_n_u_m___r_u_n_n_i_n_g___d_i_s_k___j_o_b_s_,_ _-_1_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_s_r_c_/_m_m_a_p___d_i_s_k___i_o_._c_p_p_:_1_0_1_7 |this is potentially very expensive. One way to solve it would be to have a fence for just this one piece. but it hardly seems worth | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_t_h_e_ _c_o_m_p_l_e_x_i_t_y_ _a_n_d_ _c_o_s_t_ _j_u_s_t_ _f_o_r_ _t_h_e_ _e_d_g_e_ _c_a_s_e_ _o_f_ _r_e_c_e_i_v_i_n_g_ _a_ _c_o_r_r_u_p_t_ _p_i_e_c_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tthhiiss iiss ppootteennttiiaallllyy vveerryy eexxppeennssiivvee.. OOnnee wwaayy ttoo ssoollvvee iitt wwoouulldd bbee ttoo hhaavvee aa ffeennccee ffoorr jjuusstt tthhiiss oonnee ppiieeccee.. bbuutt iitt hhaarrddllyy sseeeemmss wwoorrtthh tthhee ccoommpplleexxiittyy aanndd ccoosstt jjuusstt ffoorr tthhee | │ │ │ │ │ -|eeddggee ccaassee ooff rreecceeiivviinngg aa ccoorrrruupptt ppiieeccee ********** | │ │ │ │ │ -|****** ....//ssrrcc//mmmmaapp__ddiisskk__iioo..ccpppp::11001177 ****** | │ │ │ │ │ -|aux::mmap_disk_job* j = m_job_pool.allocate_job(aux::job_action_t::file_priority); | │ │ │ │ │ -| j->storage = m_torrents[storage]->shared_from_this(); | │ │ │ │ │ -| j->argument = std::move(prios); | │ │ │ │ │ -| j->callback = std::move(handler); | │ │ │ │ │ -| | │ │ │ │ │ -| add_fence_job(j); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| void mmap_disk_io::async_clear_piece(storage_index_t const storage | │ │ │ │ │ -| , piece_index_t const index, std::function handler) | │ │ │ │ │ -| { | │ │ │ │ │ -| aux::mmap_disk_job* j = m_job_pool.allocate_job(aux::job_action_t::clear_piece); | │ │ │ │ │ -| j->storage = m_torrents[storage]->shared_from_this(); | │ │ │ │ │ -| j->piece = index; | │ │ │ │ │ -| j->callback = std::move(handler); | │ │ │ │ │ -| | │ │ │ │ │ -| // regular jobs are not guaranteed to be executed in-order | │ │ │ │ │ -| // since clear piece must guarantee that all write jobs that | │ │ │ │ │ -| // have been issued finish before the clear piece job completes | │ │ │ │ │ -| | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_s_r_c_/_m_m_a_p___d_i_s_k___i_o_._c_p_p_:_1_0_2_2 |Perhaps the job queue could be traversed and all jobs for this piece could be cancelled. If there are no threads currently writing | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_t_o_ _t_h_i_s_ _p_i_e_c_e_,_ _w_e_ _c_o_u_l_d_ _s_k_i_p_ _t_h_e_ _f_e_n_c_e_ _a_l_t_o_g_e_t_h_e_r_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** PPeerrhhaappss tthhee jjoobb qquueeuuee ccoouulldd bbee ttrraavveerrsseedd aanndd aallll jjoobbss ffoorr tthhiiss ppiieeccee ccoouulldd bbee ccaanncceelllleedd.. IIff tthheerree aarree nnoo tthhrreeaaddss ccuurrrreennttllyy wwrriittiinngg ttoo tthhiiss ppiieeccee,, wwee ccoouulldd sskkiipp tthhee ffeennccee| │ │ │ │ │ -|aallttooggeetthheerr ********** | │ │ │ │ │ -|****** ....//ssrrcc//mmmmaapp__ddiisskk__iioo..ccpppp::11002222 ****** | │ │ │ │ │ -|j->storage = m_torrents[storage]->shared_from_this(); | │ │ │ │ │ -| j->argument = std::move(prios); | │ │ │ │ │ -| j->callback = std::move(handler); | │ │ │ │ │ -| | │ │ │ │ │ -| add_fence_job(j); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| void mmap_disk_io::async_clear_piece(storage_index_t const storage | │ │ │ │ │ -| , piece_index_t const index, std::function handler) | │ │ │ │ │ -| { | │ │ │ │ │ -| aux::mmap_disk_job* j = m_job_pool.allocate_job(aux::job_action_t::clear_piece); | │ │ │ │ │ -| j->storage = m_torrents[storage]->shared_from_this(); | │ │ │ │ │ -| j->piece = index; | │ │ │ │ │ -| j->callback = std::move(handler); | │ │ │ │ │ -| | │ │ │ │ │ -| // regular jobs are not guaranteed to be executed in-order | │ │ │ │ │ -| // since clear piece must guarantee that all write jobs that | │ │ │ │ │ -| // have been issued finish before the clear piece job completes | │ │ │ │ │ -| | │ │ │ │ │ -| | │ │ │ │ │ -|add_fence_job(j); | │ │ │ │ │ -|} | │ │ │ │ │ -| | │ │ │ │ │ -| status_t mmap_disk_io::do_hash(aux::mmap_disk_job* j) | │ │ │ │ │ -| { | │ │ │ │ │ -| // we're not using a cache. This is the simple path | │ │ │ │ │ -| // just read straight from the file | │ │ │ │ │ -| TORRENT_ASSERT(m_magic == 0x1337); | │ │ │ │ │ -| | │ │ │ │ │ -| bool const v1 = bool(j->flags & disk_interface::v1_hash); | │ │ │ │ │ -| bool const v2 = !j->d.h.block_hashes.empty(); | │ │ │ │ │ -| | │ │ │ │ │ -| int const piece_size = v1 ? j->storage->files().piece_size(j->piece) : 0; | │ │ │ │ │ -| int const piece_size2 = v2 ? j->storage->files().piece_size2(j->piece) : 0; | │ │ │ │ │ -| int const blocks_in_piece = v1 ? (piece_size + default_block_size - 1) / default_block_size : 0; | │ │ │ │ │ -| int const blocks_in_piece2 = v2 ? j->storage->files().blocks_in_piece2(j->piece) : 0; | │ │ │ │ │ -| aux::open_mode_t const file_mode = file_mode_for_job(j); | │ │ │ │ │ -| | │ │ │ │ │ -| TORRENT_ASSERT(!v2 || int(j->d.h.block_hashes.size()) >= blocks_in_piece2); | │ │ │ │ │ -| TORRENT_ASSERT(v1 || v2); | │ │ │ │ │ -| | │ │ │ │ │ -| hasher h; | │ │ │ │ │ -| int ret = 0; | │ │ │ │ │ -| int offset = 0; | │ │ │ │ │ -| int const blocks_to_read = std::max(blocks_in_piece, blocks_in_piece2); | │ │ │ │ │ -| time_point const start_time = clock_type::now(); | │ │ │ │ │ -| for (int i = 0; i < blocks_to_read; ++i) | │ │ │ │ │ -| { | │ │ │ │ │ -| bool const v2_block = i < blocks_in_piece2; | │ │ │ │ │ -| | │ │ │ │ │ -|_ _ _ _D_L_O_G_(_"_d_o___h_a_s_h_:_ _r_e_a_d_i_n_g_ _(_p_i_e_c_e_:_ _%_d_ _b_l_o_c_k_:_ _%_d_)_\_n_"_,_ _i_n_t_(_j_-_>_p_i_e_c_e_)_,_ _i_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_m_a_g_n_e_t___u_r_i_._c_p_p_:_4_3_9_ _ _ _ _ _|_w_h_a_t_'_s_ _t_h_e_ _r_i_g_h_t_ _n_u_m_b_e_r_ _h_e_r_e_?_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** wwhhaatt''ss tthhee rriigghhtt nnuummbbeerr hheerree?? ********** | │ │ │ │ │ -|****** ....//ssrrcc//mmaaggnneett__uurrii..ccpppp::443399 ****** | │ │ │ │ │ -|} | │ │ │ │ │ -| else if (string_equal_no_case(name, "so"_sv)) // select-only (files) | │ │ │ │ │ -| { | │ │ │ │ │ -| // accept only digits, '-' and ',' | │ │ │ │ │ -| if (std::any_of(value.begin(), value.end(), [](char c) | │ │ │ │ │ -| { return !is_digit(c) && c != '-' && c != ','; })) | │ │ │ │ │ -| continue; | │ │ │ │ │ -| | │ │ │ │ │ -| // make sure all file priorities are set to 0, except the ones | │ │ │ │ │ -| // we specify in the file_priorities | │ │ │ │ │ -| p.flags |= torrent_flags::default_dont_download; | │ │ │ │ │ -| | │ │ │ │ │ -| do | │ │ │ │ │ -| { | │ │ │ │ │ -| string_view token; | │ │ │ │ │ -| std::tie(token, value) = split_string(value, ','); | │ │ │ │ │ -| | │ │ │ │ │ -| if (token.empty()) continue; | │ │ │ │ │ -| | │ │ │ │ │ -| int idx1, idx2; | │ │ │ │ │ -|constexpr int max_index = 10000; // can't risk out of memory | │ │ │ │ │ -| | │ │ │ │ │ -| auto const divider = token.find_first_of('-'); | │ │ │ │ │ -| if (divider != std::string::npos) // it's a range | │ │ │ │ │ -| { | │ │ │ │ │ -| if (divider == 0) // no start index | │ │ │ │ │ -| continue; | │ │ │ │ │ -| if (divider == token.size() - 1) // no end index | │ │ │ │ │ -| continue; | │ │ │ │ │ -| | │ │ │ │ │ -| idx1 = std::atoi(token.substr(0, divider).to_string().c_str()); | │ │ │ │ │ -| if (idx1 < 0 || idx1 > max_index) // invalid index | │ │ │ │ │ -| continue; | │ │ │ │ │ -| idx2 = std::atoi(token.substr(divider + 1).to_string().c_str()); | │ │ │ │ │ -| if (idx2 < 0 || idx2 > max_index) // invalid index | │ │ │ │ │ -| continue; | │ │ │ │ │ -| | │ │ │ │ │ -| if (idx1 > idx2) // wrong range limits | │ │ │ │ │ -| continue; | │ │ │ │ │ -| } | │ │ │ │ │ -| else // it's an index | │ │ │ │ │ -| { | │ │ │ │ │ -| idx1 = std::atoi(token.to_string().c_str()); | │ │ │ │ │ -| if (idx1 < 0 || idx1 > max_index) // invalid index | │ │ │ │ │ -| continue; | │ │ │ │ │ -| idx2 = idx1; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| if (int(p.file_priorities.size()) <= idx2) | │ │ │ │ │ -|_ _ _ _ _ _ _p_._f_i_l_e___p_r_i_o_r_i_t_i_e_s_._r_e_s_i_z_e_(_s_t_a_t_i_c___c_a_s_t_<_s_t_d_:_:_s_i_z_e___t_>_(_i_d_x_2_)_ _+_ _1_,_ _d_o_n_t___d_o_w_n_l_o_a_d_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_a_l_e_r_t_._c_p_p_:_4_0_4_ _ _ _ _ _ _ _ _ _ _|_m_o_v_e_ _t_h_i_s_ _f_i_e_l_d_ _i_n_t_o_ _t_r_a_c_k_e_r___a_l_e_r_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** mmoovvee tthhiiss ffiieelldd iinnttoo ttrraacckkeerr__aalleerrtt ********** | │ │ │ │ │ -|****** ....//ssrrcc//aalleerrtt..ccpppp::440044 ****** | │ │ │ │ │ -| return torrent_alert::message() + ": state changed to: " | │ │ │ │ │ -| + state_str[state]; | │ │ │ │ │ -|#endif | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| tracker_error_alert::tracker_error_alert(aux::stack_allocator& alloc | │ │ │ │ │ -| , torrent_handle const& h, tcp::endpoint const& ep, int times | │ │ │ │ │ -| , protocol_version v, string_view u, operation_t const operation | │ │ │ │ │ -| , error_code const& e | │ │ │ │ │ -| , string_view m) | │ │ │ │ │ -| : tracker_alert(alloc, h, ep, u) | │ │ │ │ │ -| , times_in_row(times) | │ │ │ │ │ -| , error(e) | │ │ │ │ │ -| , op(operation) | │ │ │ │ │ -| , m_msg_idx(alloc.copy_string(m)) | │ │ │ │ │ -|#if TORRENT_ABI_VERSION == 1 | │ │ │ │ │ -| , status_code(e && e.category() == http_category() ? e.value() : -1) | │ │ │ │ │ -| , msg(m) | │ │ │ │ │ -|#endif | │ │ │ │ │ -|, version(v) | │ │ │ │ │ -|{ | │ │ │ │ │ -| TORRENT_ASSERT(!u.empty()); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| char const* tracker_error_alert::failure_reason() const | │ │ │ │ │ -| { | │ │ │ │ │ -| return m_alloc.get().ptr(m_msg_idx); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| std::string tracker_error_alert::message() const | │ │ │ │ │ -| { | │ │ │ │ │ -|#ifdef TORRENT_DISABLE_ALERT_MSG | │ │ │ │ │ -| return {}; | │ │ │ │ │ -|#else | │ │ │ │ │ -| char ret[400]; | │ │ │ │ │ -| std::snprintf(ret, sizeof(ret), "%s %s %s \"%s\" (%d)" | │ │ │ │ │ -| , tracker_alert::message().c_str() | │ │ │ │ │ -| , version == protocol_version::V1 ? "v1" : "v2" | │ │ │ │ │ -| , convert_from_native(error.message()).c_str(), error_message() | │ │ │ │ │ -| , times_in_row); | │ │ │ │ │ -| return ret; | │ │ │ │ │ -|#endif | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| tracker_warning_alert::tracker_warning_alert(aux::stack_allocator& alloc | │ │ │ │ │ -| , torrent_handle const& h, tcp::endpoint const& ep | │ │ │ │ │ -| , string_view u, protocol_version v, string_view m) | │ │ │ │ │ -| : tracker_alert(alloc, h, ep, u) | │ │ │ │ │ -| , m_msg_idx(alloc.copy_string(m)) | │ │ │ │ │ -|_#_i_f_ _T_O_R_R_E_N_T___A_B_I___V_E_R_S_I_O_N_ _=_=_ _1_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_a_l_e_r_t_._c_p_p_:_4_3_8_ _ _ _ _ _ _ _ _ _ _|_m_o_v_e_ _t_h_i_s_ _i_n_t_o_ _t_r_a_c_k_e_r___a_l_e_r_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** mmoovvee tthhiiss iinnttoo ttrraacckkeerr__aalleerrtt ********** | │ │ │ │ │ -|****** ....//ssrrcc//aalleerrtt..ccpppp::443388 ****** | │ │ │ │ │ -|return {}; | │ │ │ │ │ -|#else | │ │ │ │ │ -| char ret[400]; | │ │ │ │ │ -| std::snprintf(ret, sizeof(ret), "%s %s %s \"%s\" (%d)" | │ │ │ │ │ -| , tracker_alert::message().c_str() | │ │ │ │ │ -| , version == protocol_version::V1 ? "v1" : "v2" | │ │ │ │ │ -| , convert_from_native(error.message()).c_str(), error_message() | │ │ │ │ │ -| , times_in_row); | │ │ │ │ │ -| return ret; | │ │ │ │ │ -|#endif | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| tracker_warning_alert::tracker_warning_alert(aux::stack_allocator& alloc | │ │ │ │ │ -| , torrent_handle const& h, tcp::endpoint const& ep | │ │ │ │ │ -| , string_view u, protocol_version v, string_view m) | │ │ │ │ │ -| : tracker_alert(alloc, h, ep, u) | │ │ │ │ │ -| , m_msg_idx(alloc.copy_string(m)) | │ │ │ │ │ -|#if TORRENT_ABI_VERSION == 1 | │ │ │ │ │ -| , msg(m) | │ │ │ │ │ -|#endif | │ │ │ │ │ -|, version(v) | │ │ │ │ │ -|{ | │ │ │ │ │ -| TORRENT_ASSERT(!u.empty()); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| char const* tracker_warning_alert::warning_message() const | │ │ │ │ │ -| { | │ │ │ │ │ -| return m_alloc.get().ptr(m_msg_idx); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| std::string tracker_warning_alert::message() const | │ │ │ │ │ -| { | │ │ │ │ │ -|#ifdef TORRENT_DISABLE_ALERT_MSG | │ │ │ │ │ -| return {}; | │ │ │ │ │ -|#else | │ │ │ │ │ -| return tracker_alert::message() + (version == protocol_version::V1 ? " v1" : " v2") + " warning: " + warning_message(); | │ │ │ │ │ -|#endif | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| scrape_reply_alert::scrape_reply_alert(aux::stack_allocator& alloc | │ │ │ │ │ -| , torrent_handle const& h, tcp::endpoint const& ep | │ │ │ │ │ -| , int incomp, int comp, string_view u, protocol_version const v) | │ │ │ │ │ -| : tracker_alert(alloc, h, ep, u) | │ │ │ │ │ -| , incomplete(incomp) | │ │ │ │ │ -|_ _ _,_ _c_o_m_p_l_e_t_e_(_c_o_m_p_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_a_l_e_r_t_._c_p_p_:_4_6_4_ _ _ _ _ _ _ _ _ _ _|_m_o_v_e_ _t_h_i_s_ _i_n_t_o_ _t_r_a_c_k_e_r___a_l_e_r_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** mmoovvee tthhiiss iinnttoo ttrraacckkeerr__aalleerrtt ********** | │ │ │ │ │ -|****** ....//ssrrcc//aalleerrtt..ccpppp::446644 ****** | │ │ │ │ │ -|char const* tracker_warning_alert::warning_message() const | │ │ │ │ │ -| { | │ │ │ │ │ -| return m_alloc.get().ptr(m_msg_idx); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| std::string tracker_warning_alert::message() const | │ │ │ │ │ -| { | │ │ │ │ │ -|#ifdef TORRENT_DISABLE_ALERT_MSG | │ │ │ │ │ -| return {}; | │ │ │ │ │ -|#else | │ │ │ │ │ -| return tracker_alert::message() + (version == protocol_version::V1 ? " v1" : " v2") + " warning: " + warning_message(); | │ │ │ │ │ -|#endif | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| scrape_reply_alert::scrape_reply_alert(aux::stack_allocator& alloc | │ │ │ │ │ -| , torrent_handle const& h, tcp::endpoint const& ep | │ │ │ │ │ -| , int incomp, int comp, string_view u, protocol_version const v) | │ │ │ │ │ -| : tracker_alert(alloc, h, ep, u) | │ │ │ │ │ -| , incomplete(incomp) | │ │ │ │ │ -| , complete(comp) | │ │ │ │ │ -|, version(v) | │ │ │ │ │ -|{ | │ │ │ │ │ -| TORRENT_ASSERT(!u.empty()); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| std::string scrape_reply_alert::message() const | │ │ │ │ │ -| { | │ │ │ │ │ -|#ifdef TORRENT_DISABLE_ALERT_MSG | │ │ │ │ │ -| return {}; | │ │ │ │ │ -|#else | │ │ │ │ │ -| char ret[400]; | │ │ │ │ │ -| std::snprintf(ret, sizeof(ret), "%s %s scrape reply: %d %d" | │ │ │ │ │ -| , tracker_alert::message().c_str() | │ │ │ │ │ -| , version == protocol_version::V1 ? "v1" : "v2" | │ │ │ │ │ -| , incomplete, complete); | │ │ │ │ │ -| return ret; | │ │ │ │ │ -|#endif | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| scrape_failed_alert::scrape_failed_alert(aux::stack_allocator& alloc | │ │ │ │ │ -| , torrent_handle const& h, tcp::endpoint const& ep | │ │ │ │ │ -| , string_view u, protocol_version const v, error_code const& e) | │ │ │ │ │ -| : tracker_alert(alloc, h, ep, u) | │ │ │ │ │ -| , error(e) | │ │ │ │ │ -| , m_msg_idx() | │ │ │ │ │ -|#if TORRENT_ABI_VERSION == 1 | │ │ │ │ │ -| , msg(convert_from_native(e.message())) | │ │ │ │ │ -|_#_e_n_d_i_f_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_a_l_e_r_t_._c_p_p_:_4_9_3_ _ _ _ _ _ _ _ _ _ _|_m_o_v_e_ _t_h_i_s_ _i_n_t_o_ _t_r_a_c_k_e_r___a_l_e_r_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** mmoovvee tthhiiss iinnttoo ttrraacckkeerr__aalleerrtt ********** | │ │ │ │ │ -|****** ....//ssrrcc//aalleerrtt..ccpppp::449933 ****** | │ │ │ │ │ -|return {}; | │ │ │ │ │ -|#else | │ │ │ │ │ -| char ret[400]; | │ │ │ │ │ -| std::snprintf(ret, sizeof(ret), "%s %s scrape reply: %d %d" | │ │ │ │ │ -| , tracker_alert::message().c_str() | │ │ │ │ │ -| , version == protocol_version::V1 ? "v1" : "v2" | │ │ │ │ │ -| , incomplete, complete); | │ │ │ │ │ -| return ret; | │ │ │ │ │ -|#endif | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| scrape_failed_alert::scrape_failed_alert(aux::stack_allocator& alloc | │ │ │ │ │ -| , torrent_handle const& h, tcp::endpoint const& ep | │ │ │ │ │ -| , string_view u, protocol_version const v, error_code const& e) | │ │ │ │ │ -| : tracker_alert(alloc, h, ep, u) | │ │ │ │ │ -| , error(e) | │ │ │ │ │ -| , m_msg_idx() | │ │ │ │ │ -|#if TORRENT_ABI_VERSION == 1 | │ │ │ │ │ -| , msg(convert_from_native(e.message())) | │ │ │ │ │ -|#endif | │ │ │ │ │ -|, version(v) | │ │ │ │ │ -|{ | │ │ │ │ │ -| TORRENT_ASSERT(!u.empty()); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| scrape_failed_alert::scrape_failed_alert(aux::stack_allocator& alloc | │ │ │ │ │ -| , torrent_handle const& h, tcp::endpoint const& ep | │ │ │ │ │ -| , string_view u, string_view m) | │ │ │ │ │ -| : tracker_alert(alloc, h, ep, u) | │ │ │ │ │ -| , error(errors::tracker_failure) | │ │ │ │ │ -| , m_msg_idx(alloc.copy_string(m)) | │ │ │ │ │ -|#if TORRENT_ABI_VERSION == 1 | │ │ │ │ │ -| , msg(m) | │ │ │ │ │ -|#endif | │ │ │ │ │ -| { | │ │ │ │ │ -| TORRENT_ASSERT(!u.empty()); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| char const* scrape_failed_alert::error_message() const | │ │ │ │ │ -| { | │ │ │ │ │ -| if (m_msg_idx == aux::allocation_slot()) return ""; | │ │ │ │ │ -| else return m_alloc.get().ptr(m_msg_idx); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| std::string scrape_failed_alert::message() const | │ │ │ │ │ -| { | │ │ │ │ │ -|#ifdef TORRENT_DISABLE_ALERT_MSG | │ │ │ │ │ -| return {}; | │ │ │ │ │ -|#else | │ │ │ │ │ -| return tracker_alert::message() + " scrape failed: " + error_message(); | │ │ │ │ │ -|_#_e_n_d_i_f_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_a_l_e_r_t_._c_p_p_:_5_3_2_ _ _ _ _ _ _ _ _ _ _|_m_o_v_e_ _t_h_i_s_ _f_i_e_l_d_ _i_n_t_o_ _t_r_a_c_k_e_r___a_l_e_r_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** mmoovvee tthhiiss ffiieelldd iinnttoo ttrraacckkeerr__aalleerrtt ********** | │ │ │ │ │ -|****** ....//ssrrcc//aalleerrtt..ccpppp::553322 ****** | │ │ │ │ │ -|char const* scrape_failed_alert::error_message() const | │ │ │ │ │ -| { | │ │ │ │ │ -| if (m_msg_idx == aux::allocation_slot()) return ""; | │ │ │ │ │ -| else return m_alloc.get().ptr(m_msg_idx); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| std::string scrape_failed_alert::message() const | │ │ │ │ │ -| { | │ │ │ │ │ -|#ifdef TORRENT_DISABLE_ALERT_MSG | │ │ │ │ │ -| return {}; | │ │ │ │ │ -|#else | │ │ │ │ │ -| return tracker_alert::message() + " scrape failed: " + error_message(); | │ │ │ │ │ -|#endif | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| tracker_reply_alert::tracker_reply_alert(aux::stack_allocator& alloc | │ │ │ │ │ -| , torrent_handle const& h, tcp::endpoint const& ep | │ │ │ │ │ -| , int np, protocol_version v, string_view u) | │ │ │ │ │ -| : tracker_alert(alloc, h, ep, u) | │ │ │ │ │ -| , num_peers(np) | │ │ │ │ │ -|, version(v) | │ │ │ │ │ -|{ | │ │ │ │ │ -| TORRENT_ASSERT(!u.empty()); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| std::string tracker_reply_alert::message() const | │ │ │ │ │ -| { | │ │ │ │ │ -|#ifdef TORRENT_DISABLE_ALERT_MSG | │ │ │ │ │ -| return {}; | │ │ │ │ │ -|#else | │ │ │ │ │ -| char ret[400]; | │ │ │ │ │ -| std::snprintf(ret, sizeof(ret), "%s %s received peers: %d" | │ │ │ │ │ -| , tracker_alert::message().c_str() | │ │ │ │ │ -| , version == protocol_version::V1 ? "v1" : "v2" | │ │ │ │ │ -| , num_peers); | │ │ │ │ │ -| return ret; | │ │ │ │ │ -|#endif | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| dht_reply_alert::dht_reply_alert(aux::stack_allocator& alloc | │ │ │ │ │ -| , torrent_handle const& h | │ │ │ │ │ -| , int np) | │ │ │ │ │ -| : tracker_alert(alloc, h, {}, "") | │ │ │ │ │ -| , num_peers(np) | │ │ │ │ │ -| {} | │ │ │ │ │ -| | │ │ │ │ │ -| std::string dht_reply_alert::message() const | │ │ │ │ │ -| { | │ │ │ │ │ -|#ifdef TORRENT_DISABLE_ALERT_MSG | │ │ │ │ │ -| return {}; | │ │ │ │ │ -|_#_e_l_s_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_a_l_e_r_t_._c_p_p_:_5_7_6_ _ _ _ _ _ _ _ _ _ _|_m_o_v_e_ _t_h_i_s_ _t_o_ _t_r_a_c_k_e_r___a_l_e_r_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** mmoovvee tthhiiss ttoo ttrraacckkeerr__aalleerrtt ********** | │ │ │ │ │ -|****** ....//ssrrcc//aalleerrtt..ccpppp::557766 ****** | │ │ │ │ │ -|, num_peers(np) | │ │ │ │ │ -| {} | │ │ │ │ │ -| | │ │ │ │ │ -| std::string dht_reply_alert::message() const | │ │ │ │ │ -| { | │ │ │ │ │ -|#ifdef TORRENT_DISABLE_ALERT_MSG | │ │ │ │ │ -| return {}; | │ │ │ │ │ -|#else | │ │ │ │ │ -| char ret[400]; | │ │ │ │ │ -| std::snprintf(ret, sizeof(ret), "%s received DHT peers: %d" | │ │ │ │ │ -| , tracker_alert::message().c_str(), num_peers); | │ │ │ │ │ -| return ret; | │ │ │ │ │ -|#endif | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| tracker_announce_alert::tracker_announce_alert(aux::stack_allocator& alloc | │ │ │ │ │ -| , torrent_handle const& h, tcp::endpoint const& ep, string_view u | │ │ │ │ │ -| , protocol_version const v, event_t const e) | │ │ │ │ │ -| : tracker_alert(alloc, h, ep, u) | │ │ │ │ │ -| , event(e) | │ │ │ │ │ -|, version(v) | │ │ │ │ │ -|{ | │ │ │ │ │ -| TORRENT_ASSERT(!u.empty()); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| std::string tracker_announce_alert::message() const | │ │ │ │ │ -| { | │ │ │ │ │ -|#ifdef TORRENT_DISABLE_ALERT_MSG | │ │ │ │ │ -| return {}; | │ │ │ │ │ -|#else | │ │ │ │ │ -| static const char* const event_str[] = {"none", "completed", "started", "stopped", "paused"}; | │ │ │ │ │ -| return tracker_alert::message() | │ │ │ │ │ -| + (version == protocol_version::V1 ? " v1" : " v2") | │ │ │ │ │ -| + " sending announce (" + event_str[static_cast(event)] + ")"; | │ │ │ │ │ -|#endif | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| hash_failed_alert::hash_failed_alert( | │ │ │ │ │ -| aux::stack_allocator& alloc | │ │ │ │ │ -| , torrent_handle const& h | │ │ │ │ │ -| , piece_index_t index) | │ │ │ │ │ -| : torrent_alert(alloc, h) | │ │ │ │ │ -| , piece_index(index) | │ │ │ │ │ -| { | │ │ │ │ │ -| TORRENT_ASSERT(index >= piece_index_t(0)); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| std::string hash_failed_alert::message() const | │ │ │ │ │ -| { | │ │ │ │ │ -|#ifdef TORRENT_DISABLE_ALERT_MSG | │ │ │ │ │ -|_ _ _r_e_t_u_r_n_ _{_}_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_s_e_t_t_i_n_g_s___p_a_c_k_._c_p_p_:_3_0_5_ _ _|_d_e_p_r_e_c_a_t_e_ _t_h_i_s_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** ddeepprreeccaattee tthhiiss ********** | │ │ │ │ │ -|****** ....//ssrrcc//sseettttiinnggss__ppaacckk..ccpppp::330055 ****** | │ │ │ │ │ -|SET(outgoing_port, 0, nullptr), | │ │ │ │ │ -| SET(num_outgoing_ports, 0, nullptr), | │ │ │ │ │ -| SET(peer_dscp, 0x04, &session_impl::update_peer_dscp), | │ │ │ │ │ -| SET(active_downloads, 3, &session_impl::trigger_auto_manage), | │ │ │ │ │ -| SET(active_seeds, 5, &session_impl::trigger_auto_manage), | │ │ │ │ │ -| SET(active_checking, 1, &session_impl::trigger_auto_manage), | │ │ │ │ │ -| SET(active_dht_limit, 88, nullptr), | │ │ │ │ │ -| SET(active_tracker_limit, 1600, nullptr), | │ │ │ │ │ -| SET(active_lsd_limit, 60, nullptr), | │ │ │ │ │ -| SET(active_limit, 500, &session_impl::trigger_auto_manage), | │ │ │ │ │ -| DEPRECATED_SET(active_loaded_limit, 0, &session_impl::trigger_auto_manage), | │ │ │ │ │ -| SET(auto_manage_interval, 30, nullptr), | │ │ │ │ │ -| SET(seed_time_limit, 24 * 60 * 60, nullptr), | │ │ │ │ │ -| SET(auto_scrape_interval, 1800, nullptr), | │ │ │ │ │ -| SET(auto_scrape_min_interval, 300, nullptr), | │ │ │ │ │ -| SET(max_peerlist_size, 3000, nullptr), | │ │ │ │ │ -| SET(max_paused_peerlist_size, 1000, nullptr), | │ │ │ │ │ -| SET(min_announce_interval, 5 * 60, nullptr), | │ │ │ │ │ -| SET(auto_manage_startup, 60, nullptr), | │ │ │ │ │ -| SET(seeding_piece_quota, 20, nullptr), | │ │ │ │ │ -|SET(max_rejects, 50, nullptr), | │ │ │ │ │ -|SET(recv_socket_buffer_size, 0, &session_impl::update_socket_buffer_size), | │ │ │ │ │ -| SET(send_socket_buffer_size, 0, &session_impl::update_socket_buffer_size), | │ │ │ │ │ -| SET(max_peer_recv_buffer_size, 2 * 1024 * 1024, nullptr), | │ │ │ │ │ -| DEPRECATED_SET(file_checks_delay_per_block, 0, nullptr), | │ │ │ │ │ -| DEPRECATED2_SET(read_cache_line_size, 32, nullptr), | │ │ │ │ │ -| DEPRECATED2_SET(write_cache_line_size, 16, nullptr), | │ │ │ │ │ -| SET(optimistic_disk_retry, 10 * 60, nullptr), | │ │ │ │ │ -| SET(max_suggest_pieces, 16, nullptr), | │ │ │ │ │ -| SET(local_service_announce_interval, 5 * 60, nullptr), | │ │ │ │ │ -| SET(dht_announce_interval, 15 * 60, &session_impl::update_dht_announce_interval), | │ │ │ │ │ -| SET(udp_tracker_token_expiry, 60, nullptr), | │ │ │ │ │ -| DEPRECATED_SET(default_cache_min_age, 1, nullptr), | │ │ │ │ │ -| SET(num_optimistic_unchoke_slots, 0, nullptr), | │ │ │ │ │ -| DEPRECATED_SET(default_est_reciprocation_rate, 16000, nullptr), | │ │ │ │ │ -| DEPRECATED_SET(increase_est_reciprocation_rate, 20, nullptr), | │ │ │ │ │ -| DEPRECATED_SET(decrease_est_reciprocation_rate, 3, nullptr), | │ │ │ │ │ -| SET(max_pex_peers, 50, nullptr), | │ │ │ │ │ -| SET(tick_interval, 500, nullptr), | │ │ │ │ │ -| SET(share_mode_target, 3, nullptr), | │ │ │ │ │ -| SET(upload_rate_limit, 0, &session_impl::update_upload_rate), | │ │ │ │ │ -| SET(download_rate_limit, 0, &session_impl::update_download_rate), | │ │ │ │ │ -| DEPRECATED_SET(local_upload_rate_limit, 0, &session_impl::update_local_upload_rate), | │ │ │ │ │ -| DEPRECATED_SET(local_download_rate_limit, 0, &session_impl::update_local_download_rate), | │ │ │ │ │ -| SET(dht_upload_rate_limit, 8000, &session_impl::update_dht_upload_rate_limit), | │ │ │ │ │ -| SET(unchoke_slots_limit, 8, &session_impl::update_unchoke_limit), | │ │ │ │ │ -| DEPRECATED_SET(half_open_limit, 0, nullptr), | │ │ │ │ │ -| SET(connections_limit, 200, &session_impl::update_connections_limit), | │ │ │ │ │ -| SET(connections_slack, 10, nullptr), | │ │ │ │ │ -| SET(utp_target_delay, 100, nullptr), | │ │ │ │ │ -|_ _ _S_E_T_(_u_t_p___g_a_i_n___f_a_c_t_o_r_,_ _3_0_0_0_,_ _n_u_l_l_p_t_r_)_,_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_s_e_t_t_i_n_g_s___p_a_c_k_._c_p_p_:_5_8_9_ _ _|_i_t_ _w_o_u_l_d_ _b_e_ _n_i_c_e_ _t_o_ _r_e_s_e_r_v_e_(_)_ _t_h_e_s_e_ _v_e_c_t_o_r_s_ _u_p_ _f_r_o_n_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** iitt wwoouulldd bbee nniiccee ttoo rreesseerrvvee(()) tthheessee vveeccttoorrss uupp ffrroonntt ********** | │ │ │ │ │ -|****** ....//ssrrcc//sseettttiinnggss__ppaacckk..ccpppp::558899 ****** | │ │ │ │ │ -|s.set_str(settings_pack::string_type_base | i, str_settings[i].default_value); | │ │ │ │ │ -| TORRENT_ASSERT(s.get_str(settings_pack::string_type_base + i) == str_settings[i].default_value); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| for (int i = 0; i < settings_pack::num_int_settings; ++i) | │ │ │ │ │ -| { | │ │ │ │ │ -| s.set_int(settings_pack::int_type_base | i, int_settings[i].default_value); | │ │ │ │ │ -| TORRENT_ASSERT(s.get_int(settings_pack::int_type_base + i) == int_settings[i].default_value); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| for (int i = 0; i < settings_pack::num_bool_settings; ++i) | │ │ │ │ │ -| { | │ │ │ │ │ -| s.set_bool(settings_pack::bool_type_base | i, bool_settings[i].default_value); | │ │ │ │ │ -| TORRENT_ASSERT(s.get_bool(settings_pack::bool_type_base + i) == bool_settings[i].default_value); | │ │ │ │ │ -| } | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| settings_pack default_settings() | │ │ │ │ │ -| { | │ │ │ │ │ -| settings_pack ret; | │ │ │ │ │ -|for (int i = 0; i < settings_pack::num_string_settings; ++i) | │ │ │ │ │ -|{ | │ │ │ │ │ -| if (str_settings[i].default_value == nullptr) continue; | │ │ │ │ │ -| ret.set_str(settings_pack::string_type_base + i, str_settings[i].default_value); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| for (int i = 0; i < settings_pack::num_int_settings; ++i) | │ │ │ │ │ -| { | │ │ │ │ │ -| ret.set_int(settings_pack::int_type_base + i, int_settings[i].default_value); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| for (int i = 0; i < settings_pack::num_bool_settings; ++i) | │ │ │ │ │ -| { | │ │ │ │ │ -| ret.set_bool(settings_pack::bool_type_base + i, bool_settings[i].default_value); | │ │ │ │ │ -| } | │ │ │ │ │ -| return ret; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| void apply_pack(settings_pack const* pack, aux::session_settings& sett | │ │ │ │ │ -| , aux::session_impl* ses) | │ │ │ │ │ -| { | │ │ │ │ │ -| using fun_t = void (aux::session_impl::*)(); | │ │ │ │ │ -| std::vector callbacks; | │ │ │ │ │ -| | │ │ │ │ │ -| sett.bulk_set([&](aux::session_settings_single_thread& s) | │ │ │ │ │ -| { | │ │ │ │ │ -| apply_pack_impl(pack, s, ses ? &callbacks : nullptr); | │ │ │ │ │ -| }); | │ │ │ │ │ -| | │ │ │ │ │ -| // call the callbacks once all the settings have been applied, and | │ │ │ │ │ -|_ _ _/_/_ _o_n_l_y_ _o_n_c_e_ _p_e_r_ _c_a_l_l_b_a_c_k_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_s_r_c_/_p_a_r_t___f_i_l_e_._c_p_p_:_3_0_0 |what do we do if someone is currently reading from the disk from this piece? does it matter? Since we won't actively erase the data | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_f_r_o_m_ _d_i_s_k_,_ _b_u_t_ _i_t_ _m_a_y_ _b_e_ _o_v_e_r_w_r_i_t_t_e_n_ _s_o_o_n_,_ _i_t_'_s_ _p_r_o_b_a_b_l_y_ _n_o_t_ _t_h_a_t_ _b_i_g_ _o_f_ _a_ _d_e_a_l_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** wwhhaatt ddoo wwee ddoo iiff ssoommeeoonnee iiss ccuurrrreennttllyy rreeaaddiinngg ffrroomm tthhee ddiisskk ffrroomm tthhiiss ppiieeccee?? ddooeess iitt mmaatttteerr?? SSiinnccee wwee wwoonn''tt aaccttiivveellyy eerraassee tthhee ddaattaa ffrroomm ddiisskk,, bbuutt iitt mmaayy bbee oovveerrwwrriitttteenn | │ │ │ │ │ -|ssoooonn,, iitt''ss pprroobbaabbllyy nnoott tthhaatt bbiigg ooff aa ddeeaall ********** | │ │ │ │ │ -|****** ....//ssrrcc//ppaarrtt__ffiillee..ccpppp::330000 ****** | │ │ │ │ │ -|create_directories(m_path, ec); | │ │ │ │ │ -| if (ec) return {}; | │ │ │ │ │ -| return aux::file_handle(fn, 0, mode); | │ │ │ │ │ -| } | │ │ │ │ │ -| return {}; | │ │ │ │ │ -| } | │ │ │ │ │ -| } | │ │ │ │ │ -| catch (storage_error const& e) | │ │ │ │ │ -| { | │ │ │ │ │ -| ec = e.ec; | │ │ │ │ │ -| return {}; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| void part_file::free_piece(piece_index_t const piece) | │ │ │ │ │ -| { | │ │ │ │ │ -| std::lock_guard l(m_mutex); | │ │ │ │ │ -| | │ │ │ │ │ -| auto const i = m_piece_map.find(piece); | │ │ │ │ │ -| if (i == m_piece_map.end()) return; | │ │ │ │ │ -| | │ │ │ │ │ -| | │ │ │ │ │ -|m_free_slots.push_back(i->second); | │ │ │ │ │ -| m_piece_map.erase(i); | │ │ │ │ │ -| m_dirty_metadata = true; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| void part_file::move_partfile(std::string const& path, error_code& ec) | │ │ │ │ │ -| { | │ │ │ │ │ -| std::lock_guard l(m_mutex); | │ │ │ │ │ -| | │ │ │ │ │ -| flush_metadata_impl(ec); | │ │ │ │ │ -| if (ec) return; | │ │ │ │ │ -| | │ │ │ │ │ -| if (!m_piece_map.empty()) | │ │ │ │ │ -| { | │ │ │ │ │ -| std::string old_path = combine_path(m_path, m_name); | │ │ │ │ │ -| std::string new_path = combine_path(path, m_name); | │ │ │ │ │ -| | │ │ │ │ │ -| rename(old_path, new_path, ec); | │ │ │ │ │ -| if (ec == boost::system::errc::no_such_file_or_directory) | │ │ │ │ │ -| ec.clear(); | │ │ │ │ │ -| | │ │ │ │ │ -| if (ec) | │ │ │ │ │ -| { | │ │ │ │ │ -| storage_error se; | │ │ │ │ │ -| aux::copy_file(old_path, new_path, se); | │ │ │ │ │ -| ec = se.ec; | │ │ │ │ │ -| if (ec) return; | │ │ │ │ │ -| remove(old_path, ec); | │ │ │ │ │ -| } | │ │ │ │ │ -|_ _ _}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_p_a_r_t___f_i_l_e_._c_p_p_:_4_1_2_ _ _ _ _ _ _|_i_n_s_t_e_a_d_ _o_f_ _r_e_b_u_i_l_d_i_n_g_ _t_h_e_ _w_h_o_l_e_ _f_i_l_e_ _h_e_a_d_e_r_ _a_n_d_ _f_l_u_s_h_i_n_g_ _i_t_,_ _u_p_d_a_t_e_ _t_h_e_ _s_l_o_t_ _e_n_t_r_i_e_s_ _a_s_ _w_e_ _g_o_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** iinnsstteeaadd ooff rreebbuuiillddiinngg tthhee wwhhoollee ffiillee hheeaaddeerr aanndd fflluusshhiinngg iitt,, uuppddaattee tthhee sslloott eennttrriieess aass wwee ggoo ********** | │ │ │ │ │ -|****** ....//ssrrcc//ppaarrtt__ffiillee..ccpppp::441122 ****** | │ │ │ │ │ -|TORRENT_ASSERT(j->second == slot); | │ │ │ │ │ -| m_free_slots.push_back(j->second); | │ │ │ │ │ -| m_piece_map.erase(j); | │ │ │ │ │ -| m_dirty_metadata = true; | │ │ │ │ │ -| } | │ │ │ │ │ -| } | │ │ │ │ │ -| } | │ │ │ │ │ -| file_offset += block_to_copy; | │ │ │ │ │ -| piece_offset = 0; | │ │ │ │ │ -| size -= block_to_copy; | │ │ │ │ │ -| } | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| void part_file::flush_metadata(error_code& ec) | │ │ │ │ │ -| { | │ │ │ │ │ -| std::lock_guard l(m_mutex); | │ │ │ │ │ -| | │ │ │ │ │ -| flush_metadata_impl(ec); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -|void part_file::flush_metadata_impl(error_code& ec) | │ │ │ │ │ -|{ | │ │ │ │ │ -| // do we need to flush the metadata? | │ │ │ │ │ -| if (m_dirty_metadata == false) return; | │ │ │ │ │ -| | │ │ │ │ │ -| if (m_piece_map.empty()) | │ │ │ │ │ -| { | │ │ │ │ │ -| // if we don't have any pieces left in the | │ │ │ │ │ -| // part file, remove it | │ │ │ │ │ -| std::string const p = combine_path(m_path, m_name); | │ │ │ │ │ -| remove(p, ec); | │ │ │ │ │ -| | │ │ │ │ │ -| if (ec == boost::system::errc::no_such_file_or_directory) | │ │ │ │ │ -| ec.clear(); | │ │ │ │ │ -| return; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| auto f = open_file(aux::open_mode::write | aux::open_mode::hidden, ec); | │ │ │ │ │ -| if (ec) return; | │ │ │ │ │ -| | │ │ │ │ │ -| std::vector header(static_cast(m_header_size)); | │ │ │ │ │ -| | │ │ │ │ │ -| using namespace libtorrent::aux; | │ │ │ │ │ -| | │ │ │ │ │ -| char* ptr = header.data(); | │ │ │ │ │ -| write_uint32(m_max_pieces, ptr); | │ │ │ │ │ -| write_uint32(m_piece_size, ptr); | │ │ │ │ │ -| | │ │ │ │ │ -| for (piece_index_t piece(0); piece < piece_index_t(m_max_pieces); ++piece) | │ │ │ │ │ -| { | │ │ │ │ │ -|_ _ _ _a_u_t_o_ _c_o_n_s_t_ _i_ _=_ _m___p_i_e_c_e___m_a_p_._f_i_n_d_(_p_i_e_c_e_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |relevance 0|_._._/_s_r_c_/_a_d_d___t_o_r_r_e_n_t___p_a_r_a_m_s_._c_p_p_:|pre C++17, GCC and msvc does not make std::string nothrow move assignable, which means no type containing a string will be nothrow | │ │ │ │ │ |_ _ _ _ _ _ _ _ _ _ _ _|_7_8_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_m_o_v_e_ _a_s_s_i_g_n_a_b_l_e_ _b_y_ _d_e_f_a_u_l_t_ _e_i_t_h_e_r_ _s_t_a_t_i_c___a_s_s_e_r_t_(_s_t_d_:_:_i_s___n_o_t_h_r_o_w___m_o_v_e___a_s_s_i_g_n_a_b_l_e_:_:_v_a_l_u_e_ _,_ _"_s_h_o_u_l_d_ _b_e_ _n_o_t_h_r_o_w_ _m_o_v_e_ _a_s_s_i_g_n_a_b_l_e_"_)_;_ _ _ _ _ _ | │ │ │ │ │ |********** pprree CC++++1177,, GGCCCC aanndd mmssvvcc ddooeess nnoott mmaakkee ssttdd::::ssttrriinngg nnootthhrrooww mmoovvee aassssiiggnnaabbllee,, wwhhiicchh mmeeaannss nnoo ttyyppee ccoonnttaaiinniinngg aa ssttrriinngg wwiillll bbee nnootthhrrooww mmoovvee aassssiiggnnaabbllee bbyy ddeeffaauulltt eeiitthheerr | │ │ │ │ │ |ssttaattiicc__aasssseerrtt((ssttdd::::iiss__nnootthhrrooww__mmoovvee__aassssiiggnnaabbllee::::vvaalluuee ,, ""sshhoouulldd bbee nnootthhrrooww mmoovvee aassssiiggnnaabbllee""));; ********** | │ │ │ │ │ |****** ....//ssrrcc//aadddd__ttoorrrreenntt__ppaarraammss..ccpppp::7788 ****** | │ │ │ │ │ |DECL_FLAG(sequential_download); | │ │ │ │ │ | DECL_FLAG(pinned); | │ │ │ │ │ @@ -8445,258 +7212,49 @@ │ │ │ │ │ | { | │ │ │ │ │ | return !atp.have_pieces.empty() | │ │ │ │ │ | || (atp.flags & torrent_flags::seed_mode); | │ │ │ │ │ | } | │ │ │ │ │ |} | │ │ │ │ │ | | │ │ │ │ │ |_}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_l_o_a_d___t_o_r_r_e_n_t_._c_p_p_:_1_2_1_ _ _ _|_m_o_v_e_ _t_h_e_ _l_o_a_d_i_n_g_ _l_o_g_i_c_ _f_r_o_m_ _t_o_r_r_e_n_t___i_n_f_o_ _c_o_n_s_t_r_u_c_t_o_r_ _i_n_t_o_ _h_e_r_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** mmoovvee tthhee llooaaddiinngg llooggiicc ffrroomm ttoorrrreenntt__iinnffoo ccoonnssttrruuccttoorr iinnttoo hheerree ********** | │ │ │ │ │ -|****** ....//ssrrcc//llooaadd__ttoorrrreenntt..ccpppp::112211 ****** | │ │ │ │ │ -|mask.resize(std::size_t(full_size), false); | │ │ │ │ │ -| for (int i = merkle_first_leaf(piece_layer_size) | │ │ │ │ │ -| , end = i + num_pieces; i < end; ++i) | │ │ │ │ │ -| { | │ │ │ │ │ -| mask[std::size_t(i)] = true; | │ │ │ │ │ -| } | │ │ │ │ │ -| } | │ │ │ │ │ -| ti->free_piece_layers(); | │ │ │ │ │ -| } | │ │ │ │ │ -| atp.info_hashes = atp.ti->info_hashes(); | │ │ │ │ │ -| } | │ │ │ │ │ -|} | │ │ │ │ │ -| | │ │ │ │ │ -| add_torrent_params load_torrent_file(std::string const& filename) | │ │ │ │ │ -| { return load_torrent_file(filename, load_torrent_limits{}); } | │ │ │ │ │ -| add_torrent_params load_torrent_buffer(span buffer) | │ │ │ │ │ -| { return load_torrent_buffer(buffer, load_torrent_limits{}); } | │ │ │ │ │ -| add_torrent_params load_torrent_parsed(bdecode_node const& torrent_file) | │ │ │ │ │ -| { return load_torrent_parsed(torrent_file, load_torrent_limits{}); } | │ │ │ │ │ -| | │ │ │ │ │ -|add_torrent_params load_torrent_file(std::string const& filename, load_torrent_limits const& cfg) | │ │ │ │ │ -|{ | │ │ │ │ │ -| add_torrent_params ret; | │ │ │ │ │ -| ret.ti = std::make_shared(filename, cfg); | │ │ │ │ │ -| update_atp(ret); | │ │ │ │ │ -| return ret; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| add_torrent_params load_torrent_buffer(span buffer, load_torrent_limits const& cfg) | │ │ │ │ │ -| { | │ │ │ │ │ -| add_torrent_params ret; | │ │ │ │ │ -| ret.ti = std::make_shared(buffer, cfg, from_span); | │ │ │ │ │ -| update_atp(ret); | │ │ │ │ │ -| return ret; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| add_torrent_params load_torrent_parsed(bdecode_node const& torrent_file, load_torrent_limits const& cfg) | │ │ │ │ │ -| { | │ │ │ │ │ -| add_torrent_params ret; | │ │ │ │ │ -| ret.ti = std::make_shared(torrent_file, cfg); | │ │ │ │ │ -| update_atp(ret); | │ │ │ │ │ -| return ret; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -|_}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_s_r_c_/ |introduce a web-seed default class which has a low download priority | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_w_e_b___c_o_n_n_e_c_t_i_o_n___b_a_s_e_._c_p_p_:_7_2_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** iinnttrroodduuccee aa wweebb--sseeeedd ddeeffaauulltt ccllaassss wwhhiicchh hhaass aa llooww ddoowwnnllooaadd pprriioorriittyy ********** | │ │ │ │ │ -|****** ....//ssrrcc//wweebb__ccoonnnneeccttiioonn__bbaassee..ccpppp::7722 ****** | │ │ │ │ │ -|: peer_connection(pack) | │ │ │ │ │ -| , m_first_request(true) | │ │ │ │ │ -| , m_ssl(false) | │ │ │ │ │ -| , m_external_auth(web.auth) | │ │ │ │ │ -| , m_extra_headers(web.extra_headers) | │ │ │ │ │ -| , m_parser(http_parser::dont_parse_chunks) | │ │ │ │ │ -| , m_body_start(0) | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_s_e_s_s_i_o_n_._c_p_p_:_5_4_0_ _ _ _ _ _ _ _ _|_I_n_ _C_+_+_1_7_._ _u_s_e_ _i_f_ _c_o_n_s_t_e_x_p_r_ _i_n_s_t_e_a_d_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** IInn CC++++1177.. uussee iiff ccoonnsstteexxpprr iinnsstteeaadd ********** | │ │ │ │ │ +|****** ....//ssrrcc//sseessssiioonn..ccpppp::554400 ****** | │ │ │ │ │ +|{} | │ │ │ │ │ +| session_proxy::session_proxy(session_proxy const&) = default; | │ │ │ │ │ +| session_proxy& session_proxy::operator=(session_proxy const&) & = default; | │ │ │ │ │ +| session_proxy::session_proxy(session_proxy&&) noexcept = default; | │ │ │ │ │ +| session_proxy& session_proxy::operator=(session_proxy&&) & noexcept = default; | │ │ │ │ │ +| session_proxy::~session_proxy() | │ │ │ │ │ | { | │ │ │ │ │ -| TORRENT_ASSERT(&web.peer_info == pack.peerinfo); | │ │ │ │ │ -| // when going through a proxy, we don't necessarily have an endpoint here, | │ │ │ │ │ -| // since the proxy might be resolving the hostname, not us | │ │ │ │ │ -| TORRENT_ASSERT(web.endpoints.empty() || web.endpoints.front() == pack.endp); | │ │ │ │ │ -| | │ │ │ │ │ -| INVARIANT_CHECK; | │ │ │ │ │ -| | │ │ │ │ │ -| TORRENT_ASSERT(is_outgoing()); | │ │ │ │ │ -| | │ │ │ │ │ -| TORRENT_ASSERT(!m_torrent.lock()->is_upload_only()); | │ │ │ │ │ -| | │ │ │ │ │ -| // we only want left-over bandwidth | │ │ │ │ │ -| | │ │ │ │ │ -|std::string protocol; | │ │ │ │ │ -| error_code ec; | │ │ │ │ │ -| std::tie(protocol, m_basic_auth, m_host, m_port, m_path) | │ │ │ │ │ -| = parse_url_components(web.url, ec); | │ │ │ │ │ -| TORRENT_ASSERT(!ec); | │ │ │ │ │ -| | │ │ │ │ │ -| if (m_port == -1 && protocol == "http") | │ │ │ │ │ -| m_port = 80; | │ │ │ │ │ -| | │ │ │ │ │ -|#if TORRENT_USE_SSL | │ │ │ │ │ -| if (protocol == "https") | │ │ │ │ │ +| if (m_thread && m_thread.use_count() == 1) | │ │ │ │ │ | { | │ │ │ │ │ -| m_ssl = true; | │ │ │ │ │ -| if (m_port == -1) m_port = 443; | │ │ │ │ │ -| } | │ │ │ │ │ +|#if defined TORRENT_ASIO_DEBUGGING | │ │ │ │ │ +| wait_for_asio_handlers(); | │ │ │ │ │ |#endif | │ │ │ │ │ -| | │ │ │ │ │ -| if (!m_basic_auth.empty()) | │ │ │ │ │ -| m_basic_auth = base64encode(m_basic_auth); | │ │ │ │ │ -| | │ │ │ │ │ -| m_server_string = m_host; | │ │ │ │ │ -| aux::verify_encoding(m_server_string); | │ │ │ │ │ +| m_thread->join(); | │ │ │ │ │ +| } | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -| int web_connection_base::timeout() const | │ │ │ │ │ +| TORRENT_EXPORT std::unique_ptr default_disk_io_constructor( | │ │ │ │ │ +| io_context& ios, settings_interface const& sett, counters& cnt) | │ │ │ │ │ | { | │ │ │ │ │ -| // since this is a web seed, change the timeout | │ │ │ │ │ -| // according to the settings. | │ │ │ │ │ -| return m_settings.get_int(settings_pack::urlseed_timeout); | │ │ │ │ │ -|_ _}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_p_e___c_r_y_p_t_o_._c_p_p_:_6_0_ _ _ _ _ _ _ _|_i_t_ _w_o_u_l_d_ _b_e_ _n_i_c_e_ _t_o_ _g_e_t_ _t_h_e_ _l_i_t_e_r_a_l_ _w_o_r_k_i_n_g_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** iitt wwoouulldd bbee nniiccee ttoo ggeett tthhee lliitteerraall wwoorrkkiinngg ********** | │ │ │ │ │ -|****** ....//ssrrcc//ppee__ccrryyppttoo..ccpppp::6600 ****** | │ │ │ │ │ -|#include | │ │ │ │ │ -|#include | │ │ │ │ │ -| | │ │ │ │ │ -|#include "libtorrent/aux_/disable_warnings_push.hpp" | │ │ │ │ │ -| | │ │ │ │ │ -|#include | │ │ │ │ │ -|#include | │ │ │ │ │ -| | │ │ │ │ │ +|#if TORRENT_HAVE_MMAP || TORRENT_HAVE_MAP_VIEW_OF_FILE | │ │ │ │ │ +|#include "libtorrent/aux_/disable_deprecation_warnings_push.hpp" | │ │ │ │ │ +|if (sizeof(void*) == 8) | │ │ │ │ │ +| return mmap_disk_io_constructor(ios, sett, cnt); | │ │ │ │ │ +| else | │ │ │ │ │ +| return posix_disk_io_constructor(ios, sett, cnt); | │ │ │ │ │ |#include "libtorrent/aux_/disable_warnings_pop.hpp" | │ │ │ │ │ -| | │ │ │ │ │ -|#include "libtorrent/random.hpp" | │ │ │ │ │ -|#include "libtorrent/aux_/alloca.hpp" | │ │ │ │ │ -|#include "libtorrent/pe_crypto.hpp" | │ │ │ │ │ -|#include "libtorrent/hasher.hpp" | │ │ │ │ │ -| | │ │ │ │ │ -|namespace libtorrent { | │ │ │ │ │ -| | │ │ │ │ │ -| namespace mp = boost::multiprecision; | │ │ │ │ │ -| | │ │ │ │ │ -| namespace { | │ │ │ │ │ -|key_t const dh_prime | │ │ │ │ │ -|("0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63|36210000000000090563"); │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| std::array export_key(key_t const& k) | │ │ │ │ │ -| { | │ │ │ │ │ -| std::array ret; | │ │ │ │ │ -| auto* begin = reinterpret_cast(ret.data()); | │ │ │ │ │ -|_ _ _s_t_d_:_:_u_i_n_t_8___t_*_ _e_n_d_ _=_ _m_p_:_:_e_x_p_o_r_t___b_i_t_s_(_k_,_ _b_e_g_i_n_,_ _8_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_p_e___c_r_y_p_t_o_._c_p_p_:_7_1_ _ _ _ _ _ _ _|_i_t_ _w_o_u_l_d_ _b_e_ _n_i_c_e_ _t_o_ _b_e_ _a_b_l_e_ _t_o_ _e_x_p_o_r_t_ _t_o_ _a_ _f_i_x_e_d_ _w_i_d_t_h_ _f_i_e_l_d_,_ _s_o_ _w_e_ _w_o_u_l_d_n_'_t_ _h_a_v_e_ _t_o_ _s_h_i_f_t_ _i_t_ _l_a_t_e_r_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** iitt wwoouulldd bbee nniiccee ttoo bbee aabbllee ttoo eexxppoorrtt ttoo aa ffiixxeedd wwiiddtthh ffiieelldd,, ssoo wwee wwoouullddnn''tt hhaavvee ttoo sshhiifftt iitt llaatteerr ********** | │ │ │ │ │ -|****** ....//ssrrcc//ppee__ccrryyppttoo..ccpppp::7711 ****** | │ │ │ │ │ -|#include "libtorrent/random.hpp" | │ │ │ │ │ -|#include "libtorrent/aux_/alloca.hpp" | │ │ │ │ │ -|#include "libtorrent/pe_crypto.hpp" | │ │ │ │ │ -|#include "libtorrent/hasher.hpp" | │ │ │ │ │ -| | │ │ │ │ │ -|namespace libtorrent { | │ │ │ │ │ -| | │ │ │ │ │ -| namespace mp = boost::multiprecision; | │ │ │ │ │ -| | │ │ │ │ │ -| namespace { | │ │ │ │ │ -| key_t const dh_prime | │ │ │ │ │ -| | │ │ │ │ │ -|("0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63|36210000000000090563"); │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| std::array export_key(key_t const& k) | │ │ │ │ │ -| { | │ │ │ │ │ -| std::array ret; | │ │ │ │ │ -| auto* begin = reinterpret_cast(ret.data()); | │ │ │ │ │ -| std::uint8_t* end = mp::export_bits(k, begin, 8); | │ │ │ │ │ -| | │ │ │ │ │ -|if (end < begin + 96) | │ │ │ │ │ -|{ | │ │ │ │ │ -| int const len = int(end - begin); | │ │ │ │ │ -|#if defined __GNUC__ && __GNUC__ == 12 | │ │ │ │ │ -|#pragma GCC diagnostic push | │ │ │ │ │ -|#pragma GCC diagnostic ignored "-Wstringop-overflow" | │ │ │ │ │ -|#endif | │ │ │ │ │ -| std::memmove(begin + 96 - len, begin, aux::numeric_cast(len)); | │ │ │ │ │ -|#if defined __GNUC__ && __GNUC__ == 12 | │ │ │ │ │ -|#pragma GCC diagnostic pop | │ │ │ │ │ +|#else | │ │ │ │ │ +| return posix_disk_io_constructor(ios, sett, cnt); | │ │ │ │ │ |#endif | │ │ │ │ │ -| std::memset(begin, 0, aux::numeric_cast(96 - len)); | │ │ │ │ │ -| } | │ │ │ │ │ -| return ret; | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -| void rc4_init(const unsigned char* in, std::size_t len, rc4 *state); | │ │ │ │ │ -| std::size_t rc4_encrypt(unsigned char *out, std::size_t outlen, rc4 *state); | │ │ │ │ │ -| | │ │ │ │ │ -| // Set the prime P and the generator, generate local public key | │ │ │ │ │ -| dh_key_exchange::dh_key_exchange() | │ │ │ │ │ -| { | │ │ │ │ │ -| aux::array random_key; | │ │ │ │ │ -| aux::random_bytes({reinterpret_cast(random_key.data()) | │ │ │ │ │ -| , static_cast(random_key.size())}); | │ │ │ │ │ -| | │ │ │ │ │ -| // create local key (random) | │ │ │ │ │ -| mp::import_bits(m_dh_local_secret, random_key.begin(), random_key.end()); | │ │ │ │ │ -| | │ │ │ │ │ -| // key = (2 ^ secret) % prime | │ │ │ │ │ -|_ _ _m___d_h___l_o_c_a_l___k_e_y_ _=_ _m_p_:_:_p_o_w_m_(_k_e_y___t_(_2_)_,_ _m___d_h___l_o_c_a_l___s_e_c_r_e_t_,_ _d_h___p_r_i_m_e_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_u_t___m_e_t_a_d_a_t_a_._c_p_p_:_2_8_1_ _ _ _ _|_w_e_ _r_e_a_l_l_y_ _n_e_e_d_ _t_o_ _i_n_c_r_e_m_e_n_t_ _t_h_e_ _r_e_f_c_o_u_n_t_e_r_ _o_n_ _t_h_e_ _t_o_r_r_e_n_t_ _w_h_i_l_e_ _t_h_i_s_ _b_u_f_f_e_r_ _i_s_ _s_t_i_l_l_ _i_n_ _t_h_e_ _p_e_e_r_'_s_ _s_e_n_d_ _b_u_f_f_e_r_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** wwee rreeaallllyy nneeeedd ttoo iinnccrreemmeenntt tthhee rreeffccoouunntteerr oonn tthhee ttoorrrreenntt wwhhiillee tthhiiss bbuuffffeerr iiss ssttiillll iinn tthhee ppeeeerr''ss sseenndd bbuuffffeerr ********** | │ │ │ │ │ -|****** ....//ssrrcc//uutt__mmeettaaddaattaa..ccpppp::228811 ****** | │ │ │ │ │ -|int const offset = piece * 16 * 1024; | │ │ │ │ │ -| metadata = m_tp.metadata().data() + offset; | │ │ │ │ │ -| metadata_piece_size = std::min( | │ │ │ │ │ -| int(m_tp.metadata().size()) - offset, 16 * 1024); | │ │ │ │ │ -| TORRENT_ASSERT(metadata_piece_size > 0); | │ │ │ │ │ -| TORRENT_ASSERT(offset >= 0); | │ │ │ │ │ -| TORRENT_ASSERT(offset + metadata_piece_size <= m_tp.metadata().size()); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| char msg[200]; | │ │ │ │ │ -| char* header = msg; | │ │ │ │ │ -| char* p = &msg[6]; | │ │ │ │ │ -| int const len = bencode(p, e); | │ │ │ │ │ -| int const total_size = 2 + len + metadata_piece_size; | │ │ │ │ │ -| namespace io = aux; | │ │ │ │ │ -| io::write_uint32(total_size, header); | │ │ │ │ │ -| io::write_uint8(bt_peer_connection::msg_extended, header); | │ │ │ │ │ -| io::write_uint8(m_message_index, header); | │ │ │ │ │ -| | │ │ │ │ │ -| m_pc.send_buffer({msg, len + 6}); | │ │ │ │ │ -|if (metadata_piece_size) | │ │ │ │ │ -|{ | │ │ │ │ │ -| m_pc.append_const_send_buffer( | │ │ │ │ │ -| span(const_cast(metadata), metadata_piece_size), metadata_piece_size); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| m_pc.stats_counters().inc_stats_counter(counters::num_outgoing_extended); | │ │ │ │ │ -| m_pc.stats_counters().inc_stats_counter(counters::num_outgoing_metadata); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| bool on_extended(int const length | │ │ │ │ │ -| , int const extended_msg, span body) override | │ │ │ │ │ -| { | │ │ │ │ │ -| if (extended_msg != 2) return false; | │ │ │ │ │ -| if (m_message_index == 0) return false; | │ │ │ │ │ -| | │ │ │ │ │ -| if (length > 17 * 1024) | │ │ │ │ │ -| { | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ -| m_pc.peer_log(peer_log_alert::incoming_message, "UT_METADATA" | │ │ │ │ │ -| , "packet too big %d", length); | │ │ │ │ │ -|#endif | │ │ │ │ │ -| m_pc.disconnect(errors::invalid_metadata_message, operation_t::bittorrent, peer_connection_interface::peer_error); | │ │ │ │ │ -| return true; | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| if (!m_pc.packet_finished()) return true; | │ │ │ │ │ -| | │ │ │ │ │ -| error_code ec; | │ │ │ │ │ -| bdecode_node msg = bdecode(body, ec); | │ │ │ │ │ -|_ _ _ _i_f_ _(_m_s_g_._t_y_p_e_(_)_ _!_=_ _b_d_e_c_o_d_e___n_o_d_e_:_:_d_i_c_t___t_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_e_n_u_m___n_e_t_._c_p_p_:_1_4_4_ _ _ _ _ _ _ _|_i_n_ _C_+_+_1_7_,_ _u_s_e_ _____h_a_s___i_n_c_l_u_d_e_ _f_o_r_ _t_h_i_s_._ _O_t_h_e_r_ _o_p_e_r_a_t_i_n_g_ _s_y_s_t_e_m_s_ _a_r_e_ _l_i_k_e_l_y_ _t_o_ _r_e_q_u_i_r_e_ _t_h_i_s_ _a_s_ _w_e_l_l_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** iinn CC++++1177,, uussee ____hhaass__iinncclluuddee ffoorr tthhiiss.. OOtthheerr ooppeerraattiinngg ssyysstteemmss aarree lliikkeellyy ttoo rreeqquuiirree tthhiiss aass wweellll ********** | │ │ │ │ │ |****** ....//ssrrcc//eennuumm__nneett..ccpppp::114444 ****** | │ │ │ │ │ |#include | │ │ │ │ │ |#include | │ │ │ │ │ |#include | │ │ │ │ │ |#include | │ │ │ │ │ @@ -8824,519 +7382,295 @@ │ │ │ │ │ | return -1; | │ │ │ │ │ | | │ │ │ │ │ | // get the socket's port ID so that we can verify it in the response | │ │ │ │ │ | sockaddr_nl sock_addr; | │ │ │ │ │ | socklen_t sock_addr_len = sizeof(sock_addr); | │ │ │ │ │ | if (::getsockname(sock, reinterpret_cast(&sock_addr), &sock_addr_len) < 0) | │ │ │ │ │ |_ _ _ _r_e_t_u_r_n_ _-_1_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_t_o_r_r_e_n_t_._c_p_p_:_1_9_4_1_ _ _ _ _ _ _ _|_t_h_i_s_ _c_o_u_l_d_ _b_e_ _o_p_t_i_m_i_z_e_d_ _b_y_ _l_o_o_k_i_n_g_ _u_p_ _w_h_i_c_h_ _f_i_l_e_s_ _a_r_e_ _c_o_m_p_l_e_t_e_ _a_n_d_ _j_u_s_t_ _l_o_o_k_ _a_t_ _t_h_o_s_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tthhiiss ccoouulldd bbee ooppttiimmiizzeedd bbyy llooookkiinngg uupp wwhhiicchh ffiilleess aarree ccoommpplleettee aanndd jjuusstt llooookk aatt tthhoossee ********** | │ │ │ │ │ -|****** ....//ssrrcc//ttoorrrreenntt..ccpppp::11994411 ****** | │ │ │ │ │ -|// TORRENT_ASSERT(picker().have_piece(i)); | │ │ │ │ │ -| we_have(i); | │ │ │ │ │ -| } | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| set_state(torrent_status::checking_resume_data); | │ │ │ │ │ -| | │ │ │ │ │ -| aux::vector links; | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_MUTABLE_TORRENTS | │ │ │ │ │ -| if (!m_torrent_file->similar_torrents().empty() | │ │ │ │ │ -| || !m_torrent_file->collections().empty()) | │ │ │ │ │ -| { | │ │ │ │ │ -| resolve_links res(m_torrent_file); | │ │ │ │ │ -| | │ │ │ │ │ -| for (auto const& ih : m_torrent_file->similar_torrents()) | │ │ │ │ │ -| { | │ │ │ │ │ -| std::shared_ptr t = m_ses.find_torrent(info_hash_t(ih)).lock(); | │ │ │ │ │ -| if (!t) continue; | │ │ │ │ │ -| | │ │ │ │ │ -| // Only attempt to reuse files from torrents that are seeding. | │ │ │ │ │ -|if (!t->is_seed()) continue; | │ │ │ │ │ -| | │ │ │ │ │ -| res.match(t->get_torrent_file(), t->save_path()); | │ │ │ │ │ -| } | │ │ │ │ │ -| for (auto const& c : m_torrent_file->collections()) | │ │ │ │ │ -| { | │ │ │ │ │ -| std::vector> ts = m_ses.find_collection(c); | │ │ │ │ │ +|relevance 0|_._._/_s_r_c_/ |introduce a web-seed default class which has a low download priority | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_w_e_b___c_o_n_n_e_c_t_i_o_n___b_a_s_e_._c_p_p_:_7_2_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** iinnttrroodduuccee aa wweebb--sseeeedd ddeeffaauulltt ccllaassss wwhhiicchh hhaass aa llooww ddoowwnnllooaadd pprriioorriittyy ********** | │ │ │ │ │ +|****** ....//ssrrcc//wweebb__ccoonnnneeccttiioonn__bbaassee..ccpppp::7722 ****** | │ │ │ │ │ +|: peer_connection(pack) | │ │ │ │ │ +| , m_first_request(true) | │ │ │ │ │ +| , m_ssl(false) | │ │ │ │ │ +| , m_external_auth(web.auth) | │ │ │ │ │ +| , m_extra_headers(web.extra_headers) | │ │ │ │ │ +| , m_parser(http_parser::dont_parse_chunks) | │ │ │ │ │ +| , m_body_start(0) | │ │ │ │ │ +| { | │ │ │ │ │ +| TORRENT_ASSERT(&web.peer_info == pack.peerinfo); | │ │ │ │ │ +| // when going through a proxy, we don't necessarily have an endpoint here, | │ │ │ │ │ +| // since the proxy might be resolving the hostname, not us | │ │ │ │ │ +| TORRENT_ASSERT(web.endpoints.empty() || web.endpoints.front() == pack.endp); | │ │ │ │ │ | | │ │ │ │ │ -| for (auto const& t : ts) | │ │ │ │ │ -| { | │ │ │ │ │ -|_ _ _ _ _ _/_/_ _O_n_l_y_ _a_t_t_e_m_p_t_ _t_o_ _r_e_u_s_e_ _f_i_l_e_s_ _f_r_o_m_ _t_o_r_r_e_n_t_s_ _t_h_a_t_ _a_r_e_ _s_e_e_d_i_n_g_._ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_t_o_r_r_e_n_t_._c_p_p_:_1_9_5_4_ _ _ _ _ _ _ _|_t_h_i_s_ _c_o_u_l_d_ _b_e_ _o_p_t_i_m_i_z_e_d_ _b_y_ _l_o_o_k_i_n_g_ _u_p_ _w_h_i_c_h_ _f_i_l_e_s_ _a_r_e_ _c_o_m_p_l_e_t_e_ _a_n_d_ _j_u_s_t_ _l_o_o_k_ _a_t_ _t_h_o_s_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tthhiiss ccoouulldd bbee ooppttiimmiizzeedd bbyy llooookkiinngg uupp wwhhiicchh ffiilleess aarree ccoommpplleettee aanndd jjuusstt llooookk aatt tthhoossee ********** | │ │ │ │ │ -|****** ....//ssrrcc//ttoorrrreenntt..ccpppp::11995544 ****** | │ │ │ │ │ -|{ | │ │ │ │ │ -| resolve_links res(m_torrent_file); | │ │ │ │ │ +| INVARIANT_CHECK; | │ │ │ │ │ | | │ │ │ │ │ -| for (auto const& ih : m_torrent_file->similar_torrents()) | │ │ │ │ │ -| { | │ │ │ │ │ -| std::shared_ptr t = m_ses.find_torrent(info_hash_t(ih)).lock(); | │ │ │ │ │ -| if (!t) continue; | │ │ │ │ │ +| TORRENT_ASSERT(is_outgoing()); | │ │ │ │ │ | | │ │ │ │ │ -| // Only attempt to reuse files from torrents that are seeding. | │ │ │ │ │ -| if (!t->is_seed()) continue; | │ │ │ │ │ +| TORRENT_ASSERT(!m_torrent.lock()->is_upload_only()); | │ │ │ │ │ | | │ │ │ │ │ -| res.match(t->get_torrent_file(), t->save_path()); | │ │ │ │ │ -| } | │ │ │ │ │ -| for (auto const& c : m_torrent_file->collections()) | │ │ │ │ │ -| { | │ │ │ │ │ -| std::vector> ts = m_ses.find_collection(c); | │ │ │ │ │ +| // we only want left-over bandwidth | │ │ │ │ │ | | │ │ │ │ │ -| for (auto const& t : ts) | │ │ │ │ │ -| { | │ │ │ │ │ -| // Only attempt to reuse files from torrents that are seeding. | │ │ │ │ │ -|if (!t->is_seed()) continue; | │ │ │ │ │ +|std::string protocol; | │ │ │ │ │ +| error_code ec; | │ │ │ │ │ +| std::tie(protocol, m_basic_auth, m_host, m_port, m_path) | │ │ │ │ │ +| = parse_url_components(web.url, ec); | │ │ │ │ │ +| TORRENT_ASSERT(!ec); | │ │ │ │ │ | | │ │ │ │ │ -| res.match(t->get_torrent_file(), t->save_path()); | │ │ │ │ │ -| } | │ │ │ │ │ -| } | │ │ │ │ │ +| if (m_port == -1 && protocol == "http") | │ │ │ │ │ +| m_port = 80; | │ │ │ │ │ | | │ │ │ │ │ -| std::vector const& l = res.get_links(); | │ │ │ │ │ -| if (!l.empty()) | │ │ │ │ │ -| { | │ │ │ │ │ -| links.resize(m_torrent_file->files().num_files()); | │ │ │ │ │ -| for (auto const& i : l) | │ │ │ │ │ -| { | │ │ │ │ │ -| if (!i.ti) continue; | │ │ │ │ │ -| links[i.file_idx] = combine_path(i.save_path | │ │ │ │ │ -| , i.ti->files().file_path(i.file_idx)); | │ │ │ │ │ -| } | │ │ │ │ │ -| } | │ │ │ │ │ +|#if TORRENT_USE_SSL | │ │ │ │ │ +| if (protocol == "https") | │ │ │ │ │ +| { | │ │ │ │ │ +| m_ssl = true; | │ │ │ │ │ +| if (m_port == -1) m_port = 443; | │ │ │ │ │ | } | │ │ │ │ │ -|#endif // TORRENT_DISABLE_MUTABLE_TORRENTS | │ │ │ │ │ -| | │ │ │ │ │ -|#if TORRENT_USE_ASSERTS | │ │ │ │ │ -| TORRENT_ASSERT(m_outstanding_check_files == false); | │ │ │ │ │ -| m_outstanding_check_files = true; | │ │ │ │ │ |#endif | │ │ │ │ │ | | │ │ │ │ │ -| if (!m_add_torrent_params || !(m_add_torrent_params->flags & torrent_flags::no_verify_files)) | │ │ │ │ │ -| { | │ │ │ │ │ -| m_ses.disk_thread().async_check_files( | │ │ │ │ │ -| m_storage, m_add_torrent_params ? m_add_torrent_params.get() : nullptr | │ │ │ │ │ -| , std::move(links), [self = shared_from_this()](status_t st, storage_error const& error) | │ │ │ │ │ -|_ _ _ _ _{_ _s_e_l_f_-_>_o_n___r_e_s_u_m_e___d_a_t_a___c_h_e_c_k_e_d_(_s_t_,_ _e_r_r_o_r_)_;_ _}_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_s_r_c_/_t_o_r_r_e_n_t_._c_p_p_:_2_7_1_5 |this pattern is repeated in a few places. Factor this into a function and generalize the concept of a torrent having a dedicated | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_l_i_s_t_e_n_ _p_o_r_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** tthhiiss ppaatttteerrnn iiss rreeppeeaatteedd iinn aa ffeeww ppllaacceess.. FFaaccttoorr tthhiiss iinnttoo aa ffuunnccttiioonn aanndd ggeenneerraalliizzee tthhee ccoonncceepptt ooff aa ttoorrrreenntt hhaavviinngg aa ddeeddiiccaatteedd lliisstteenn ppoorrtt ********** | │ │ │ │ │ -|****** ....//ssrrcc//ttoorrrreenntt..ccpppp::22771155 ****** | │ │ │ │ │ -|// not ready for peers. Except, if we don't have metadata, | │ │ │ │ │ -| // we need peers to download from | │ │ │ │ │ -| if (!m_files_checked && valid_metadata()) return; | │ │ │ │ │ +| if (!m_basic_auth.empty()) | │ │ │ │ │ +| m_basic_auth = base64encode(m_basic_auth); | │ │ │ │ │ | | │ │ │ │ │ -| if (!m_announce_to_lsd) return; | │ │ │ │ │ +| m_server_string = m_host; | │ │ │ │ │ +| aux::verify_encoding(m_server_string); | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -| // private torrents are never announced on LSD | │ │ │ │ │ -| if (m_torrent_file->is_valid() && m_torrent_file->priv()) return; | │ │ │ │ │ +| int web_connection_base::timeout() const | │ │ │ │ │ +| { | │ │ │ │ │ +| // since this is a web seed, change the timeout | │ │ │ │ │ +| // according to the settings. | │ │ │ │ │ +| return m_settings.get_int(settings_pack::urlseed_timeout); | │ │ │ │ │ +|_ _}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_s_r_c_/ |move stats_counter_t out of counters | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_p_e_r_f_o_r_m_a_n_c_e___c_o_u_n_t_e_r_s_._c_p_p_:_4_0_ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** mmoovvee ssttaattss__ccoouunntteerr__tt oouutt ooff ccoouunntteerrss ********** | │ │ │ │ │ +|_**_**_**_ _.._.._//_ss_rr_cc_//_pp_ee_rr_ff_oo_rr_mm_aa_nn_cc_ee____cc_oo_uu_nn_tt_ee_rr_ss_.._cc_pp_pp_::_44_00_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_s_r_c_/ |should bittorrent keep-alive messages have a counter too? | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_p_e_r_f_o_r_m_a_n_c_e___c_o_u_n_t_e_r_s_._c_p_p_:_4_1_ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** sshhoouulldd bbiittttoorrrreenntt kkeeeepp--aalliivvee mmeessssaaggeess hhaavvee aa ccoouunntteerr ttoooo?? ********** | │ │ │ │ │ +|_**_**_**_ _.._.._//_ss_rr_cc_//_pp_ee_rr_ff_oo_rr_mm_aa_nn_cc_ee____cc_oo_uu_nn_tt_ee_rr_ss_.._cc_pp_pp_::_44_11_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_s_r_c_/ |It would be nice if this could be an internal type. default_disk_constructor depends on it now | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_p_e_r_f_o_r_m_a_n_c_e___c_o_u_n_t_e_r_s_._c_p_p_:_4_2_ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** IItt wwoouulldd bbee nniiccee iiff tthhiiss ccoouulldd bbee aann iinntteerrnnaall ttyyppee.. ddeeffaauulltt__ddiisskk__ccoonnssttrruuccttoorr ddeeppeennddss oonn iitt nnooww ********** | │ │ │ │ │ +|****** ....//ssrrcc//ppeerrffoorrmmaannccee__ccoouunntteerrss..ccpppp::4422 ****** | │ │ │ │ │ +|THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | │ │ │ │ │ +|AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | │ │ │ │ │ +|IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | │ │ │ │ │ +|ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | │ │ │ │ │ +|LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | │ │ │ │ │ +|CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | │ │ │ │ │ +|SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | │ │ │ │ │ +|INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | │ │ │ │ │ +|CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | │ │ │ │ │ +|ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | │ │ │ │ │ +|POSSIBILITY OF SUCH DAMAGE. | │ │ │ │ │ | | │ │ │ │ │ -|#if TORRENT_USE_I2P | │ │ │ │ │ -| // i2p torrents are also never announced on LSD | │ │ │ │ │ -| // unless we allow mixed swarms | │ │ │ │ │ -| if (is_i2p() && !settings().get_bool(settings_pack::allow_i2p_mixed)) | │ │ │ │ │ -| return; | │ │ │ │ │ -|#endif | │ │ │ │ │ +|*/ | │ │ │ │ │ | | │ │ │ │ │ -| if (is_paused()) return; | │ │ │ │ │ +|#include "libtorrent/performance_counters.hpp" | │ │ │ │ │ +|#include "libtorrent/assert.hpp" | │ │ │ │ │ +|#include // for memset | │ │ │ │ │ | | │ │ │ │ │ -| if (!m_ses.has_lsd()) return; | │ │ │ │ │ +|namespace libtorrent { | │ │ │ │ │ | | │ │ │ │ │ -|#ifdef TORRENT_SSL_PEERS | │ │ │ │ │ -|int port = is_ssl_torrent() ? m_ses.ssl_listen_port() : m_ses.listen_port(); | │ │ │ │ │ +|counters::counters() TORRENT_COUNTER_NOEXCEPT | │ │ │ │ │ +|{ | │ │ │ │ │ +|#ifdef ATOMIC_LLONG_LOCK_FREE | │ │ │ │ │ +| for (auto& counter : m_stats_counter) | │ │ │ │ │ +| counter.store(0, std::memory_order_relaxed); | │ │ │ │ │ |#else | │ │ │ │ │ -| int port = m_ses.listen_port(); | │ │ │ │ │ +| m_stats_counter.fill(0); | │ │ │ │ │ |#endif | │ │ │ │ │ -| | │ │ │ │ │ -| // announce with the local discovery service | │ │ │ │ │ -| m_torrent_file->info_hashes().for_each([&](sha1_hash const& ih, protocol_version) | │ │ │ │ │ -| { | │ │ │ │ │ -| m_ses.announce_lsd(ih, port); | │ │ │ │ │ -| }); | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_DHT | │ │ │ │ │ -| | │ │ │ │ │ -| void torrent::dht_announce() | │ │ │ │ │ +| counters::counters(counters const& c) TORRENT_COUNTER_NOEXCEPT | │ │ │ │ │ | { | │ │ │ │ │ -| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ -| if (!m_ses.dht()) | │ │ │ │ │ -| { | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ -| debug_log("DHT: no dht initialized"); | │ │ │ │ │ -|#endif | │ │ │ │ │ -| return; | │ │ │ │ │ -| } | │ │ │ │ │ -| if (!should_announce_dht()) | │ │ │ │ │ -| { | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ -| if (should_log()) | │ │ │ │ │ -| { | │ │ │ │ │ -|_#_i_f_ _T_O_R_R_E_N_T___U_S_E___I_2_P_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_t_o_r_r_e_n_t_._c_p_p_:_3_8_7_0_ _ _ _ _ _ _ _|_a_d_d_ _o_n_e_ _p_e_e_r_ _p_e_r_ _I_P_ _t_h_e_ _h_o_s_t_n_a_m_e_ _r_e_s_o_l_v_e_s_ _t_o_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** aadddd oonnee ppeeeerr ppeerr IIPP tthhee hhoossttnnaammee rreessoollvveess ttoo ********** | │ │ │ │ │ -|****** ....//ssrrcc//ttoorrrreenntt..ccpppp::33887700 ****** | │ │ │ │ │ -|catch (...) { handle_exception(); } | │ │ │ │ │ +|#ifdef ATOMIC_LLONG_LOCK_FREE | │ │ │ │ │ +| for (int i = 0; i < m_stats_counter.end_index(); ++i) | │ │ │ │ │ +| m_stats_counter[i].store( | │ │ │ │ │ +| c.m_stats_counter[i].load(std::memory_order_relaxed) | │ │ │ │ │ +| , std::memory_order_relaxed); | │ │ │ │ │ +|#else | │ │ │ │ │ +| std::lock_guard l(c.m_mutex); | │ │ │ │ │ +| m_stats_counter = c.m_stats_counter; | │ │ │ │ │ |#endif | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -| void torrent::on_peer_name_lookup(error_code const& e | │ │ │ │ │ -| , std::vector
    const& host_list, int const port | │ │ │ │ │ -| , protocol_version const v) try | │ │ │ │ │ +| counters& counters::operator=(counters const& c) & TORRENT_COUNTER_NOEXCEPT | │ │ │ │ │ | { | │ │ │ │ │ -| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ -| | │ │ │ │ │ -| INVARIANT_CHECK; | │ │ │ │ │ -| | │ │ │ │ │ -| COMPLETE_ASYNC("torrent::on_peer_name_lookup"); | │ │ │ │ │ -| | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ -| if (e && should_log()) | │ │ │ │ │ -| debug_log("peer name lookup error: %s", e.message().c_str()); | │ │ │ │ │ +| if (&c == this) return *this; | │ │ │ │ │ +|#ifdef ATOMIC_LLONG_LOCK_FREE | │ │ │ │ │ +| for (int i = 0; i < m_stats_counter.end_index(); ++i) | │ │ │ │ │ +| m_stats_counter[i].store( | │ │ │ │ │ +| c.m_stats_counter[i].load(std::memory_order_relaxed) | │ │ │ │ │ +|_ _ _ _ _ _,_ _s_t_d_:_:_m_e_m_o_r_y___o_r_d_e_r___r_e_l_a_x_e_d_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_t_o_r_r_e_n_t___h_a_n_d_l_e_._c_p_p_:_5_8_9_ _|_s_u_p_p_o_r_t_ _m_o_v_i_n_g_ _f_i_l_e_s_ _i_n_t_o_ _t_h_i_s_ _c_a_l_l_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** ssuuppppoorrtt mmoovviinngg ffiilleess iinnttoo tthhiiss ccaallll ********** | │ │ │ │ │ +|****** ....//ssrrcc//ttoorrrreenntt__hhaannddllee..ccpppp::558899 ****** | │ │ │ │ │ +|auto retp = &prio; | │ │ │ │ │ +| sync_call(&torrent::piece_priorities, retp); | │ │ │ │ │ +| std::vector ret; | │ │ │ │ │ +| ret.reserve(prio.size()); | │ │ │ │ │ +| for (auto p : prio) | │ │ │ │ │ +| ret.push_back(int(static_cast(p))); | │ │ │ │ │ +| return ret; | │ │ │ │ │ +| } | │ │ │ │ │ |#endif | │ │ │ │ │ | | │ │ │ │ │ -| if (e || m_abort || host_list.empty() || m_ses.is_aborted()) return; | │ │ │ │ │ -| | │ │ │ │ │ -|tcp::endpoint host(host_list.front(), std::uint16_t(port)); | │ │ │ │ │ -| | │ │ │ │ │ -| if (m_ip_filter && m_ip_filter->access(host.address()) & ip_filter::blocked) | │ │ │ │ │ -| { | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ -| if (should_log()) | │ │ │ │ │ -| { | │ │ │ │ │ -| debug_log("blocked ip from tracker: %s", host.address().to_string().c_str()); | │ │ │ │ │ -| } | │ │ │ │ │ -|#endif | │ │ │ │ │ -| if (m_ses.alerts().should_post()) | │ │ │ │ │ -| m_ses.alerts().emplace_alert(get_handle() | │ │ │ │ │ -| , host, peer_blocked_alert::ip_filter); | │ │ │ │ │ -| return; | │ │ │ │ │ -| } | │ │ │ │ │ +| void torrent_handle::file_priority(file_index_t index, download_priority_t priority) const | │ │ │ │ │ +| { | │ │ │ │ │ +| async_call(&torrent::set_file_priority, index, priority); | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -| if (add_peer(host, peer_info::tracker, v == protocol_version::V2 ? pex_lt_v2 : pex_flags_t(0))) | │ │ │ │ │ -| { | │ │ │ │ │ -| state_updated(); | │ │ │ │ │ +| download_priority_t torrent_handle::file_priority(file_index_t index) const | │ │ │ │ │ +| { | │ │ │ │ │ +| return sync_call_ret(dont_download, &torrent::file_priority, index); | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ -| if (should_log()) | │ │ │ │ │ -| { | │ │ │ │ │ -| debug_log("name-lookup add_peer() [ %s ] connect-candidates: %d" | │ │ │ │ │ -| , host.address().to_string().c_str() | │ │ │ │ │ -| , m_peer_list ? m_peer_list->num_connect_candidates() : -1); | │ │ │ │ │ -| } | │ │ │ │ │ -|#endif | │ │ │ │ │ -| } | │ │ │ │ │ -| update_want_peers(); | │ │ │ │ │ -|_ _}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_t_o_r_r_e_n_t_._c_p_p_:_4_5_6_2_ _ _ _ _ _ _ _|_o_n_l_y_ _d_o_ _t_h_i_s_ _i_f_ _t_h_e_ _p_i_e_c_e_ _s_i_z_e_ _>_ _1_ _b_l_o_c_k_s_ _T_h_i_s_ _i_s_ _a_ _v_2_ _t_o_r_r_e_n_t_ _s_o_ _w_e_ _c_a_n_ _r_e_q_u_e_s_t_ _g_e_t_ _b_l_o_c_k_ _l_e_v_e_l_ _h_a_s_h_e_s_._ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** oonnllyy ddoo tthhiiss iiff tthhee ppiieeccee ssiizzee >> 11 bblloocckkss TThhiiss iiss aa vv22 ttoorrrreenntt ssoo wwee ccaann rreeqquueesstt ggeett bblloocckk lleevveell hhaasshheess.. ********** | │ │ │ │ │ -|****** ....//ssrrcc//ttoorrrreenntt..ccpppp::44556622 ****** | │ │ │ │ │ +|void torrent_handle::prioritize_files(std::vector const& files) const | │ │ │ │ │ |{ | │ │ │ │ │ -| std::set ret; | │ │ │ │ │ -| if (!blocks.empty() && !downloaders.empty()) | │ │ │ │ │ -| { | │ │ │ │ │ -| for (auto const b : blocks) ret.insert(downloaders[std::size_t(b)]); | │ │ │ │ │ -| } | │ │ │ │ │ -| else | │ │ │ │ │ -| { | │ │ │ │ │ -| std::copy(downloaders.begin(), downloaders.end(), std::inserter(ret, ret.begin())); | │ │ │ │ │ -| } | │ │ │ │ │ -| return ret; | │ │ │ │ │ -| }(); | │ │ │ │ │ -| | │ │ │ │ │ -| // if this piece wasn't downloaded from peers, we just found it on disk. | │ │ │ │ │ -| // In that case, we should just consider it as "not-have" and there's no | │ │ │ │ │ -| // need to try to get higher fidelity hashes (yet) | │ │ │ │ │ -| bool const found_on_disk = peers.size() == 1 && peers.count(nullptr); | │ │ │ │ │ -| | │ │ │ │ │ -| if (!torrent_file().info_hashes().has_v1() && blocks.empty() && !found_on_disk) | │ │ │ │ │ -| { | │ │ │ │ │ -|verify_block_hashes(index); | │ │ │ │ │ -|} | │ │ │ │ │ -| | │ │ │ │ │ -| // the below code is penalizing peers that sent use bad data. | │ │ │ │ │ -| // increase the total amount of failed bytes | │ │ │ │ │ -| if (!found_on_disk) | │ │ │ │ │ -| { | │ │ │ │ │ -| if (blocks.empty()) | │ │ │ │ │ -| add_failed_bytes(m_torrent_file->piece_size(index)); | │ │ │ │ │ -| else | │ │ │ │ │ -| add_failed_bytes(static_cast(blocks.size()) * default_block_size); | │ │ │ │ │ -| | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_EXTENSIONS | │ │ │ │ │ -| for (auto& ext : m_extensions) | │ │ │ │ │ -| { | │ │ │ │ │ -| ext->on_piece_failed(index); | │ │ │ │ │ -| } | │ │ │ │ │ -|#endif | │ │ │ │ │ -| | │ │ │ │ │ -| // did we receive this piece from a single peer? | │ │ │ │ │ -| // if we know exactly which blocks failed the hash, we can also be certain | │ │ │ │ │ -| // that all peers in the list sent us bad data | │ │ │ │ │ -| bool const known_bad_peer = (!found_on_disk && peers.size() == 1) || !blocks.empty(); | │ │ │ │ │ -| | │ │ │ │ │ -| penalize_peers(peers, index, known_bad_peer); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| // If m_storage isn't set here, it means we're shutting down | │ │ │ │ │ -| if (m_storage) | │ │ │ │ │ -| { | │ │ │ │ │ -|_ _ _ _/_/_ _i_t_ _d_o_e_s_n_'_t_ _m_a_k_e_ _m_u_c_h_ _s_e_n_s_e_ _t_o_ _f_a_i_l_ _t_o_ _h_a_s_h_ _a_ _p_i_e_c_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_t_o_r_r_e_n_t_._c_p_p_:_7_5_0_1_ _ _ _ _ _ _ _|_c_o_m_e_ _u_p_ _w_i_t_h_ _a_ _b_e_t_t_e_r_ _w_a_y_ _o_f_ _d_o_i_n_g_ _t_h_i_s_,_ _i_n_s_t_e_a_d_ _o_f_ _a_n_ _i_m_m_e_d_i_a_t_e_l_y_ _i_n_v_o_k_e_d_ _l_a_m_b_d_a_ _e_x_p_r_e_s_s_i_o_n_._ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** ccoommee uupp wwiitthh aa bbeetttteerr wwaayy ooff ddooiinngg tthhiiss,, iinnsstteeaadd ooff aann iimmmmeeddiiaatteellyy iinnvvookkeedd llaammbbddaa eexxpprreessssiioonn.. ********** | │ │ │ │ │ -|****** ....//ssrrcc//ttoorrrreenntt..ccpppp::77550011 ****** | │ │ │ │ │ -||| peerinfo->confirmed_supports_utp)) | │ │ │ │ │ -| { | │ │ │ │ │ -| sm = m_ses.utp_socket_manager(); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| // don't make a TCP connection if it's disabled | │ │ │ │ │ -| if (sm == nullptr && !settings().get_bool(settings_pack::enable_outgoing_tcp)) | │ │ │ │ │ -| { | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ -| if (should_log()) | │ │ │ │ │ -| { | │ │ │ │ │ -| debug_log("discarding peer \"%s\": TCP connections disabled " | │ │ │ │ │ -| "[ supports-utp: %d ]", peerinfo->to_string().c_str() | │ │ │ │ │ -| , peerinfo->supports_utp); | │ │ │ │ │ -| } | │ │ │ │ │ -|#endif | │ │ │ │ │ -| return false; | │ │ │ │ │ -| } | │ │ │ │ │ -| } | │ │ │ │ │ +| async_call(&torrent::prioritize_files | │ │ │ │ │ +| , static_cast const&>(files)); | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -|aux::socket_type s = [&] { | │ │ │ │ │ +| std::vector torrent_handle::get_file_priorities() const | │ │ │ │ │ +| { | │ │ │ │ │ +| aux::vector ret; | │ │ │ │ │ +| auto retp = &ret; | │ │ │ │ │ +| sync_call(&torrent::file_priorities, retp); | │ │ │ │ │ +| return TORRENT_RVO(ret); | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -|#if TORRENT_USE_I2P | │ │ │ │ │ -| if (peerinfo->is_i2p_addr) | │ │ │ │ │ -| { | │ │ │ │ │ -| // It's not entirely obvious why this peer connection is not marked as | │ │ │ │ │ -| // one. The main feature of a peer connection is that whether or not we | │ │ │ │ │ -| // proxy it is configurable. When we use i2p, we want to always prox | │ │ │ │ │ -| // everything via i2p. | │ │ │ │ │ +|#if TORRENT_ABI_VERSION == 1 | │ │ │ │ │ | | │ │ │ │ │ -| aux::proxy_settings proxy; | │ │ │ │ │ -| proxy.hostname = settings().get_str(settings_pack::i2p_hostname); | │ │ │ │ │ -| proxy.port = std::uint16_t(settings().get_int(settings_pack::i2p_port)); | │ │ │ │ │ -| proxy.type = settings_pack::i2p_proxy; | │ │ │ │ │ +|// ============ start deprecation =============== | │ │ │ │ │ | | │ │ │ │ │ -| aux::socket_type ret = instantiate_connection(m_ses.get_context() | │ │ │ │ │ -| , proxy, nullptr, nullptr, false, false); | │ │ │ │ │ -| i2p_stream& str = boost::get(ret); | │ │ │ │ │ -| str.set_local_i2p_endpoint(m_ses.local_i2p_endpoint()); | │ │ │ │ │ -| str.set_destination(static_cast(peerinfo)->dest()); | │ │ │ │ │ -| str.set_command(i2p_stream::cmd_connect); | │ │ │ │ │ -| str.set_session_id(m_ses.i2p_session()); | │ │ │ │ │ -| return ret; | │ │ │ │ │ +| void torrent_handle::prioritize_files(std::vector const& files) const | │ │ │ │ │ +| { | │ │ │ │ │ +| aux::vector file_prio; | │ │ │ │ │ +| file_prio.reserve(files.size()); | │ │ │ │ │ +| for (auto const p : files) { | │ │ │ │ │ +| file_prio.push_back(download_priority_t(static_cast(p))); | │ │ │ │ │ | } | │ │ │ │ │ -| else | │ │ │ │ │ -|#endif | │ │ │ │ │ -| { | │ │ │ │ │ -| void* userdata = nullptr; | │ │ │ │ │ -|#ifdef TORRENT_SSL_PEERS | │ │ │ │ │ -| if (is_ssl_torrent()) | │ │ │ │ │ -|_ _ _ _{_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_t_o_r_r_e_n_t_._c_p_p_:_9_0_9_1_ _ _ _ _ _ _ _|_p_e_r_h_a_p_s_ _0_ _s_h_o_u_l_d_ _a_c_t_u_a_l_l_y_ _m_e_a_n_ _0_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** ppeerrhhaappss 00 sshhoouulldd aaccttuuaallllyy mmeeaann 00 ********** | │ │ │ │ │ -|****** ....//ssrrcc//ttoorrrreenntt..ccpppp::99009911 ****** | │ │ │ │ │ -|// finished torrents may not change their queue positions, as it's set to | │ │ │ │ │ -| // -1 | │ │ │ │ │ -| if ((m_abort || is_finished()) && p != no_pos) return; | │ │ │ │ │ -| | │ │ │ │ │ -| TORRENT_ASSERT((p == no_pos) == is_finished() | │ │ │ │ │ -| || (!m_auto_managed && p == no_pos) | │ │ │ │ │ -| || (m_abort && p == no_pos) | │ │ │ │ │ -| || (!m_added && p == no_pos)); | │ │ │ │ │ -| if (p == m_sequence_number) return; | │ │ │ │ │ -| | │ │ │ │ │ -| TORRENT_ASSERT(p >= no_pos); | │ │ │ │ │ -| | │ │ │ │ │ -| state_updated(); | │ │ │ │ │ -| | │ │ │ │ │ -| m_ses.set_queue_position(this, p); | │ │ │ │ │ +| async_call(&torrent::prioritize_files, file_prio); | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -| void torrent::set_max_uploads(int limit, bool const state_update) | │ │ │ │ │ +| std::vector torrent_handle::file_priorities() const | │ │ │ │ │ | { | │ │ │ │ │ -| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ -|if (limit <= 0) limit = (1 << 24) - 1; | │ │ │ │ │ -|if (int(m_max_uploads) == limit) return; | │ │ │ │ │ -| if (state_update) state_updated(); | │ │ │ │ │ -| m_max_uploads = aux::numeric_cast(limit); | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ -| if (should_log() && state_update) | │ │ │ │ │ -| debug_log("*** set-max-uploads: %d", m_max_uploads); | │ │ │ │ │ -|#endif | │ │ │ │ │ -| | │ │ │ │ │ -| if (state_update) | │ │ │ │ │ -| set_need_save_resume(torrent_handle::if_config_changed); | │ │ │ │ │ -| } | │ │ │ │ │ +|_ _ _a_u_x_:_:_v_e_c_t_o_r_<_d_o_w_n_l_o_a_d___p_r_i_o_r_i_t_y___t_,_ _f_i_l_e___i_n_d_e_x___t_>_ _p_r_i_o_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_s_r_c_/_p_o_s_i_x___p_a_r_t___f_i_l_e_._c_p_p_:_3_3_7|what do we do if someone is currently reading from the disk from this piece? does it matter? Since we won't actively erase the data | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_f_r_o_m_ _d_i_s_k_,_ _b_u_t_ _i_t_ _m_a_y_ _b_e_ _o_v_e_r_w_r_i_t_t_e_n_ _s_o_o_n_,_ _i_t_'_s_ _p_r_o_b_a_b_l_y_ _n_o_t_ _t_h_a_t_ _b_i_g_ _o_f_ _a_ _d_e_a_l_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** wwhhaatt ddoo wwee ddoo iiff ssoommeeoonnee iiss ccuurrrreennttllyy rreeaaddiinngg ffrroomm tthhee ddiisskk ffrroomm tthhiiss ppiieeccee?? ddooeess iitt mmaatttteerr?? SSiinnccee wwee wwoonn''tt aaccttiivveellyy eerraassee tthhee ddaattaa ffrroomm ddiisskk,, bbuutt iitt mmaayy bbee oovveerrwwrriitttteenn | │ │ │ │ │ +|ssoooonn,, iitt''ss pprroobbaabbllyy nnoott tthhaatt bbiigg ooff aa ddeeaall ********** | │ │ │ │ │ +|****** ....//ssrrcc//ppoossiixx__ppaarrtt__ffiillee..ccpppp::333377 ****** | │ │ │ │ │ +| if (ec) return {}; | │ │ │ │ │ | | │ │ │ │ │ -| void torrent::set_max_connections(int limit, bool const state_update) | │ │ │ │ │ -| { | │ │ │ │ │ -|_ _ _T_O_R_R_E_N_T___A_S_S_E_R_T_(_i_s___s_i_n_g_l_e___t_h_r_e_a_d_(_)_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_t_o_r_r_e_n_t_._c_p_p_:_9_1_0_8_ _ _ _ _ _ _ _|_p_e_r_h_a_p_s_ _0_ _s_h_o_u_l_d_ _a_c_t_u_a_l_l_y_ _m_e_a_n_ _0_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** ppeerrhhaappss 00 sshhoouulldd aaccttuuaallllyy mmeeaann 00 ********** | │ │ │ │ │ -|****** ....//ssrrcc//ttoorrrreenntt..ccpppp::99110088 ****** | │ │ │ │ │ -| void torrent::set_max_uploads(int limit, bool const state_update) | │ │ │ │ │ -| { | │ │ │ │ │ -| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ -| if (limit <= 0) limit = (1 << 24) - 1; | │ │ │ │ │ -| if (int(m_max_uploads) == limit) return; | │ │ │ │ │ -| if (state_update) state_updated(); | │ │ │ │ │ -| m_max_uploads = aux::numeric_cast(limit); | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ -| if (should_log() && state_update) | │ │ │ │ │ -| debug_log("*** set-max-uploads: %d", m_max_uploads); | │ │ │ │ │ +|#ifdef TORRENT_WINDOWS | │ │ │ │ │ +| ret = file_pointer(::_wfopen(convert_to_native_path_string(fn).c_str(), L"wb+")); | │ │ │ │ │ +|#else | │ │ │ │ │ +| ret = file_pointer(::fopen(fn.c_str(), "wb+")); | │ │ │ │ │ |#endif | │ │ │ │ │ -| | │ │ │ │ │ -| if (state_update) | │ │ │ │ │ -| set_need_save_resume(torrent_handle::if_config_changed); | │ │ │ │ │ +| if (ret.file() == nullptr) | │ │ │ │ │ +| ec.assign(errno, generic_category()); | │ │ │ │ │ +| } | │ │ │ │ │ +| if (ec) return {}; | │ │ │ │ │ +| return ret; | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -| void torrent::set_max_connections(int limit, bool const state_update) | │ │ │ │ │ +| void posix_part_file::free_piece(piece_index_t const piece) | │ │ │ │ │ | { | │ │ │ │ │ -| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ -|if (limit <= 0) limit = (1 << 24) - 1; | │ │ │ │ │ -|if (int(m_max_connections) == limit) return; | │ │ │ │ │ -| if (state_update) state_updated(); | │ │ │ │ │ -| m_max_connections = aux::numeric_cast(limit); | │ │ │ │ │ -| update_want_peers(); | │ │ │ │ │ +| auto const i = m_piece_map.find(piece); | │ │ │ │ │ +| if (i == m_piece_map.end()) return; | │ │ │ │ │ | | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ -| if (should_log() && state_update) | │ │ │ │ │ -| debug_log("*** set-max-connections: %d", m_max_connections); | │ │ │ │ │ -|#endif | │ │ │ │ │ | | │ │ │ │ │ -| if (num_peers() > int(m_max_connections)) | │ │ │ │ │ -| { | │ │ │ │ │ -| disconnect_peers(num_peers() - m_max_connections | │ │ │ │ │ -| , errors::too_many_connections); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -| if (state_update) | │ │ │ │ │ -| set_need_save_resume(torrent_handle::if_config_changed); | │ │ │ │ │ +|m_free_slots.push_back(i->second); | │ │ │ │ │ +| m_piece_map.erase(i); | │ │ │ │ │ +| m_dirty_metadata = true; | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -| void torrent::set_upload_limit(int const limit) | │ │ │ │ │ +| void posix_part_file::move_partfile(std::string const& path, error_code& ec) | │ │ │ │ │ | { | │ │ │ │ │ -| set_limit_impl(limit, peer_connection::upload_channel); | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ -| debug_log("*** set-upload-limit: %d", limit); | │ │ │ │ │ -|#endif | │ │ │ │ │ -| } | │ │ │ │ │ +| flush_metadata_impl(ec); | │ │ │ │ │ +| if (ec) return; | │ │ │ │ │ | | │ │ │ │ │ -| void torrent::set_download_limit(int const limit) | │ │ │ │ │ -|_ _{_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_t_o_r_r_e_n_t_._c_p_p_:_1_1_0_3_4_ _ _ _ _ _ _|_i_n_s_t_e_a_d_ _o_f_ _r_e_s_o_r_t_i_n_g_ _t_h_e_ _w_h_o_l_e_ _l_i_s_t_,_ _i_n_s_e_r_t_ _t_h_e_ _p_e_e_r_s_ _d_i_r_e_c_t_l_y_ _i_n_t_o_ _t_h_e_ _r_i_g_h_t_ _p_l_a_c_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** iinnsstteeaadd ooff rreessoorrttiinngg tthhee wwhhoollee lliisstt,, iinnsseerrtt tthhee ppeeeerrss ddiirreeccttllyy iinnttoo tthhee rriigghhtt ppllaaccee ********** | │ │ │ │ │ -|****** ....//ssrrcc//ttoorrrreenntt..ccpppp::1111003344 ****** | │ │ │ │ │ -|std::printf("timed out [average-piece-time: %d ms ]\n" | │ │ │ │ │ -| , m_average_piece_time); | │ │ │ │ │ -|#endif | │ │ │ │ │ -| } | │ │ │ │ │ +| if (!m_piece_map.empty()) | │ │ │ │ │ +| { | │ │ │ │ │ +| std::string old_path = combine_path(m_path, m_name); | │ │ │ │ │ +| std::string new_path = combine_path(path, m_name); | │ │ │ │ │ | | │ │ │ │ │ -| // pick all blocks for this piece. the peers list is kept up to date | │ │ │ │ │ -| // and sorted. when we issue a request to a peer, its download queue | │ │ │ │ │ -| // time will increase and it may need to be bumped in the peers list, | │ │ │ │ │ -| // since it's ordered by download queue time | │ │ │ │ │ -| pick_time_critical_block(peers, ignore_peers | │ │ │ │ │ -| , peers_with_requests | │ │ │ │ │ -| , pi, &i, m_picker.get() | │ │ │ │ │ -| , blocks_in_piece, timed_out); | │ │ │ │ │ +| rename(old_path, new_path, ec); | │ │ │ │ │ +| if (ec == boost::system::errc::no_such_file_or_directory) | │ │ │ │ │ +| ec.clear(); | │ │ │ │ │ | | │ │ │ │ │ -| // put back the peers we ignored into the peer list for the next piece | │ │ │ │ │ -| if (!ignore_peers.empty()) | │ │ │ │ │ +| if (ec) | │ │ │ │ │ | { | │ │ │ │ │ -| peers.insert(peers.begin(), ignore_peers.begin(), ignore_peers.end()); | │ │ │ │ │ -| ignore_peers.clear(); | │ │ │ │ │ -| | │ │ │ │ │ -|std::sort(peers.begin(), peers.end() | │ │ │ │ │ -|, [] (peer_connection const* lhs, peer_connection const* rhs) | │ │ │ │ │ -| { return lhs->download_queue_time(16*1024) < rhs->download_queue_time(16*1024); }); | │ │ │ │ │ +| storage_error se; | │ │ │ │ │ +| aux::copy_file(old_path, new_path, se); | │ │ │ │ │ +| ec = se.ec; | │ │ │ │ │ +| if (ec) return; | │ │ │ │ │ +| remove(old_path, ec); | │ │ │ │ │ | } | │ │ │ │ │ -| | │ │ │ │ │ -| // if this peer's download time exceeds 2 seconds, we're done. | │ │ │ │ │ -| // We don't want to build unreasonably long request queues | │ │ │ │ │ -| if (!peers.empty() && peers[0]->download_queue_time() > milliseconds(2000)) | │ │ │ │ │ -| break; | │ │ │ │ │ | } | │ │ │ │ │ +| m_path = path; | │ │ │ │ │ +|_ _}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_p_o_s_i_x___p_a_r_t___f_i_l_e_._c_p_p_:_4_2_5_|_i_n_s_t_e_a_d_ _o_f_ _r_e_b_u_i_l_d_i_n_g_ _t_h_e_ _w_h_o_l_e_ _f_i_l_e_ _h_e_a_d_e_r_ _a_n_d_ _f_l_u_s_h_i_n_g_ _i_t_,_ _u_p_d_a_t_e_ _t_h_e_ _s_l_o_t_ _e_n_t_r_i_e_s_ _a_s_ _w_e_ _g_o_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** iinnsstteeaadd ooff rreebbuuiillddiinngg tthhee wwhhoollee ffiillee hheeaaddeerr aanndd fflluusshhiinngg iitt,, uuppddaattee tthhee sslloott eennttrriieess aass wwee ggoo ********** | │ │ │ │ │ +|****** ....//ssrrcc//ppoossiixx__ppaarrtt__ffiillee..ccpppp::442255 ****** | │ │ │ │ │ +|auto bytes_read = std::fread(buf.get(), 1, std::size_t(block_to_copy), file.file()); | │ │ │ │ │ +| if (int(bytes_read) != block_to_copy) | │ │ │ │ │ +| ec.assign(errno, generic_category()); | │ │ │ │ │ | | │ │ │ │ │ -| // commit all the time critical requests | │ │ │ │ │ -| for (auto p : peers_with_requests) | │ │ │ │ │ -| { | │ │ │ │ │ -| p->send_block_requests(); | │ │ │ │ │ +| TORRENT_ASSERT(!ec); | │ │ │ │ │ +| if (ec) return; | │ │ │ │ │ +| | │ │ │ │ │ +| f(file_offset, {buf.get(), block_to_copy}); | │ │ │ │ │ +| } | │ │ │ │ │ +| file_offset += block_to_copy; | │ │ │ │ │ +| piece_offset = 0; | │ │ │ │ │ +| size -= block_to_copy; | │ │ │ │ │ | } | │ │ │ │ │ | } | │ │ │ │ │ -|#endif // TORRENT_DISABLE_STREAMING | │ │ │ │ │ | | │ │ │ │ │ -| std::set torrent::web_seeds(web_seed_entry::type_t const type) const | │ │ │ │ │ +| void posix_part_file::flush_metadata(error_code& ec) | │ │ │ │ │ | { | │ │ │ │ │ -| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ -| std::set ret; | │ │ │ │ │ -| for (auto const& s : m_web_seeds) | │ │ │ │ │ +| flush_metadata_impl(ec); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +|void posix_part_file::flush_metadata_impl(error_code& ec) | │ │ │ │ │ +|{ | │ │ │ │ │ +| // do we need to flush the metadata? | │ │ │ │ │ +| if (m_dirty_metadata == false) return; | │ │ │ │ │ +| | │ │ │ │ │ +| if (m_piece_map.empty()) | │ │ │ │ │ | { | │ │ │ │ │ -| if (s.peer_info.banned) continue; | │ │ │ │ │ -| if (s.removed) continue; | │ │ │ │ │ -| if (s.type != type) continue; | │ │ │ │ │ -| ret.insert(s.url); | │ │ │ │ │ -| } | │ │ │ │ │ -|_ _ _r_e_t_u_r_n_ _r_e_t_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_r_a_n_d_o_m_._c_p_p_:_1_4_1_ _ _ _ _ _ _ _ _ _|_i_m_p_r_o_v_e_ _c_a_l_l_i_n_g_ _R_A_N_D___b_y_t_e_s_ _m_u_l_t_i_p_l_e_ _t_i_m_e_s_,_ _u_s_i_n_g_ _f_a_l_l_b_a_c_k_ _f_o_r_ _n_o_w_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** iimmpprroovvee ccaalllliinngg RRAANNDD__bbyytteess mmuullttiippllee ttiimmeess,, uussiinngg ffaallllbbaacckk ffoorr nnooww ********** | │ │ │ │ │ -|****** ....//ssrrcc//rraannddoomm..ccpppp::114411 ****** | │ │ │ │ │ -|#else | │ │ │ │ │ -| std::generate(buffer.begin(), buffer.end(), [] { return char(random(0xff)); }); | │ │ │ │ │ -|#endif | │ │ │ │ │ +| // if we don't have any pieces left in the | │ │ │ │ │ +| // part file, remove it | │ │ │ │ │ +| std::string const p = combine_path(m_path, m_name); | │ │ │ │ │ +| remove(p, ec); | │ │ │ │ │ +| | │ │ │ │ │ +| if (ec == boost::system::errc::no_such_file_or_directory) | │ │ │ │ │ +| ec.clear(); | │ │ │ │ │ +| return; | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -| void crypto_random_bytes(span buffer) | │ │ │ │ │ -| { | │ │ │ │ │ -|#ifdef TORRENT_BUILD_SIMULATOR | │ │ │ │ │ -| // In the simulator we want deterministic random numbers | │ │ │ │ │ -| std::generate(buffer.begin(), buffer.end(), [] { return char(random(0xff)); }); | │ │ │ │ │ -|#elif TORRENT_USE_CNG | │ │ │ │ │ -| aux::cng_gen_random(buffer); | │ │ │ │ │ -|#elif TORRENT_USE_CRYPTOAPI | │ │ │ │ │ -| // windows | │ │ │ │ │ -| aux::crypt_gen_random(buffer); | │ │ │ │ │ -|#elif defined TORRENT_USE_LIBCRYPTO && !defined TORRENT_USE_WOLFSSL | │ │ │ │ │ -|// wolfSSL uses wc_RNG_GenerateBlock as the internal function for the | │ │ │ │ │ -|// openssl compatibility layer. This function API does not support | │ │ │ │ │ -|// an arbitrary buffer size (openssl does), it is limited by the | │ │ │ │ │ -|// constant RNG_MAX_BLOCK_LEN. | │ │ │ │ │ +| auto f = open_file(open_mode::read_write, ec); | │ │ │ │ │ +| if (ec) return; | │ │ │ │ │ | | │ │ │ │ │ -|// openssl | │ │ │ │ │ -| int r = RAND_bytes(reinterpret_cast(buffer.data()) | │ │ │ │ │ -| , int(buffer.size())); | │ │ │ │ │ -| if (r != 1) aux::throw_ex(errors::no_entropy); | │ │ │ │ │ -|#elif TORRENT_USE_GETRANDOM | │ │ │ │ │ -| ssize_t const r = ::getrandom(buffer.data(), static_cast(buffer.size()), 0); | │ │ │ │ │ -| if (r == ssize_t(buffer.size())) return; | │ │ │ │ │ -| if (r == -1 && errno != ENOSYS) aux::throw_ex(error_code(errno, generic_category())); | │ │ │ │ │ -| static dev_random dev; | │ │ │ │ │ -| dev.read(buffer); | │ │ │ │ │ -|#elif TORRENT_USE_DEV_RANDOM | │ │ │ │ │ -| static dev_random dev; | │ │ │ │ │ -| dev.read(buffer); | │ │ │ │ │ -|#else | │ │ │ │ │ +| std::vector header(static_cast(m_header_size)); | │ │ │ │ │ | | │ │ │ │ │ -|#if TORRENT_BROKEN_RANDOM_DEVICE | │ │ │ │ │ -| // even pseudo random numbers rely on being able to seed the random | │ │ │ │ │ -| // generator | │ │ │ │ │ -|#error "no entropy source available" | │ │ │ │ │ -|#else | │ │ │ │ │ -|#ifdef TORRENT_I_WANT_INSECURE_RANDOM_NUMBERS | │ │ │ │ │ -| std::generate(buffer.begin(), buffer.end(), [] { return char(random(0xff)); }); | │ │ │ │ │ -|#else | │ │ │ │ │ -|#error "no secure entropy source available. If you really want insecure random numbers, define TORRENT_I_WANT_INSECURE_RANDOM_NUMBERS" | │ │ │ │ │ -|#endif | │ │ │ │ │ -|#endif | │ │ │ │ │ +| using namespace libtorrent::aux; | │ │ │ │ │ | | │ │ │ │ │ -|#endif | │ │ │ │ │ -| } | │ │ │ │ │ -|_}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +| char* ptr = header.data(); | │ │ │ │ │ +| write_uint32(m_max_pieces, ptr); | │ │ │ │ │ +| write_uint32(m_piece_size, ptr); | │ │ │ │ │ +| | │ │ │ │ │ +| for (piece_index_t piece(0); piece < piece_index_t(m_max_pieces); ++piece) | │ │ │ │ │ +| { | │ │ │ │ │ +|_ _ _ _a_u_t_o_ _c_o_n_s_t_ _i_ _=_ _m___p_i_e_c_e___m_a_p_._f_i_n_d_(_p_i_e_c_e_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_s_e_s_s_i_o_n___i_m_p_l_._c_p_p_:_6_1_5_ _ _ _|_c_o_m_e_ _u_p_ _w_i_t_h_ _s_o_m_e_ _a_b_s_t_r_a_c_t_i_o_n_ _t_o_ _d_o_ _t_h_i_s_ _f_o_r_ _g_n_u_t_l_s_ _a_s_ _w_e_l_l_ _l_o_a_d_ _c_e_r_t_i_f_i_c_a_t_e_s_ _f_r_o_m_ _t_h_e_ _w_i_n_d_o_w_s_ _s_y_s_t_e_m_ _c_e_r_t_i_f_i_c_a_t_e_ _s_t_o_r_e_ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** ccoommee uupp wwiitthh ssoommee aabbssttrraaccttiioonn ttoo ddoo tthhiiss ffoorr ggnnuuttllss aass wweellll llooaadd cceerrttiiffiiccaatteess ffrroomm tthhee wwiinnddoowwss ssyysstteemm cceerrttiiffiiccaattee ssttoorree ********** | │ │ │ │ │ |****** ....//ssrrcc//sseessssiioonn__iimmppll..ccpppp::661155 ****** | │ │ │ │ │ |pause(); | │ │ │ │ │ | } | │ │ │ │ │ |#endif | │ │ │ │ │ | | │ │ │ │ │ @@ -10087,14 +8421,945 @@ │ │ │ │ │ | for (wakeup_t const& w : _wakeups) | │ │ │ │ │ | { | │ │ │ │ │ | bool const idle_wakeup = w.context_switches > prev_csw; | │ │ │ │ │ | std::fprintf(f, "%" PRId64 "\t%" PRId64 "\t%" PRId64 "\t%c\t%s\n" | │ │ │ │ │ | , total_microseconds(w.timestamp - m) | │ │ │ │ │ | , total_microseconds(w.timestamp - prev) | │ │ │ │ │ |_ _ _ _ _ _,_ _w_._c_o_n_t_e_x_t___s_w_i_t_c_h_e_s_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_l_o_a_d___t_o_r_r_e_n_t_._c_p_p_:_1_2_1_ _ _ _|_m_o_v_e_ _t_h_e_ _l_o_a_d_i_n_g_ _l_o_g_i_c_ _f_r_o_m_ _t_o_r_r_e_n_t___i_n_f_o_ _c_o_n_s_t_r_u_c_t_o_r_ _i_n_t_o_ _h_e_r_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** mmoovvee tthhee llooaaddiinngg llooggiicc ffrroomm ttoorrrreenntt__iinnffoo ccoonnssttrruuccttoorr iinnttoo hheerree ********** | │ │ │ │ │ +|****** ....//ssrrcc//llooaadd__ttoorrrreenntt..ccpppp::112211 ****** | │ │ │ │ │ +|mask.resize(std::size_t(full_size), false); | │ │ │ │ │ +| for (int i = merkle_first_leaf(piece_layer_size) | │ │ │ │ │ +| , end = i + num_pieces; i < end; ++i) | │ │ │ │ │ +| { | │ │ │ │ │ +| mask[std::size_t(i)] = true; | │ │ │ │ │ +| } | │ │ │ │ │ +| } | │ │ │ │ │ +| ti->free_piece_layers(); | │ │ │ │ │ +| } | │ │ │ │ │ +| atp.info_hashes = atp.ti->info_hashes(); | │ │ │ │ │ +| } | │ │ │ │ │ +|} | │ │ │ │ │ +| | │ │ │ │ │ +| add_torrent_params load_torrent_file(std::string const& filename) | │ │ │ │ │ +| { return load_torrent_file(filename, load_torrent_limits{}); } | │ │ │ │ │ +| add_torrent_params load_torrent_buffer(span buffer) | │ │ │ │ │ +| { return load_torrent_buffer(buffer, load_torrent_limits{}); } | │ │ │ │ │ +| add_torrent_params load_torrent_parsed(bdecode_node const& torrent_file) | │ │ │ │ │ +| { return load_torrent_parsed(torrent_file, load_torrent_limits{}); } | │ │ │ │ │ +| | │ │ │ │ │ +|add_torrent_params load_torrent_file(std::string const& filename, load_torrent_limits const& cfg) | │ │ │ │ │ +|{ | │ │ │ │ │ +| add_torrent_params ret; | │ │ │ │ │ +| ret.ti = std::make_shared(filename, cfg); | │ │ │ │ │ +| update_atp(ret); | │ │ │ │ │ +| return ret; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| add_torrent_params load_torrent_buffer(span buffer, load_torrent_limits const& cfg) | │ │ │ │ │ +| { | │ │ │ │ │ +| add_torrent_params ret; | │ │ │ │ │ +| ret.ti = std::make_shared(buffer, cfg, from_span); | │ │ │ │ │ +| update_atp(ret); | │ │ │ │ │ +| return ret; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| add_torrent_params load_torrent_parsed(bdecode_node const& torrent_file, load_torrent_limits const& cfg) | │ │ │ │ │ +| { | │ │ │ │ │ +| add_torrent_params ret; | │ │ │ │ │ +| ret.ti = std::make_shared(torrent_file, cfg); | │ │ │ │ │ +| update_atp(ret); | │ │ │ │ │ +| return ret; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +|_}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_c_p_u_i_d_._c_p_p_:_1_3_1_ _ _ _ _ _ _ _ _ _ _|_e_n_a_b_l_e_ _w_h_e_n_ _a_a_r_c_h_6_4_ _i_s_ _r_e_a_l_l_y_ _t_e_s_t_e_d_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** eennaabbllee wwhheenn aaaarrcchh6644 iiss rreeaallllyy tteesstteedd ********** | │ │ │ │ │ +|****** ....//ssrrcc//ccppuuiidd..ccpppp::113311 ****** | │ │ │ │ │ +|bool supports_mmx() noexcept | │ │ │ │ │ +| { | │ │ │ │ │ +|#if TORRENT_HAS_SSE | │ │ │ │ │ +| std::uint32_t cpui[4] = {0}; | │ │ │ │ │ +| cpuid(cpui, 1); | │ │ │ │ │ +| return (cpui[2] & (1 << 23)) != 0; | │ │ │ │ │ +|#else | │ │ │ │ │ +| return false; | │ │ │ │ │ +|#endif | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| bool supports_arm_neon() noexcept | │ │ │ │ │ +| { | │ │ │ │ │ +|#if TORRENT_HAS_ARM_NEON && TORRENT_HAS_AUXV | │ │ │ │ │ +|#if defined __arm__ | │ │ │ │ │ +| //return (getauxval(AT_HWCAP) & HWCAP_NEON); | │ │ │ │ │ +| return (helper_getauxval(16) & (1 << 12)); | │ │ │ │ │ +|#elif defined __aarch64__ | │ │ │ │ │ +| //return (getauxval(AT_HWCAP) & HWCAP_ASIMD); | │ │ │ │ │ +| //return (getauxval(16) & (1 << 1)); | │ │ │ │ │ +|return false; | │ │ │ │ │ +|#endif | │ │ │ │ │ +|#else | │ │ │ │ │ +| return false; | │ │ │ │ │ +|#endif | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| bool supports_arm_crc32c() noexcept | │ │ │ │ │ +| { | │ │ │ │ │ +|#if TORRENT_HAS_ARM_CRC32 && TORRENT_HAS_AUXV | │ │ │ │ │ +|#if defined TORRENT_FORCE_ARM_CRC32 | │ │ │ │ │ +| return true; | │ │ │ │ │ +|#elif defined __arm__ | │ │ │ │ │ +| //return (getauxval(AT_HWCAP2) & HWCAP2_CRC32); | │ │ │ │ │ +| return (helper_getauxval(26) & (1 << 4)); | │ │ │ │ │ +|#elif defined __aarch64__ | │ │ │ │ │ +| //return (getauxval(AT_HWCAP) & HWCAP_CRC32); | │ │ │ │ │ +| return (helper_getauxval(16) & (1 << 7)); | │ │ │ │ │ +|#endif | │ │ │ │ │ +|#else | │ │ │ │ │ +| return false; | │ │ │ │ │ +|#endif | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +|} // anonymous namespace | │ │ │ │ │ +| | │ │ │ │ │ +| bool const sse42_support = supports_sse42(); | │ │ │ │ │ +| bool const mmx_support = supports_mmx(); | │ │ │ │ │ +| bool const arm_neon_support = supports_arm_neon(); | │ │ │ │ │ +| bool const arm_crc32c_support = supports_arm_crc32c(); | │ │ │ │ │ +|_}_ _}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_t_o_r_r_e_n_t___i_n_f_o_._c_p_p_:_8_7_5_ _ _ _|_t_h_i_s_ _s_h_o_u_l_d_ _b_e_ _c_o_n_s_i_d_e_r_e_d_ _a_ _f_a_i_l_u_r_e_,_ _a_n_d_ _t_h_e_ _._t_o_r_r_e_n_t_ _f_i_l_e_ _r_e_j_e_c_t_e_d_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tthhiiss sshhoouulldd bbee ccoonnssiiddeerreedd aa ffaaiilluurree,, aanndd tthhee ..ttoorrrreenntt ffiillee rreejjeecctteedd ********** | │ │ │ │ │ +|****** ....//ssrrcc//ttoorrrreenntt__iinnffoo..ccpppp::887755 ****** | │ │ │ │ │ +|std::string ext = extension(filename); | │ │ │ │ │ +| int cnt = 0; | │ │ │ │ │ +| for (;;) | │ │ │ │ │ +| { | │ │ │ │ │ +| ++cnt; | │ │ │ │ │ +| char new_ext[50]; | │ │ │ │ │ +| std::snprintf(new_ext, sizeof(new_ext), ".%d%s", cnt, ext.c_str()); | │ │ │ │ │ +| filename = base + new_ext; | │ │ │ │ │ +| | │ │ │ │ │ +| boost::crc_optimal<32, 0x1EDC6F41, 0xFFFFFFFF, 0xFFFFFFFF, true, true> crc; | │ │ │ │ │ +| process_string_lowercase(crc, filename); | │ │ │ │ │ +| std::uint32_t const new_hash = crc.checksum(); | │ │ │ │ │ +| if (files.find(new_hash) == files.end()) | │ │ │ │ │ +| { | │ │ │ │ │ +| files.insert({new_hash, {i, 0}}); | │ │ │ │ │ +| break; | │ │ │ │ │ +| } | │ │ │ │ │ +| ++num_collisions; | │ │ │ │ │ +| if (num_collisions > 100) | │ │ │ │ │ +| { | │ │ │ │ │ +|} | │ │ │ │ │ +|} | │ │ │ │ │ +| | │ │ │ │ │ +| copy_on_write(); | │ │ │ │ │ +| m_files.rename_file(i, filename); | │ │ │ │ │ +| } | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| void torrent_info::remap_files(file_storage const& f) | │ │ │ │ │ +| { | │ │ │ │ │ +| INVARIANT_CHECK; | │ │ │ │ │ +| | │ │ │ │ │ +| TORRENT_ASSERT(is_loaded()); | │ │ │ │ │ +| // the new specified file storage must have the exact | │ │ │ │ │ +| // same size as the current file storage | │ │ │ │ │ +| TORRENT_ASSERT(m_files.total_size() == f.total_size()); | │ │ │ │ │ +| | │ │ │ │ │ +| if (m_files.total_size() != f.total_size()) return; | │ │ │ │ │ +| copy_on_write(); | │ │ │ │ │ +| m_files = f; | │ │ │ │ │ +| m_files.set_num_pieces(m_orig_files->num_pieces()); | │ │ │ │ │ +| m_files.set_piece_length(m_orig_files->piece_length()); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +|#if TORRENT_ABI_VERSION == 1 | │ │ │ │ │ +| // standard constructor that parses a torrent file | │ │ │ │ │ +| torrent_info::torrent_info(entry const& torrent_file) | │ │ │ │ │ +| { | │ │ │ │ │ +| std::vector tmp; | │ │ │ │ │ +| std::back_insert_iterator> out(tmp); | │ │ │ │ │ +|_ _ _b_e_n_c_o_d_e_(_o_u_t_,_ _t_o_r_r_e_n_t___f_i_l_e_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_s_e_t_t_i_n_g_s___p_a_c_k_._c_p_p_:_3_0_5_ _ _|_d_e_p_r_e_c_a_t_e_ _t_h_i_s_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** ddeepprreeccaattee tthhiiss ********** | │ │ │ │ │ +|****** ....//ssrrcc//sseettttiinnggss__ppaacckk..ccpppp::330055 ****** | │ │ │ │ │ +|SET(outgoing_port, 0, nullptr), | │ │ │ │ │ +| SET(num_outgoing_ports, 0, nullptr), | │ │ │ │ │ +| SET(peer_dscp, 0x04, &session_impl::update_peer_dscp), | │ │ │ │ │ +| SET(active_downloads, 3, &session_impl::trigger_auto_manage), | │ │ │ │ │ +| SET(active_seeds, 5, &session_impl::trigger_auto_manage), | │ │ │ │ │ +| SET(active_checking, 1, &session_impl::trigger_auto_manage), | │ │ │ │ │ +| SET(active_dht_limit, 88, nullptr), | │ │ │ │ │ +| SET(active_tracker_limit, 1600, nullptr), | │ │ │ │ │ +| SET(active_lsd_limit, 60, nullptr), | │ │ │ │ │ +| SET(active_limit, 500, &session_impl::trigger_auto_manage), | │ │ │ │ │ +| DEPRECATED_SET(active_loaded_limit, 0, &session_impl::trigger_auto_manage), | │ │ │ │ │ +| SET(auto_manage_interval, 30, nullptr), | │ │ │ │ │ +| SET(seed_time_limit, 24 * 60 * 60, nullptr), | │ │ │ │ │ +| SET(auto_scrape_interval, 1800, nullptr), | │ │ │ │ │ +| SET(auto_scrape_min_interval, 300, nullptr), | │ │ │ │ │ +| SET(max_peerlist_size, 3000, nullptr), | │ │ │ │ │ +| SET(max_paused_peerlist_size, 1000, nullptr), | │ │ │ │ │ +| SET(min_announce_interval, 5 * 60, nullptr), | │ │ │ │ │ +| SET(auto_manage_startup, 60, nullptr), | │ │ │ │ │ +| SET(seeding_piece_quota, 20, nullptr), | │ │ │ │ │ +|SET(max_rejects, 50, nullptr), | │ │ │ │ │ +|SET(recv_socket_buffer_size, 0, &session_impl::update_socket_buffer_size), | │ │ │ │ │ +| SET(send_socket_buffer_size, 0, &session_impl::update_socket_buffer_size), | │ │ │ │ │ +| SET(max_peer_recv_buffer_size, 2 * 1024 * 1024, nullptr), | │ │ │ │ │ +| DEPRECATED_SET(file_checks_delay_per_block, 0, nullptr), | │ │ │ │ │ +| DEPRECATED2_SET(read_cache_line_size, 32, nullptr), | │ │ │ │ │ +| DEPRECATED2_SET(write_cache_line_size, 16, nullptr), | │ │ │ │ │ +| SET(optimistic_disk_retry, 10 * 60, nullptr), | │ │ │ │ │ +| SET(max_suggest_pieces, 16, nullptr), | │ │ │ │ │ +| SET(local_service_announce_interval, 5 * 60, nullptr), | │ │ │ │ │ +| SET(dht_announce_interval, 15 * 60, &session_impl::update_dht_announce_interval), | │ │ │ │ │ +| SET(udp_tracker_token_expiry, 60, nullptr), | │ │ │ │ │ +| DEPRECATED_SET(default_cache_min_age, 1, nullptr), | │ │ │ │ │ +| SET(num_optimistic_unchoke_slots, 0, nullptr), | │ │ │ │ │ +| DEPRECATED_SET(default_est_reciprocation_rate, 16000, nullptr), | │ │ │ │ │ +| DEPRECATED_SET(increase_est_reciprocation_rate, 20, nullptr), | │ │ │ │ │ +| DEPRECATED_SET(decrease_est_reciprocation_rate, 3, nullptr), | │ │ │ │ │ +| SET(max_pex_peers, 50, nullptr), | │ │ │ │ │ +| SET(tick_interval, 500, nullptr), | │ │ │ │ │ +| SET(share_mode_target, 3, nullptr), | │ │ │ │ │ +| SET(upload_rate_limit, 0, &session_impl::update_upload_rate), | │ │ │ │ │ +| SET(download_rate_limit, 0, &session_impl::update_download_rate), | │ │ │ │ │ +| DEPRECATED_SET(local_upload_rate_limit, 0, &session_impl::update_local_upload_rate), | │ │ │ │ │ +| DEPRECATED_SET(local_download_rate_limit, 0, &session_impl::update_local_download_rate), | │ │ │ │ │ +| SET(dht_upload_rate_limit, 8000, &session_impl::update_dht_upload_rate_limit), | │ │ │ │ │ +| SET(unchoke_slots_limit, 8, &session_impl::update_unchoke_limit), | │ │ │ │ │ +| DEPRECATED_SET(half_open_limit, 0, nullptr), | │ │ │ │ │ +| SET(connections_limit, 200, &session_impl::update_connections_limit), | │ │ │ │ │ +| SET(connections_slack, 10, nullptr), | │ │ │ │ │ +| SET(utp_target_delay, 100, nullptr), | │ │ │ │ │ +|_ _ _S_E_T_(_u_t_p___g_a_i_n___f_a_c_t_o_r_,_ _3_0_0_0_,_ _n_u_l_l_p_t_r_)_,_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_s_e_t_t_i_n_g_s___p_a_c_k_._c_p_p_:_5_8_9_ _ _|_i_t_ _w_o_u_l_d_ _b_e_ _n_i_c_e_ _t_o_ _r_e_s_e_r_v_e_(_)_ _t_h_e_s_e_ _v_e_c_t_o_r_s_ _u_p_ _f_r_o_n_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** iitt wwoouulldd bbee nniiccee ttoo rreesseerrvvee(()) tthheessee vveeccttoorrss uupp ffrroonntt ********** | │ │ │ │ │ +|****** ....//ssrrcc//sseettttiinnggss__ppaacckk..ccpppp::558899 ****** | │ │ │ │ │ +|s.set_str(settings_pack::string_type_base | i, str_settings[i].default_value); | │ │ │ │ │ +| TORRENT_ASSERT(s.get_str(settings_pack::string_type_base + i) == str_settings[i].default_value); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| for (int i = 0; i < settings_pack::num_int_settings; ++i) | │ │ │ │ │ +| { | │ │ │ │ │ +| s.set_int(settings_pack::int_type_base | i, int_settings[i].default_value); | │ │ │ │ │ +| TORRENT_ASSERT(s.get_int(settings_pack::int_type_base + i) == int_settings[i].default_value); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| for (int i = 0; i < settings_pack::num_bool_settings; ++i) | │ │ │ │ │ +| { | │ │ │ │ │ +| s.set_bool(settings_pack::bool_type_base | i, bool_settings[i].default_value); | │ │ │ │ │ +| TORRENT_ASSERT(s.get_bool(settings_pack::bool_type_base + i) == bool_settings[i].default_value); | │ │ │ │ │ +| } | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| settings_pack default_settings() | │ │ │ │ │ +| { | │ │ │ │ │ +| settings_pack ret; | │ │ │ │ │ +|for (int i = 0; i < settings_pack::num_string_settings; ++i) | │ │ │ │ │ +|{ | │ │ │ │ │ +| if (str_settings[i].default_value == nullptr) continue; | │ │ │ │ │ +| ret.set_str(settings_pack::string_type_base + i, str_settings[i].default_value); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| for (int i = 0; i < settings_pack::num_int_settings; ++i) | │ │ │ │ │ +| { | │ │ │ │ │ +| ret.set_int(settings_pack::int_type_base + i, int_settings[i].default_value); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| for (int i = 0; i < settings_pack::num_bool_settings; ++i) | │ │ │ │ │ +| { | │ │ │ │ │ +| ret.set_bool(settings_pack::bool_type_base + i, bool_settings[i].default_value); | │ │ │ │ │ +| } | │ │ │ │ │ +| return ret; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| void apply_pack(settings_pack const* pack, aux::session_settings& sett | │ │ │ │ │ +| , aux::session_impl* ses) | │ │ │ │ │ +| { | │ │ │ │ │ +| using fun_t = void (aux::session_impl::*)(); | │ │ │ │ │ +| std::vector callbacks; | │ │ │ │ │ +| | │ │ │ │ │ +| sett.bulk_set([&](aux::session_settings_single_thread& s) | │ │ │ │ │ +| { | │ │ │ │ │ +| apply_pack_impl(pack, s, ses ? &callbacks : nullptr); | │ │ │ │ │ +| }); | │ │ │ │ │ +| | │ │ │ │ │ +| // call the callbacks once all the settings have been applied, and | │ │ │ │ │ +|_ _ _/_/_ _o_n_l_y_ _o_n_c_e_ _p_e_r_ _c_a_l_l_b_a_c_k_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_u_d_p___s_o_c_k_e_t_._c_p_p_:_6_5_9_ _ _ _ _ _|_p_e_r_h_a_p_s_ _a_n_ _a_t_t_e_m_p_t_ _s_h_o_u_l_d_ _b_e_ _m_a_d_e_ _t_o_ _b_i_n_d_ _m___s_o_c_k_s_5___s_o_c_k_ _t_o_ _t_h_e_ _d_e_v_i_c_e_ _o_f_ _m___l_i_s_t_e_n___s_o_c_k_e_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** ppeerrhhaappss aann aatttteemmpptt sshhoouulldd bbee mmaaddee ttoo bbiinndd mm__ssoocckkss55__ssoocckk ttoo tthhee ddeevviiccee ooff mm__lliisstteenn__ssoocckkeett ********** | │ │ │ │ │ +|****** ....//ssrrcc//uuddpp__ssoocckkeett..ccpppp::665599 ****** | │ │ │ │ │ +|if (ec) | │ │ │ │ │ +| { | │ │ │ │ │ +| if (m_alerts.should_post()) | │ │ │ │ │ +| m_alerts.emplace_alert(m_proxy_addr, operation_t::sock_option, ec); | │ │ │ │ │ +| ec.clear(); | │ │ │ │ │ +| } | │ │ │ │ │ +|#endif | │ │ │ │ │ +|#endif | │ │ │ │ │ +| | │ │ │ │ │ +| tcp::endpoint const bind_ep(m_listen_socket.get_local_endpoint().address(), 0); | │ │ │ │ │ +| m_socks5_sock.bind(bind_ep, ec); | │ │ │ │ │ +| if (ec) | │ │ │ │ │ +| { | │ │ │ │ │ +| if (m_alerts.should_post()) | │ │ │ │ │ +| m_alerts.emplace_alert(m_proxy_addr, operation_t::sock_bind, ec); | │ │ │ │ │ +| ++m_failures; | │ │ │ │ │ +| retry_connection(); | │ │ │ │ │ +| return; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| | │ │ │ │ │ +|ADD_OUTSTANDING_ASYNC("socks5::on_connected"); | │ │ │ │ │ +| m_socks5_sock.async_connect(m_proxy_addr | │ │ │ │ │ +| , std::bind(&socks5::on_connected, self(), _1)); | │ │ │ │ │ +| | │ │ │ │ │ +| ADD_OUTSTANDING_ASYNC("socks5::on_connect_timeout"); | │ │ │ │ │ +| m_timer.expires_after(seconds(10)); | │ │ │ │ │ +| m_timer.async_wait(std::bind(&socks5::on_connect_timeout | │ │ │ │ │ +| , self(), _1)); | │ │ │ │ │ +|} | │ │ │ │ │ +| | │ │ │ │ │ +|void socks5::on_connect_timeout(error_code const& e) | │ │ │ │ │ +|{ | │ │ │ │ │ +| COMPLETE_ASYNC("socks5::on_connect_timeout"); | │ │ │ │ │ +| | │ │ │ │ │ +| if (e == boost::asio::error::operation_aborted) return; | │ │ │ │ │ +| | │ │ │ │ │ +| if (m_abort) return; | │ │ │ │ │ +| | │ │ │ │ │ +| if (m_alerts.should_post()) | │ │ │ │ │ +| m_alerts.emplace_alert(m_proxy_addr, operation_t::connect, errors::timed_out); | │ │ │ │ │ +| | │ │ │ │ │ +| error_code ignore; | │ │ │ │ │ +| m_socks5_sock.close(ignore); | │ │ │ │ │ +| | │ │ │ │ │ +| ++m_failures; | │ │ │ │ │ +| retry_connection(); | │ │ │ │ │ +|} | │ │ │ │ │ +| | │ │ │ │ │ +|void socks5::on_connected(error_code const& e) | │ │ │ │ │ +|_{_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_t_o_r_r_e_n_t_._c_p_p_:_1_9_4_1_ _ _ _ _ _ _ _|_t_h_i_s_ _c_o_u_l_d_ _b_e_ _o_p_t_i_m_i_z_e_d_ _b_y_ _l_o_o_k_i_n_g_ _u_p_ _w_h_i_c_h_ _f_i_l_e_s_ _a_r_e_ _c_o_m_p_l_e_t_e_ _a_n_d_ _j_u_s_t_ _l_o_o_k_ _a_t_ _t_h_o_s_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tthhiiss ccoouulldd bbee ooppttiimmiizzeedd bbyy llooookkiinngg uupp wwhhiicchh ffiilleess aarree ccoommpplleettee aanndd jjuusstt llooookk aatt tthhoossee ********** | │ │ │ │ │ +|****** ....//ssrrcc//ttoorrrreenntt..ccpppp::11994411 ****** | │ │ │ │ │ +|// TORRENT_ASSERT(picker().have_piece(i)); | │ │ │ │ │ +| we_have(i); | │ │ │ │ │ +| } | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| set_state(torrent_status::checking_resume_data); | │ │ │ │ │ +| | │ │ │ │ │ +| aux::vector links; | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_MUTABLE_TORRENTS | │ │ │ │ │ +| if (!m_torrent_file->similar_torrents().empty() | │ │ │ │ │ +| || !m_torrent_file->collections().empty()) | │ │ │ │ │ +| { | │ │ │ │ │ +| resolve_links res(m_torrent_file); | │ │ │ │ │ +| | │ │ │ │ │ +| for (auto const& ih : m_torrent_file->similar_torrents()) | │ │ │ │ │ +| { | │ │ │ │ │ +| std::shared_ptr t = m_ses.find_torrent(info_hash_t(ih)).lock(); | │ │ │ │ │ +| if (!t) continue; | │ │ │ │ │ +| | │ │ │ │ │ +| // Only attempt to reuse files from torrents that are seeding. | │ │ │ │ │ +|if (!t->is_seed()) continue; | │ │ │ │ │ +| | │ │ │ │ │ +| res.match(t->get_torrent_file(), t->save_path()); | │ │ │ │ │ +| } | │ │ │ │ │ +| for (auto const& c : m_torrent_file->collections()) | │ │ │ │ │ +| { | │ │ │ │ │ +| std::vector> ts = m_ses.find_collection(c); | │ │ │ │ │ +| | │ │ │ │ │ +| for (auto const& t : ts) | │ │ │ │ │ +| { | │ │ │ │ │ +|_ _ _ _ _ _/_/_ _O_n_l_y_ _a_t_t_e_m_p_t_ _t_o_ _r_e_u_s_e_ _f_i_l_e_s_ _f_r_o_m_ _t_o_r_r_e_n_t_s_ _t_h_a_t_ _a_r_e_ _s_e_e_d_i_n_g_._ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_t_o_r_r_e_n_t_._c_p_p_:_1_9_5_4_ _ _ _ _ _ _ _|_t_h_i_s_ _c_o_u_l_d_ _b_e_ _o_p_t_i_m_i_z_e_d_ _b_y_ _l_o_o_k_i_n_g_ _u_p_ _w_h_i_c_h_ _f_i_l_e_s_ _a_r_e_ _c_o_m_p_l_e_t_e_ _a_n_d_ _j_u_s_t_ _l_o_o_k_ _a_t_ _t_h_o_s_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tthhiiss ccoouulldd bbee ooppttiimmiizzeedd bbyy llooookkiinngg uupp wwhhiicchh ffiilleess aarree ccoommpplleettee aanndd jjuusstt llooookk aatt tthhoossee ********** | │ │ │ │ │ +|****** ....//ssrrcc//ttoorrrreenntt..ccpppp::11995544 ****** | │ │ │ │ │ +|{ | │ │ │ │ │ +| resolve_links res(m_torrent_file); | │ │ │ │ │ +| | │ │ │ │ │ +| for (auto const& ih : m_torrent_file->similar_torrents()) | │ │ │ │ │ +| { | │ │ │ │ │ +| std::shared_ptr t = m_ses.find_torrent(info_hash_t(ih)).lock(); | │ │ │ │ │ +| if (!t) continue; | │ │ │ │ │ +| | │ │ │ │ │ +| // Only attempt to reuse files from torrents that are seeding. | │ │ │ │ │ +| if (!t->is_seed()) continue; | │ │ │ │ │ +| | │ │ │ │ │ +| res.match(t->get_torrent_file(), t->save_path()); | │ │ │ │ │ +| } | │ │ │ │ │ +| for (auto const& c : m_torrent_file->collections()) | │ │ │ │ │ +| { | │ │ │ │ │ +| std::vector> ts = m_ses.find_collection(c); | │ │ │ │ │ +| | │ │ │ │ │ +| for (auto const& t : ts) | │ │ │ │ │ +| { | │ │ │ │ │ +| // Only attempt to reuse files from torrents that are seeding. | │ │ │ │ │ +|if (!t->is_seed()) continue; | │ │ │ │ │ +| | │ │ │ │ │ +| res.match(t->get_torrent_file(), t->save_path()); | │ │ │ │ │ +| } | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| std::vector const& l = res.get_links(); | │ │ │ │ │ +| if (!l.empty()) | │ │ │ │ │ +| { | │ │ │ │ │ +| links.resize(m_torrent_file->files().num_files()); | │ │ │ │ │ +| for (auto const& i : l) | │ │ │ │ │ +| { | │ │ │ │ │ +| if (!i.ti) continue; | │ │ │ │ │ +| links[i.file_idx] = combine_path(i.save_path | │ │ │ │ │ +| , i.ti->files().file_path(i.file_idx)); | │ │ │ │ │ +| } | │ │ │ │ │ +| } | │ │ │ │ │ +| } | │ │ │ │ │ +|#endif // TORRENT_DISABLE_MUTABLE_TORRENTS | │ │ │ │ │ +| | │ │ │ │ │ +|#if TORRENT_USE_ASSERTS | │ │ │ │ │ +| TORRENT_ASSERT(m_outstanding_check_files == false); | │ │ │ │ │ +| m_outstanding_check_files = true; | │ │ │ │ │ +|#endif | │ │ │ │ │ +| | │ │ │ │ │ +| if (!m_add_torrent_params || !(m_add_torrent_params->flags & torrent_flags::no_verify_files)) | │ │ │ │ │ +| { | │ │ │ │ │ +| m_ses.disk_thread().async_check_files( | │ │ │ │ │ +| m_storage, m_add_torrent_params ? m_add_torrent_params.get() : nullptr | │ │ │ │ │ +| , std::move(links), [self = shared_from_this()](status_t st, storage_error const& error) | │ │ │ │ │ +|_ _ _ _ _{_ _s_e_l_f_-_>_o_n___r_e_s_u_m_e___d_a_t_a___c_h_e_c_k_e_d_(_s_t_,_ _e_r_r_o_r_)_;_ _}_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_s_r_c_/_t_o_r_r_e_n_t_._c_p_p_:_2_7_1_5 |this pattern is repeated in a few places. Factor this into a function and generalize the concept of a torrent having a dedicated | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_l_i_s_t_e_n_ _p_o_r_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tthhiiss ppaatttteerrnn iiss rreeppeeaatteedd iinn aa ffeeww ppllaacceess.. FFaaccttoorr tthhiiss iinnttoo aa ffuunnccttiioonn aanndd ggeenneerraalliizzee tthhee ccoonncceepptt ooff aa ttoorrrreenntt hhaavviinngg aa ddeeddiiccaatteedd lliisstteenn ppoorrtt ********** | │ │ │ │ │ +|****** ....//ssrrcc//ttoorrrreenntt..ccpppp::22771155 ****** | │ │ │ │ │ +|// not ready for peers. Except, if we don't have metadata, | │ │ │ │ │ +| // we need peers to download from | │ │ │ │ │ +| if (!m_files_checked && valid_metadata()) return; | │ │ │ │ │ +| | │ │ │ │ │ +| if (!m_announce_to_lsd) return; | │ │ │ │ │ +| | │ │ │ │ │ +| // private torrents are never announced on LSD | │ │ │ │ │ +| if (m_torrent_file->is_valid() && m_torrent_file->priv()) return; | │ │ │ │ │ +| | │ │ │ │ │ +|#if TORRENT_USE_I2P | │ │ │ │ │ +| // i2p torrents are also never announced on LSD | │ │ │ │ │ +| // unless we allow mixed swarms | │ │ │ │ │ +| if (is_i2p() && !settings().get_bool(settings_pack::allow_i2p_mixed)) | │ │ │ │ │ +| return; | │ │ │ │ │ +|#endif | │ │ │ │ │ +| | │ │ │ │ │ +| if (is_paused()) return; | │ │ │ │ │ +| | │ │ │ │ │ +| if (!m_ses.has_lsd()) return; | │ │ │ │ │ +| | │ │ │ │ │ +|#ifdef TORRENT_SSL_PEERS | │ │ │ │ │ +|int port = is_ssl_torrent() ? m_ses.ssl_listen_port() : m_ses.listen_port(); | │ │ │ │ │ +|#else | │ │ │ │ │ +| int port = m_ses.listen_port(); | │ │ │ │ │ +|#endif | │ │ │ │ │ +| | │ │ │ │ │ +| // announce with the local discovery service | │ │ │ │ │ +| m_torrent_file->info_hashes().for_each([&](sha1_hash const& ih, protocol_version) | │ │ │ │ │ +| { | │ │ │ │ │ +| m_ses.announce_lsd(ih, port); | │ │ │ │ │ +| }); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_DHT | │ │ │ │ │ +| | │ │ │ │ │ +| void torrent::dht_announce() | │ │ │ │ │ +| { | │ │ │ │ │ +| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ +| if (!m_ses.dht()) | │ │ │ │ │ +| { | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ +| debug_log("DHT: no dht initialized"); | │ │ │ │ │ +|#endif | │ │ │ │ │ +| return; | │ │ │ │ │ +| } | │ │ │ │ │ +| if (!should_announce_dht()) | │ │ │ │ │ +| { | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ +| if (should_log()) | │ │ │ │ │ +| { | │ │ │ │ │ +|_#_i_f_ _T_O_R_R_E_N_T___U_S_E___I_2_P_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_t_o_r_r_e_n_t_._c_p_p_:_3_8_7_0_ _ _ _ _ _ _ _|_a_d_d_ _o_n_e_ _p_e_e_r_ _p_e_r_ _I_P_ _t_h_e_ _h_o_s_t_n_a_m_e_ _r_e_s_o_l_v_e_s_ _t_o_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** aadddd oonnee ppeeeerr ppeerr IIPP tthhee hhoossttnnaammee rreessoollvveess ttoo ********** | │ │ │ │ │ +|****** ....//ssrrcc//ttoorrrreenntt..ccpppp::33887700 ****** | │ │ │ │ │ +|catch (...) { handle_exception(); } | │ │ │ │ │ +|#endif | │ │ │ │ │ +| | │ │ │ │ │ +| void torrent::on_peer_name_lookup(error_code const& e | │ │ │ │ │ +| , std::vector
    const& host_list, int const port | │ │ │ │ │ +| , protocol_version const v) try | │ │ │ │ │ +| { | │ │ │ │ │ +| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ +| | │ │ │ │ │ +| INVARIANT_CHECK; | │ │ │ │ │ +| | │ │ │ │ │ +| COMPLETE_ASYNC("torrent::on_peer_name_lookup"); | │ │ │ │ │ +| | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ +| if (e && should_log()) | │ │ │ │ │ +| debug_log("peer name lookup error: %s", e.message().c_str()); | │ │ │ │ │ +|#endif | │ │ │ │ │ +| | │ │ │ │ │ +| if (e || m_abort || host_list.empty() || m_ses.is_aborted()) return; | │ │ │ │ │ +| | │ │ │ │ │ +|tcp::endpoint host(host_list.front(), std::uint16_t(port)); | │ │ │ │ │ +| | │ │ │ │ │ +| if (m_ip_filter && m_ip_filter->access(host.address()) & ip_filter::blocked) | │ │ │ │ │ +| { | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ +| if (should_log()) | │ │ │ │ │ +| { | │ │ │ │ │ +| debug_log("blocked ip from tracker: %s", host.address().to_string().c_str()); | │ │ │ │ │ +| } | │ │ │ │ │ +|#endif | │ │ │ │ │ +| if (m_ses.alerts().should_post()) | │ │ │ │ │ +| m_ses.alerts().emplace_alert(get_handle() | │ │ │ │ │ +| , host, peer_blocked_alert::ip_filter); | │ │ │ │ │ +| return; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| if (add_peer(host, peer_info::tracker, v == protocol_version::V2 ? pex_lt_v2 : pex_flags_t(0))) | │ │ │ │ │ +| { | │ │ │ │ │ +| state_updated(); | │ │ │ │ │ +| | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ +| if (should_log()) | │ │ │ │ │ +| { | │ │ │ │ │ +| debug_log("name-lookup add_peer() [ %s ] connect-candidates: %d" | │ │ │ │ │ +| , host.address().to_string().c_str() | │ │ │ │ │ +| , m_peer_list ? m_peer_list->num_connect_candidates() : -1); | │ │ │ │ │ +| } | │ │ │ │ │ +|#endif | │ │ │ │ │ +| } | │ │ │ │ │ +| update_want_peers(); | │ │ │ │ │ +|_ _}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_t_o_r_r_e_n_t_._c_p_p_:_4_5_6_2_ _ _ _ _ _ _ _|_o_n_l_y_ _d_o_ _t_h_i_s_ _i_f_ _t_h_e_ _p_i_e_c_e_ _s_i_z_e_ _>_ _1_ _b_l_o_c_k_s_ _T_h_i_s_ _i_s_ _a_ _v_2_ _t_o_r_r_e_n_t_ _s_o_ _w_e_ _c_a_n_ _r_e_q_u_e_s_t_ _g_e_t_ _b_l_o_c_k_ _l_e_v_e_l_ _h_a_s_h_e_s_._ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** oonnllyy ddoo tthhiiss iiff tthhee ppiieeccee ssiizzee >> 11 bblloocckkss TThhiiss iiss aa vv22 ttoorrrreenntt ssoo wwee ccaann rreeqquueesstt ggeett bblloocckk lleevveell hhaasshheess.. ********** | │ │ │ │ │ +|****** ....//ssrrcc//ttoorrrreenntt..ccpppp::44556622 ****** | │ │ │ │ │ +|{ | │ │ │ │ │ +| std::set ret; | │ │ │ │ │ +| if (!blocks.empty() && !downloaders.empty()) | │ │ │ │ │ +| { | │ │ │ │ │ +| for (auto const b : blocks) ret.insert(downloaders[std::size_t(b)]); | │ │ │ │ │ +| } | │ │ │ │ │ +| else | │ │ │ │ │ +| { | │ │ │ │ │ +| std::copy(downloaders.begin(), downloaders.end(), std::inserter(ret, ret.begin())); | │ │ │ │ │ +| } | │ │ │ │ │ +| return ret; | │ │ │ │ │ +| }(); | │ │ │ │ │ +| | │ │ │ │ │ +| // if this piece wasn't downloaded from peers, we just found it on disk. | │ │ │ │ │ +| // In that case, we should just consider it as "not-have" and there's no | │ │ │ │ │ +| // need to try to get higher fidelity hashes (yet) | │ │ │ │ │ +| bool const found_on_disk = peers.size() == 1 && peers.count(nullptr); | │ │ │ │ │ +| | │ │ │ │ │ +| if (!torrent_file().info_hashes().has_v1() && blocks.empty() && !found_on_disk) | │ │ │ │ │ +| { | │ │ │ │ │ +|verify_block_hashes(index); | │ │ │ │ │ +|} | │ │ │ │ │ +| | │ │ │ │ │ +| // the below code is penalizing peers that sent use bad data. | │ │ │ │ │ +| // increase the total amount of failed bytes | │ │ │ │ │ +| if (!found_on_disk) | │ │ │ │ │ +| { | │ │ │ │ │ +| if (blocks.empty()) | │ │ │ │ │ +| add_failed_bytes(m_torrent_file->piece_size(index)); | │ │ │ │ │ +| else | │ │ │ │ │ +| add_failed_bytes(static_cast(blocks.size()) * default_block_size); | │ │ │ │ │ +| | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_EXTENSIONS | │ │ │ │ │ +| for (auto& ext : m_extensions) | │ │ │ │ │ +| { | │ │ │ │ │ +| ext->on_piece_failed(index); | │ │ │ │ │ +| } | │ │ │ │ │ +|#endif | │ │ │ │ │ +| | │ │ │ │ │ +| // did we receive this piece from a single peer? | │ │ │ │ │ +| // if we know exactly which blocks failed the hash, we can also be certain | │ │ │ │ │ +| // that all peers in the list sent us bad data | │ │ │ │ │ +| bool const known_bad_peer = (!found_on_disk && peers.size() == 1) || !blocks.empty(); | │ │ │ │ │ +| | │ │ │ │ │ +| penalize_peers(peers, index, known_bad_peer); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| // If m_storage isn't set here, it means we're shutting down | │ │ │ │ │ +| if (m_storage) | │ │ │ │ │ +| { | │ │ │ │ │ +|_ _ _ _/_/_ _i_t_ _d_o_e_s_n_'_t_ _m_a_k_e_ _m_u_c_h_ _s_e_n_s_e_ _t_o_ _f_a_i_l_ _t_o_ _h_a_s_h_ _a_ _p_i_e_c_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_t_o_r_r_e_n_t_._c_p_p_:_7_5_0_1_ _ _ _ _ _ _ _|_c_o_m_e_ _u_p_ _w_i_t_h_ _a_ _b_e_t_t_e_r_ _w_a_y_ _o_f_ _d_o_i_n_g_ _t_h_i_s_,_ _i_n_s_t_e_a_d_ _o_f_ _a_n_ _i_m_m_e_d_i_a_t_e_l_y_ _i_n_v_o_k_e_d_ _l_a_m_b_d_a_ _e_x_p_r_e_s_s_i_o_n_._ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** ccoommee uupp wwiitthh aa bbeetttteerr wwaayy ooff ddooiinngg tthhiiss,, iinnsstteeaadd ooff aann iimmmmeeddiiaatteellyy iinnvvookkeedd llaammbbddaa eexxpprreessssiioonn.. ********** | │ │ │ │ │ +|****** ....//ssrrcc//ttoorrrreenntt..ccpppp::77550011 ****** | │ │ │ │ │ +||| peerinfo->confirmed_supports_utp)) | │ │ │ │ │ +| { | │ │ │ │ │ +| sm = m_ses.utp_socket_manager(); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| // don't make a TCP connection if it's disabled | │ │ │ │ │ +| if (sm == nullptr && !settings().get_bool(settings_pack::enable_outgoing_tcp)) | │ │ │ │ │ +| { | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ +| if (should_log()) | │ │ │ │ │ +| { | │ │ │ │ │ +| debug_log("discarding peer \"%s\": TCP connections disabled " | │ │ │ │ │ +| "[ supports-utp: %d ]", peerinfo->to_string().c_str() | │ │ │ │ │ +| , peerinfo->supports_utp); | │ │ │ │ │ +| } | │ │ │ │ │ +|#endif | │ │ │ │ │ +| return false; | │ │ │ │ │ +| } | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +|aux::socket_type s = [&] { | │ │ │ │ │ +| | │ │ │ │ │ +|#if TORRENT_USE_I2P | │ │ │ │ │ +| if (peerinfo->is_i2p_addr) | │ │ │ │ │ +| { | │ │ │ │ │ +| // It's not entirely obvious why this peer connection is not marked as | │ │ │ │ │ +| // one. The main feature of a peer connection is that whether or not we | │ │ │ │ │ +| // proxy it is configurable. When we use i2p, we want to always prox | │ │ │ │ │ +| // everything via i2p. | │ │ │ │ │ +| | │ │ │ │ │ +| aux::proxy_settings proxy; | │ │ │ │ │ +| proxy.hostname = settings().get_str(settings_pack::i2p_hostname); | │ │ │ │ │ +| proxy.port = std::uint16_t(settings().get_int(settings_pack::i2p_port)); | │ │ │ │ │ +| proxy.type = settings_pack::i2p_proxy; | │ │ │ │ │ +| | │ │ │ │ │ +| aux::socket_type ret = instantiate_connection(m_ses.get_context() | │ │ │ │ │ +| , proxy, nullptr, nullptr, false, false); | │ │ │ │ │ +| i2p_stream& str = boost::get(ret); | │ │ │ │ │ +| str.set_local_i2p_endpoint(m_ses.local_i2p_endpoint()); | │ │ │ │ │ +| str.set_destination(static_cast(peerinfo)->dest()); | │ │ │ │ │ +| str.set_command(i2p_stream::cmd_connect); | │ │ │ │ │ +| str.set_session_id(m_ses.i2p_session()); | │ │ │ │ │ +| return ret; | │ │ │ │ │ +| } | │ │ │ │ │ +| else | │ │ │ │ │ +|#endif | │ │ │ │ │ +| { | │ │ │ │ │ +| void* userdata = nullptr; | │ │ │ │ │ +|#ifdef TORRENT_SSL_PEERS | │ │ │ │ │ +| if (is_ssl_torrent()) | │ │ │ │ │ +|_ _ _ _{_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_t_o_r_r_e_n_t_._c_p_p_:_9_0_9_1_ _ _ _ _ _ _ _|_p_e_r_h_a_p_s_ _0_ _s_h_o_u_l_d_ _a_c_t_u_a_l_l_y_ _m_e_a_n_ _0_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** ppeerrhhaappss 00 sshhoouulldd aaccttuuaallllyy mmeeaann 00 ********** | │ │ │ │ │ +|****** ....//ssrrcc//ttoorrrreenntt..ccpppp::99009911 ****** | │ │ │ │ │ +|// finished torrents may not change their queue positions, as it's set to | │ │ │ │ │ +| // -1 | │ │ │ │ │ +| if ((m_abort || is_finished()) && p != no_pos) return; | │ │ │ │ │ +| | │ │ │ │ │ +| TORRENT_ASSERT((p == no_pos) == is_finished() | │ │ │ │ │ +| || (!m_auto_managed && p == no_pos) | │ │ │ │ │ +| || (m_abort && p == no_pos) | │ │ │ │ │ +| || (!m_added && p == no_pos)); | │ │ │ │ │ +| if (p == m_sequence_number) return; | │ │ │ │ │ +| | │ │ │ │ │ +| TORRENT_ASSERT(p >= no_pos); | │ │ │ │ │ +| | │ │ │ │ │ +| state_updated(); | │ │ │ │ │ +| | │ │ │ │ │ +| m_ses.set_queue_position(this, p); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| void torrent::set_max_uploads(int limit, bool const state_update) | │ │ │ │ │ +| { | │ │ │ │ │ +| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ +|if (limit <= 0) limit = (1 << 24) - 1; | │ │ │ │ │ +|if (int(m_max_uploads) == limit) return; | │ │ │ │ │ +| if (state_update) state_updated(); | │ │ │ │ │ +| m_max_uploads = aux::numeric_cast(limit); | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ +| if (should_log() && state_update) | │ │ │ │ │ +| debug_log("*** set-max-uploads: %d", m_max_uploads); | │ │ │ │ │ +|#endif | │ │ │ │ │ +| | │ │ │ │ │ +| if (state_update) | │ │ │ │ │ +| set_need_save_resume(torrent_handle::if_config_changed); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| void torrent::set_max_connections(int limit, bool const state_update) | │ │ │ │ │ +| { | │ │ │ │ │ +|_ _ _T_O_R_R_E_N_T___A_S_S_E_R_T_(_i_s___s_i_n_g_l_e___t_h_r_e_a_d_(_)_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_t_o_r_r_e_n_t_._c_p_p_:_9_1_0_8_ _ _ _ _ _ _ _|_p_e_r_h_a_p_s_ _0_ _s_h_o_u_l_d_ _a_c_t_u_a_l_l_y_ _m_e_a_n_ _0_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** ppeerrhhaappss 00 sshhoouulldd aaccttuuaallllyy mmeeaann 00 ********** | │ │ │ │ │ +|****** ....//ssrrcc//ttoorrrreenntt..ccpppp::99110088 ****** | │ │ │ │ │ +| void torrent::set_max_uploads(int limit, bool const state_update) | │ │ │ │ │ +| { | │ │ │ │ │ +| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ +| if (limit <= 0) limit = (1 << 24) - 1; | │ │ │ │ │ +| if (int(m_max_uploads) == limit) return; | │ │ │ │ │ +| if (state_update) state_updated(); | │ │ │ │ │ +| m_max_uploads = aux::numeric_cast(limit); | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ +| if (should_log() && state_update) | │ │ │ │ │ +| debug_log("*** set-max-uploads: %d", m_max_uploads); | │ │ │ │ │ +|#endif | │ │ │ │ │ +| | │ │ │ │ │ +| if (state_update) | │ │ │ │ │ +| set_need_save_resume(torrent_handle::if_config_changed); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| void torrent::set_max_connections(int limit, bool const state_update) | │ │ │ │ │ +| { | │ │ │ │ │ +| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ +|if (limit <= 0) limit = (1 << 24) - 1; | │ │ │ │ │ +|if (int(m_max_connections) == limit) return; | │ │ │ │ │ +| if (state_update) state_updated(); | │ │ │ │ │ +| m_max_connections = aux::numeric_cast(limit); | │ │ │ │ │ +| update_want_peers(); | │ │ │ │ │ +| | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ +| if (should_log() && state_update) | │ │ │ │ │ +| debug_log("*** set-max-connections: %d", m_max_connections); | │ │ │ │ │ +|#endif | │ │ │ │ │ +| | │ │ │ │ │ +| if (num_peers() > int(m_max_connections)) | │ │ │ │ │ +| { | │ │ │ │ │ +| disconnect_peers(num_peers() - m_max_connections | │ │ │ │ │ +| , errors::too_many_connections); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| if (state_update) | │ │ │ │ │ +| set_need_save_resume(torrent_handle::if_config_changed); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| void torrent::set_upload_limit(int const limit) | │ │ │ │ │ +| { | │ │ │ │ │ +| set_limit_impl(limit, peer_connection::upload_channel); | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ +| debug_log("*** set-upload-limit: %d", limit); | │ │ │ │ │ +|#endif | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| void torrent::set_download_limit(int const limit) | │ │ │ │ │ +|_ _{_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_t_o_r_r_e_n_t_._c_p_p_:_1_1_0_3_4_ _ _ _ _ _ _|_i_n_s_t_e_a_d_ _o_f_ _r_e_s_o_r_t_i_n_g_ _t_h_e_ _w_h_o_l_e_ _l_i_s_t_,_ _i_n_s_e_r_t_ _t_h_e_ _p_e_e_r_s_ _d_i_r_e_c_t_l_y_ _i_n_t_o_ _t_h_e_ _r_i_g_h_t_ _p_l_a_c_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** iinnsstteeaadd ooff rreessoorrttiinngg tthhee wwhhoollee lliisstt,, iinnsseerrtt tthhee ppeeeerrss ddiirreeccttllyy iinnttoo tthhee rriigghhtt ppllaaccee ********** | │ │ │ │ │ +|****** ....//ssrrcc//ttoorrrreenntt..ccpppp::1111003344 ****** | │ │ │ │ │ +|std::printf("timed out [average-piece-time: %d ms ]\n" | │ │ │ │ │ +| , m_average_piece_time); | │ │ │ │ │ +|#endif | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| // pick all blocks for this piece. the peers list is kept up to date | │ │ │ │ │ +| // and sorted. when we issue a request to a peer, its download queue | │ │ │ │ │ +| // time will increase and it may need to be bumped in the peers list, | │ │ │ │ │ +| // since it's ordered by download queue time | │ │ │ │ │ +| pick_time_critical_block(peers, ignore_peers | │ │ │ │ │ +| , peers_with_requests | │ │ │ │ │ +| , pi, &i, m_picker.get() | │ │ │ │ │ +| , blocks_in_piece, timed_out); | │ │ │ │ │ +| | │ │ │ │ │ +| // put back the peers we ignored into the peer list for the next piece | │ │ │ │ │ +| if (!ignore_peers.empty()) | │ │ │ │ │ +| { | │ │ │ │ │ +| peers.insert(peers.begin(), ignore_peers.begin(), ignore_peers.end()); | │ │ │ │ │ +| ignore_peers.clear(); | │ │ │ │ │ +| | │ │ │ │ │ +|std::sort(peers.begin(), peers.end() | │ │ │ │ │ +|, [] (peer_connection const* lhs, peer_connection const* rhs) | │ │ │ │ │ +| { return lhs->download_queue_time(16*1024) < rhs->download_queue_time(16*1024); }); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| // if this peer's download time exceeds 2 seconds, we're done. | │ │ │ │ │ +| // We don't want to build unreasonably long request queues | │ │ │ │ │ +| if (!peers.empty() && peers[0]->download_queue_time() > milliseconds(2000)) | │ │ │ │ │ +| break; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| // commit all the time critical requests | │ │ │ │ │ +| for (auto p : peers_with_requests) | │ │ │ │ │ +| { | │ │ │ │ │ +| p->send_block_requests(); | │ │ │ │ │ +| } | │ │ │ │ │ +| } | │ │ │ │ │ +|#endif // TORRENT_DISABLE_STREAMING | │ │ │ │ │ +| | │ │ │ │ │ +| std::set torrent::web_seeds(web_seed_entry::type_t const type) const | │ │ │ │ │ +| { | │ │ │ │ │ +| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ +| std::set ret; | │ │ │ │ │ +| for (auto const& s : m_web_seeds) | │ │ │ │ │ +| { | │ │ │ │ │ +| if (s.peer_info.banned) continue; | │ │ │ │ │ +| if (s.removed) continue; | │ │ │ │ │ +| if (s.type != type) continue; | │ │ │ │ │ +| ret.insert(s.url); | │ │ │ │ │ +| } | │ │ │ │ │ +|_ _ _r_e_t_u_r_n_ _r_e_t_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_r_a_n_d_o_m_._c_p_p_:_1_4_1_ _ _ _ _ _ _ _ _ _|_i_m_p_r_o_v_e_ _c_a_l_l_i_n_g_ _R_A_N_D___b_y_t_e_s_ _m_u_l_t_i_p_l_e_ _t_i_m_e_s_,_ _u_s_i_n_g_ _f_a_l_l_b_a_c_k_ _f_o_r_ _n_o_w_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** iimmpprroovvee ccaalllliinngg RRAANNDD__bbyytteess mmuullttiippllee ttiimmeess,, uussiinngg ffaallllbbaacckk ffoorr nnooww ********** | │ │ │ │ │ +|****** ....//ssrrcc//rraannddoomm..ccpppp::114411 ****** | │ │ │ │ │ +|#else | │ │ │ │ │ +| std::generate(buffer.begin(), buffer.end(), [] { return char(random(0xff)); }); | │ │ │ │ │ +|#endif | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| void crypto_random_bytes(span buffer) | │ │ │ │ │ +| { | │ │ │ │ │ +|#ifdef TORRENT_BUILD_SIMULATOR | │ │ │ │ │ +| // In the simulator we want deterministic random numbers | │ │ │ │ │ +| std::generate(buffer.begin(), buffer.end(), [] { return char(random(0xff)); }); | │ │ │ │ │ +|#elif TORRENT_USE_CNG | │ │ │ │ │ +| aux::cng_gen_random(buffer); | │ │ │ │ │ +|#elif TORRENT_USE_CRYPTOAPI | │ │ │ │ │ +| // windows | │ │ │ │ │ +| aux::crypt_gen_random(buffer); | │ │ │ │ │ +|#elif defined TORRENT_USE_LIBCRYPTO && !defined TORRENT_USE_WOLFSSL | │ │ │ │ │ +|// wolfSSL uses wc_RNG_GenerateBlock as the internal function for the | │ │ │ │ │ +|// openssl compatibility layer. This function API does not support | │ │ │ │ │ +|// an arbitrary buffer size (openssl does), it is limited by the | │ │ │ │ │ +|// constant RNG_MAX_BLOCK_LEN. | │ │ │ │ │ +| | │ │ │ │ │ +|// openssl | │ │ │ │ │ +| int r = RAND_bytes(reinterpret_cast(buffer.data()) | │ │ │ │ │ +| , int(buffer.size())); | │ │ │ │ │ +| if (r != 1) aux::throw_ex(errors::no_entropy); | │ │ │ │ │ +|#elif TORRENT_USE_GETRANDOM | │ │ │ │ │ +| ssize_t const r = ::getrandom(buffer.data(), static_cast(buffer.size()), 0); | │ │ │ │ │ +| if (r == ssize_t(buffer.size())) return; | │ │ │ │ │ +| if (r == -1 && errno != ENOSYS) aux::throw_ex(error_code(errno, generic_category())); | │ │ │ │ │ +| static dev_random dev; | │ │ │ │ │ +| dev.read(buffer); | │ │ │ │ │ +|#elif TORRENT_USE_DEV_RANDOM | │ │ │ │ │ +| static dev_random dev; | │ │ │ │ │ +| dev.read(buffer); | │ │ │ │ │ +|#else | │ │ │ │ │ +| | │ │ │ │ │ +|#if TORRENT_BROKEN_RANDOM_DEVICE | │ │ │ │ │ +| // even pseudo random numbers rely on being able to seed the random | │ │ │ │ │ +| // generator | │ │ │ │ │ +|#error "no entropy source available" | │ │ │ │ │ +|#else | │ │ │ │ │ +|#ifdef TORRENT_I_WANT_INSECURE_RANDOM_NUMBERS | │ │ │ │ │ +| std::generate(buffer.begin(), buffer.end(), [] { return char(random(0xff)); }); | │ │ │ │ │ +|#else | │ │ │ │ │ +|#error "no secure entropy source available. If you really want insecure random numbers, define TORRENT_I_WANT_INSECURE_RANDOM_NUMBERS" | │ │ │ │ │ +|#endif | │ │ │ │ │ +|#endif | │ │ │ │ │ +| | │ │ │ │ │ +|#endif | │ │ │ │ │ +| } | │ │ │ │ │ +|_}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_m_a_g_n_e_t___u_r_i_._c_p_p_:_4_3_9_ _ _ _ _ _|_w_h_a_t_'_s_ _t_h_e_ _r_i_g_h_t_ _n_u_m_b_e_r_ _h_e_r_e_?_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** wwhhaatt''ss tthhee rriigghhtt nnuummbbeerr hheerree?? ********** | │ │ │ │ │ +|****** ....//ssrrcc//mmaaggnneett__uurrii..ccpppp::443399 ****** | │ │ │ │ │ +|} | │ │ │ │ │ +| else if (string_equal_no_case(name, "so"_sv)) // select-only (files) | │ │ │ │ │ +| { | │ │ │ │ │ +| // accept only digits, '-' and ',' | │ │ │ │ │ +| if (std::any_of(value.begin(), value.end(), [](char c) | │ │ │ │ │ +| { return !is_digit(c) && c != '-' && c != ','; })) | │ │ │ │ │ +| continue; | │ │ │ │ │ +| | │ │ │ │ │ +| // make sure all file priorities are set to 0, except the ones | │ │ │ │ │ +| // we specify in the file_priorities | │ │ │ │ │ +| p.flags |= torrent_flags::default_dont_download; | │ │ │ │ │ +| | │ │ │ │ │ +| do | │ │ │ │ │ +| { | │ │ │ │ │ +| string_view token; | │ │ │ │ │ +| std::tie(token, value) = split_string(value, ','); | │ │ │ │ │ +| | │ │ │ │ │ +| if (token.empty()) continue; | │ │ │ │ │ +| | │ │ │ │ │ +| int idx1, idx2; | │ │ │ │ │ +|constexpr int max_index = 10000; // can't risk out of memory | │ │ │ │ │ +| | │ │ │ │ │ +| auto const divider = token.find_first_of('-'); | │ │ │ │ │ +| if (divider != std::string::npos) // it's a range | │ │ │ │ │ +| { | │ │ │ │ │ +| if (divider == 0) // no start index | │ │ │ │ │ +| continue; | │ │ │ │ │ +| if (divider == token.size() - 1) // no end index | │ │ │ │ │ +| continue; | │ │ │ │ │ +| | │ │ │ │ │ +| idx1 = std::atoi(token.substr(0, divider).to_string().c_str()); | │ │ │ │ │ +| if (idx1 < 0 || idx1 > max_index) // invalid index | │ │ │ │ │ +| continue; | │ │ │ │ │ +| idx2 = std::atoi(token.substr(divider + 1).to_string().c_str()); | │ │ │ │ │ +| if (idx2 < 0 || idx2 > max_index) // invalid index | │ │ │ │ │ +| continue; | │ │ │ │ │ +| | │ │ │ │ │ +| if (idx1 > idx2) // wrong range limits | │ │ │ │ │ +| continue; | │ │ │ │ │ +| } | │ │ │ │ │ +| else // it's an index | │ │ │ │ │ +| { | │ │ │ │ │ +| idx1 = std::atoi(token.to_string().c_str()); | │ │ │ │ │ +| if (idx1 < 0 || idx1 > max_index) // invalid index | │ │ │ │ │ +| continue; | │ │ │ │ │ +| idx2 = idx1; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| if (int(p.file_priorities.size()) <= idx2) | │ │ │ │ │ +|_ _ _ _ _ _ _p_._f_i_l_e___p_r_i_o_r_i_t_i_e_s_._r_e_s_i_z_e_(_s_t_a_t_i_c___c_a_s_t_<_s_t_d_:_:_s_i_z_e___t_>_(_i_d_x_2_)_ _+_ _1_,_ _d_o_n_t___d_o_w_n_l_o_a_d_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_s_r_c_/ |why is this a linked list? | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_u_d_p___t_r_a_c_k_e_r___c_o_n_n_e_c_t_i_o_n_._c_p_p_:_6_3_3_|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** wwhhyy iiss tthhiiss aa lliinnkkeedd lliisstt?? ********** | │ │ │ │ │ +|****** ....//ssrrcc//uuddpp__ttrraacckkeerr__ccoonnnneeccttiioonn..ccpppp::663333 ****** | │ │ │ │ │ +|ipv6_peer_entry e{}; | │ │ │ │ │ +| std::memcpy(e.ip.data(), buf.data(), 16); | │ │ │ │ │ +| buf = buf.subspan(16); | │ │ │ │ │ +| e.port = aux::read_uint16(buf); | │ │ │ │ │ +| resp.peers6.push_back(e); | │ │ │ │ │ +| } | │ │ │ │ │ +| } | │ │ │ │ │ +| else | │ │ │ │ │ +| { | │ │ │ │ │ +| resp.peers4.reserve(static_cast(num_peers)); | │ │ │ │ │ +| for (int i = 0; i < num_peers; ++i) | │ │ │ │ │ +| { | │ │ │ │ │ +| ipv4_peer_entry e{}; | │ │ │ │ │ +| std::memcpy(e.ip.data(), buf.data(), 4); | │ │ │ │ │ +| buf = buf.subspan(4); | │ │ │ │ │ +| e.port = aux::read_uint16(buf); | │ │ │ │ │ +| resp.peers4.push_back(e); | │ │ │ │ │ +| } | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +|std::list
    ip_list; | │ │ │ │ │ +|std::transform(m_endpoints.begin(), m_endpoints.end(), std::back_inserter(ip_list) | │ │ │ │ │ +| , [](tcp::endpoint const& ep) { return ep.address(); } ); | │ │ │ │ │ +| | │ │ │ │ │ +| cb->tracker_response(tracker_req(), m_target.address(), ip_list, resp); | │ │ │ │ │ +| | │ │ │ │ │ +| close(); | │ │ │ │ │ +| return true; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| bool udp_tracker_connection::on_scrape_response(span buf) | │ │ │ │ │ +| { | │ │ │ │ │ +| restart_read_timeout(); | │ │ │ │ │ +| auto const action = static_cast(aux::read_int32(buf)); | │ │ │ │ │ +| std::uint32_t const transaction = aux::read_uint32(buf); | │ │ │ │ │ +| | │ │ │ │ │ +| if (transaction != m_transaction_id) | │ │ │ │ │ +| { | │ │ │ │ │ +| fail(error_code(errors::invalid_tracker_transaction_id), operation_t::bittorrent); | │ │ │ │ │ +| return false; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| if (action == action_t::error) | │ │ │ │ │ +| { | │ │ │ │ │ +| fail(error_code(errors::tracker_failure), operation_t::bittorrent | │ │ │ │ │ +| , std::string(buf.data(), static_cast(buf.size())).c_str()); | │ │ │ │ │ +| return true; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| if (action != action_t::scrape) | │ │ │ │ │ +|_ _ _{_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_p_i_e_c_e___p_i_c_k_e_r_._c_p_p_:_1_2_1_ _ _ _|_f_i_n_d_ _a_ _b_e_t_t_e_r_ _p_l_a_c_e_ _f_o_r_ _t_h_i_s_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** ffiinndd aa bbeetttteerr ppllaaccee ffoorr tthhiiss ********** | │ │ │ │ │ |****** ....//ssrrcc//ppiieeccee__ppiicckkeerr..ccpppp::112211 ****** | │ │ │ │ │ |if (limit == 0) | │ │ │ │ │ | { | │ │ │ │ │ | std::cerr << " ..."; | │ │ │ │ │ | break; | │ │ │ │ │ @@ -10355,68 +9620,288 @@ │ │ │ │ │ | TORRENT_ASSERT(!m_piece_map[block.piece_index].have()); | │ │ │ │ │ | | │ │ │ │ │ | piece_pos& p = m_piece_map[block.piece_index]; | │ │ │ │ │ | if (p.download_queue() == piece_pos::piece_open) | │ │ │ │ │ | { | │ │ │ │ │ |#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS | │ │ │ │ │ |_ _ _ _I_N_V_A_R_I_A_N_T___C_H_E_C_K_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_t_o_r_r_e_n_t___p_e_e_r_._c_p_p_:_1_8_1_ _ _ _|_h_o_w_ _d_o_ _w_e_ _d_e_a_l_ _w_i_t_h_ _o_u_r_ _e_x_t_e_r_n_a_l_ _a_d_d_r_e_s_s_ _c_h_a_n_g_i_n_g_?_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** hhooww ddoo wwee ddeeaall wwiitthh oouurr eexxtteerrnnaall aaddddrreessss cchhaannggiinngg?? ********** | │ │ │ │ │ -|****** ....//ssrrcc//ttoorrrreenntt__ppeeeerr..ccpppp::118811 ****** | │ │ │ │ │ -|// connections. If it fails, we'll | │ │ │ │ │ -| // retry with encryption | │ │ │ │ │ -| , pe_support(false) | │ │ │ │ │ -|#endif | │ │ │ │ │ -| , is_v6_addr(false) | │ │ │ │ │ -|#if TORRENT_USE_I2P | │ │ │ │ │ -| , is_i2p_addr(false) | │ │ │ │ │ +|relevance 0|_._._/_s_r_c_/_s_t_o_r_a_g_e___u_t_i_l_s_._c_p_p_:_2_3_0 |ideally, if we end up copying files because of a move across volumes, the source should not be deleted until they've all been | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_c_o_p_i_e_d_._ _T_h_a_t_ _w_o_u_l_d_ _l_e_t_ _u_s_ _r_o_l_l_b_a_c_k_ _w_i_t_h_ _h_i_g_h_e_r_ _c_o_n_f_i_d_e_n_c_e_._ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** iiddeeaallllyy,, iiff wwee eenndd uupp ccooppyyiinngg ffiilleess bbeeccaauussee ooff aa mmoovvee aaccrroossss vvoolluummeess,, tthhee ssoouurrccee sshhoouulldd nnoott bbee ddeelleetteedd uunnttiill tthheeyy''vvee aallll bbeeeenn ccooppiieedd.. TThhaatt wwoouulldd lleett uuss rroollllbbaacckk wwiitthh | │ │ │ │ │ +|hhiigghheerr ccoonnffiiddeennccee.. ********** | │ │ │ │ │ +|****** ....//ssrrcc//ssttoorraaggee__uuttiillss..ccpppp::223300 ****** | │ │ │ │ │ +|// later | │ │ │ │ │ +| aux::vector copied_files(std::size_t(f.num_files()), false); | │ │ │ │ │ +| | │ │ │ │ │ +| // track how far we got in case of an error | │ │ │ │ │ +| file_index_t file_index{}; | │ │ │ │ │ +| for (auto const i : f.file_range()) | │ │ │ │ │ +| { | │ │ │ │ │ +| // files moved out to absolute paths are not moved | │ │ │ │ │ +| if (f.file_absolute_path(i)) continue; | │ │ │ │ │ +| | │ │ │ │ │ +| std::string const old_path = combine_path(save_path, f.file_path(i)); | │ │ │ │ │ +| std::string const new_path = combine_path(new_save_path, f.file_path(i)); | │ │ │ │ │ +| | │ │ │ │ │ +| error_code ignore; | │ │ │ │ │ +| if (flags == move_flags_t::dont_replace && exists(new_path, ignore)) | │ │ │ │ │ +| { | │ │ │ │ │ +| if (ret == status_t::no_error) ret = status_t::need_full_check; | │ │ │ │ │ +| continue; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +|move_file(old_path, new_path, ec); | │ │ │ │ │ +| | │ │ │ │ │ +| // if the source file doesn't exist. That's not a problem | │ │ │ │ │ +| // we just ignore that file | │ │ │ │ │ +| if (ec.ec == boost::system::errc::no_such_file_or_directory) | │ │ │ │ │ +| ec.ec.clear(); | │ │ │ │ │ +| else if (ec | │ │ │ │ │ +| && ec.ec != boost::system::errc::invalid_argument | │ │ │ │ │ +| && ec.ec != boost::system::errc::permission_denied) | │ │ │ │ │ +| { | │ │ │ │ │ +| // moving the file failed | │ │ │ │ │ +| // on OSX, the error when trying to rename a file across different | │ │ │ │ │ +| // volumes is EXDEV, which will make it fall back to copying. | │ │ │ │ │ +| ec.ec.clear(); | │ │ │ │ │ +| copy_file(old_path, new_path, ec); | │ │ │ │ │ +| if (!ec) copied_files[i] = true; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| if (ec) | │ │ │ │ │ +| { | │ │ │ │ │ +| ec.file(i); | │ │ │ │ │ +| file_index = i; | │ │ │ │ │ +| break; | │ │ │ │ │ +| } | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| if (!ec && move_partfile) | │ │ │ │ │ +| { | │ │ │ │ │ +| error_code e; | │ │ │ │ │ +| move_partfile(new_save_path, e); | │ │ │ │ │ +|_ _ _ _i_f_ _(_e_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_s_r_c_/_s_t_o_r_a_g_e___u_t_i_l_s_._c_p_p_:_5_3_8 |it would seem reasonable to, instead, set the have_pieces bits for the pieces representing these files, and resume with the normal | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_l_o_g_i_c_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** iitt wwoouulldd sseeeemm rreeaassoonnaabbllee ttoo,, iinnsstteeaadd,, sseett tthhee hhaavvee__ppiieecceess bbiittss ffoorr tthhee ppiieecceess rreepprreesseennttiinngg tthheessee ffiilleess,, aanndd rreessuummee wwiitthh tthhee nnoorrmmaall llooggiicc ********** | │ │ │ │ │ +|****** ....//ssrrcc//ssttoorraaggee__uuttiillss..ccpppp::553388 ****** | │ │ │ │ │ +|continue; | │ │ │ │ │ +| | │ │ │ │ │ +| std::int64_t const size = get_filesize(stat, file_index, fs | │ │ │ │ │ +| , save_path, ec); | │ │ │ │ │ +| if (size < 0) return false; | │ │ │ │ │ +| | │ │ │ │ │ +| if (size < fs.file_size(file_index)) | │ │ │ │ │ +| { | │ │ │ │ │ +| ec.ec = errors::mismatching_file_size; | │ │ │ │ │ +| ec.file(file_index); | │ │ │ │ │ +| ec.operation = operation_t::check_resume; | │ │ │ │ │ +| return false; | │ │ │ │ │ +| } | │ │ │ │ │ +| } | │ │ │ │ │ +| return true; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_MUTABLE_TORRENTS | │ │ │ │ │ +| // always trigger a full recheck when we pull in files from other | │ │ │ │ │ +| // torrents, via hard links | │ │ │ │ │ +|if (added_files) return false; | │ │ │ │ │ |#endif | │ │ │ │ │ -| , on_parole(false) | │ │ │ │ │ -| , banned(false) | │ │ │ │ │ -| , supports_utp(true) // assume peers support utp | │ │ │ │ │ -| , confirmed_supports_utp(false) | │ │ │ │ │ -| , supports_holepunch(false) | │ │ │ │ │ -| , web_seed(false) | │ │ │ │ │ -| , protocol_v2(false) | │ │ │ │ │ -| {} | │ │ │ │ │ | | │ │ │ │ │ -| std::uint32_t torrent_peer::rank(external_ip const& external, int external_port) const | │ │ │ │ │ -| { | │ │ │ │ │ -| TORRENT_ASSERT(in_use); | │ │ │ │ │ -|if (peer_rank == 0) | │ │ │ │ │ -|peer_rank = peer_priority( | │ │ │ │ │ -| tcp::endpoint(external.external_address(this->address()), std::uint16_t(external_port)) | │ │ │ │ │ -| , tcp::endpoint(this->address(), this->port)); | │ │ │ │ │ -| return peer_rank; | │ │ │ │ │ +| // parse have bitmask. Verify that the files we expect to have | │ │ │ │ │ +| // actually do exist | │ │ │ │ │ +| piece_index_t const end_piece = std::min(rd.have_pieces.end_index(), fs.end_piece()); | │ │ │ │ │ +| for (piece_index_t i(0); i < end_piece; ++i) | │ │ │ │ │ +| { | │ │ │ │ │ +| if (rd.have_pieces.get_bit(i) == false) continue; | │ │ │ │ │ +| | │ │ │ │ │ +| std::vector f = fs.map_block(i, 0, 1); | │ │ │ │ │ +| TORRENT_ASSERT(!f.empty()); | │ │ │ │ │ +| | │ │ │ │ │ +| file_index_t const file_index = f[0].file_index; | │ │ │ │ │ +| | │ │ │ │ │ +| // files with priority zero may not have been saved to disk at their | │ │ │ │ │ +| // expected location, but is likely to be in a partfile. Just exempt it | │ │ │ │ │ +| // from checking | │ │ │ │ │ +| if (file_index < file_priority.end_index() | │ │ │ │ │ +| && file_priority[file_index] == dont_download) | │ │ │ │ │ +| continue; | │ │ │ │ │ +| | │ │ │ │ │ +| if (fs.pad_file_at(file_index)) continue; | │ │ │ │ │ +| | │ │ │ │ │ +| if (get_filesize(stat, file_index, fs, save_path, ec) < 0) | │ │ │ │ │ +| return false; | │ │ │ │ │ +| | │ │ │ │ │ +| // OK, this file existed, good. Now, skip all remaining pieces in | │ │ │ │ │ +| // this file. We're just sanity-checking whether the files exist | │ │ │ │ │ +| // or not. | │ │ │ │ │ +|_ _ _ _p_e_e_r___r_e_q_u_e_s_t_ _c_o_n_s_t_ _p_r_ _=_ _f_s_._m_a_p___f_i_l_e_(_f_i_l_e___i_n_d_e_x_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_s_r_c_/_p_e_e_r___c_o_n_n_e_c_t_i_o_n_._c_p_p_: |this should be the global download rate | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_1_0_9_1_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tthhiiss sshhoouulldd bbee tthhee gglloobbaall ddoowwnnllooaadd rraattee ********** | │ │ │ │ │ +|****** ....//ssrrcc//ppeeeerr__ccoonnnneeccttiioonn..ccpppp::11009911 ****** | │ │ │ │ │ +| int rate = 0; | │ │ │ │ │ +| | │ │ │ │ │ +| // if we haven't received any data recently, the current download rate | │ │ │ │ │ +| // is not representative | │ │ │ │ │ +| if (aux::time_now() - m_last_piece.get(m_connect) > seconds(30) && m_download_rate_peak > 0) | │ │ │ │ │ +| { | │ │ │ │ │ +| rate = m_download_rate_peak; | │ │ │ │ │ +| } | │ │ │ │ │ +| else if (aux::time_now() - m_last_unchoked.get(m_connect) < seconds(5) | │ │ │ │ │ +| && m_statistics.total_payload_upload() < 2 * 0x4000) | │ │ │ │ │ +| { | │ │ │ │ │ +| // if we're have only been unchoked for a short period of time, | │ │ │ │ │ +| // we don't know what rate we can get from this peer. Instead of assuming | │ │ │ │ │ +| // the lowest possible rate, assume the average. | │ │ │ │ │ +| | │ │ │ │ │ +| int peers_with_requests = int(stats_counters()[counters::num_peers_down_requests]); | │ │ │ │ │ +| // avoid division by 0 | │ │ │ │ │ +| if (peers_with_requests == 0) peers_with_requests = 1; | │ │ │ │ │ +| | │ │ │ │ │ +|rate = t->statistics().transfer_rate(stat::download_payload) / peers_with_requests; | │ │ │ │ │ +|} | │ │ │ │ │ +| else | │ │ │ │ │ +| { | │ │ │ │ │ +| // current download rate in bytes per seconds | │ │ │ │ │ +| rate = m_statistics.transfer_rate(stat::download_payload); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| // avoid division by zero | │ │ │ │ │ +| if (rate < 50) rate = 50; | │ │ │ │ │ +| | │ │ │ │ │ +| // average of current rate and peak | │ │ │ │ │ +|// rate = (rate + m_download_rate_peak) / 2; | │ │ │ │ │ +| | │ │ │ │ │ +| return milliseconds((m_outstanding_bytes + extra_bytes | │ │ │ │ │ +| + m_queued_time_critical * t->block_size() * 1000) / rate); | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ -| std::string torrent_peer::to_string() const | │ │ │ │ │ +| void peer_connection::add_stat(std::int64_t const downloaded, std::int64_t const uploaded) | │ │ │ │ │ | { | │ │ │ │ │ -| TORRENT_ASSERT(in_use); | │ │ │ │ │ -|#if TORRENT_USE_I2P | │ │ │ │ │ -| if (is_i2p_addr) return dest().to_string(); | │ │ │ │ │ -|#endif // TORRENT_USE_I2P | │ │ │ │ │ -| return address().to_string(); | │ │ │ │ │ +| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ +| m_statistics.add_stat(downloaded, uploaded); | │ │ │ │ │ | } | │ │ │ │ │ -|#endif | │ │ │ │ │ | | │ │ │ │ │ -| std::int64_t torrent_peer::total_download() const | │ │ │ │ │ +| sha1_hash peer_connection::associated_info_hash() const | │ │ │ │ │ | { | │ │ │ │ │ -| TORRENT_ASSERT(in_use); | │ │ │ │ │ -| if (connection != nullptr) | │ │ │ │ │ -| { | │ │ │ │ │ -| TORRENT_ASSERT(prev_amount_download == 0); | │ │ │ │ │ -| return connection->statistics().total_payload_download(); | │ │ │ │ │ -| } | │ │ │ │ │ -| else | │ │ │ │ │ +| std::shared_ptr t = associated_torrent().lock(); | │ │ │ │ │ +| TORRENT_ASSERT(t); | │ │ │ │ │ +| auto const& ih = t->info_hash(); | │ │ │ │ │ +| // if protocol_v2 is set on the peer, this better be a v2 torrent, | │ │ │ │ │ +|_ _ _/_/_ _o_t_h_e_r_w_i_s_e_ _s_o_m_e_t_h_i_n_g_ _i_s_n_'_t_ _r_i_g_h_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_s_r_c_/_p_e_e_r___c_o_n_n_e_c_t_i_o_n_._c_p_p_: |sort the allowed fast set in priority order | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_3_5_2_0_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** ssoorrtt tthhee aalllloowweedd ffaasstt sseett iinn pprriioorriittyy oorrddeerr ********** | │ │ │ │ │ +|****** ....//ssrrcc//ppeeeerr__ccoonnnneeccttiioonn..ccpppp::33552200 ****** | │ │ │ │ │ +| // if the peer has the piece and we want | │ │ │ │ │ +| // to download it, request it | │ │ │ │ │ +| if (index < m_have_piece.end_index() | │ │ │ │ │ +| && m_have_piece[index] | │ │ │ │ │ +| && !t->has_piece_passed(index) | │ │ │ │ │ +| && t->valid_metadata() | │ │ │ │ │ +| && t->has_picker() | │ │ │ │ │ +| && t->picker().piece_priority(index) > dont_download) | │ │ │ │ │ | { | │ │ │ │ │ -| return std::int64_t(prev_amount_download) << 10; | │ │ │ │ │ +| t->peer_is_interesting(*this); | │ │ │ │ │ | } | │ │ │ │ │ -|_ _}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| std::vector const& peer_connection::allowed_fast() | │ │ │ │ │ +| { | │ │ │ │ │ +| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ +| std::shared_ptr t = m_torrent.lock(); | │ │ │ │ │ +| TORRENT_ASSERT(t); | │ │ │ │ │ +| | │ │ │ │ │ +|return m_allowed_fast; | │ │ │ │ │ +|} | │ │ │ │ │ +| | │ │ │ │ │ +| bool peer_connection::can_request_time_critical() const | │ │ │ │ │ +| { | │ │ │ │ │ +| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ +| if (has_peer_choked() || !is_interesting()) return false; | │ │ │ │ │ +| if (int(m_download_queue.size()) + int(m_request_queue.size()) | │ │ │ │ │ +| > m_desired_queue_size * 2) return false; | │ │ │ │ │ +| if (on_parole()) return false; | │ │ │ │ │ +| if (m_disconnecting) return false; | │ │ │ │ │ +| std::shared_ptr t = m_torrent.lock(); | │ │ │ │ │ +| TORRENT_ASSERT(t); | │ │ │ │ │ +| if (t->upload_mode()) return false; | │ │ │ │ │ +| | │ │ │ │ │ +| // ignore snubbed peers, since they're not likely to return pieces in a | │ │ │ │ │ +| // timely manner anyway | │ │ │ │ │ +| if (m_snubbed) return false; | │ │ │ │ │ +| return true; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| bool peer_connection::make_time_critical(piece_block const& block) | │ │ │ │ │ +| { | │ │ │ │ │ +| TORRENT_ASSERT(is_single_thread()); | │ │ │ │ │ +| auto const rit = std::find_if(m_request_queue.begin() | │ │ │ │ │ +| , m_request_queue.end(), aux::has_block(block)); | │ │ │ │ │ +| if (rit == m_request_queue.end()) return false; | │ │ │ │ │ +|#if TORRENT_USE_ASSERTS | │ │ │ │ │ +| std::shared_ptr t = m_torrent.lock(); | │ │ │ │ │ +| TORRENT_ASSERT(t); | │ │ │ │ │ +|_ _ _T_O_R_R_E_N_T___A_S_S_E_R_T_(_t_-_>_h_a_s___p_i_c_k_e_r_(_)_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_s_r_c_/ |technically, this isn't supposed to happen, but it seems to sometimes. Some of the accounting is probably wrong in certain cases | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_h_t_t_p___s_e_e_d___c_o_n_n_e_c_t_i_o_n_._c_p_p_:_4_4_1_ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tteecchhnniiccaallllyy,, tthhiiss iissnn''tt ssuuppppoosseedd ttoo hhaappppeenn,, bbuutt iitt sseeeemmss ttoo ssoommeettiimmeess.. SSoommee ooff tthhee aaccccoouunnttiinngg iiss pprroobbaabbllyy wwrroonngg iinn cceerrttaaiinn ccaasseess ********** | │ │ │ │ │ +|****** ....//ssrrcc//hhttttpp__sseeeedd__ccoonnnneeccttiioonn..ccpppp::444411 ****** | │ │ │ │ │ +|// cut out the chunk header from the receive buffer | │ │ │ │ │ +| TORRENT_ASSERT(m_chunk_pos + m_body_start < INT_MAX); | │ │ │ │ │ +| m_recv_buffer.cut(header_size, t->block_size() + 1024, aux::numeric_cast(m_chunk_pos + m_body_start)); | │ │ │ │ │ +| recv_buffer = m_recv_buffer.get(); | │ │ │ │ │ +| recv_buffer = recv_buffer.subspan(m_body_start); | │ │ │ │ │ +| m_chunk_pos += chunk_size; | │ │ │ │ │ +| if (chunk_size == 0) | │ │ │ │ │ +| { | │ │ │ │ │ +| TORRENT_ASSERT(m_recv_buffer.get().size() < m_chunk_pos + m_body_start + 1 | │ │ │ │ │ +| || m_recv_buffer.get()[static_cast(m_chunk_pos + m_body_start)] == 'H' | │ │ │ │ │ +| || (m_parser.chunked_encoding() | │ │ │ │ │ +| && m_recv_buffer.get()[static_cast(m_chunk_pos + m_body_start)] == '\r')); | │ │ │ │ │ +| m_chunk_pos = -1; | │ │ │ │ │ +| } | │ │ │ │ │ +| } | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| int payload = int(bytes_transferred); | │ │ │ │ │ +| if (payload > m_response_left) payload = int(m_response_left); | │ │ │ │ │ +| if (payload > front_request.length) payload = front_request.length; | │ │ │ │ │ +|if (payload > outstanding_bytes()) payload = outstanding_bytes(); | │ │ │ │ │ +|received_bytes(payload, 0); | │ │ │ │ │ +| incoming_piece_fragment(payload); | │ │ │ │ │ +| m_response_left -= payload; | │ │ │ │ │ +| | │ │ │ │ │ +| if (m_parser.status_code() == 503) | │ │ │ │ │ +| { | │ │ │ │ │ +| if (!m_parser.finished()) return; | │ │ │ │ │ +| | │ │ │ │ │ +| int retry_time = std::atoi(std::string(recv_buffer.begin(), recv_buffer.end()).c_str()); | │ │ │ │ │ +| if (retry_time <= 0) retry_time = 60; | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ +| peer_log(peer_log_alert::info, "CONNECT", "retrying in %d seconds", retry_time); | │ │ │ │ │ +|#endif | │ │ │ │ │ +| | │ │ │ │ │ +| received_bytes(0, int(bytes_transferred)); | │ │ │ │ │ +| // temporarily unavailable, retry later | │ │ │ │ │ +| t->retry_web_seed(this, seconds32(retry_time)); | │ │ │ │ │ +| disconnect(error_code(m_parser.status_code(), http_category()), operation_t::bittorrent, failure); | │ │ │ │ │ +| return; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| | │ │ │ │ │ +| // we only received the header, no data | │ │ │ │ │ +| if (recv_buffer.empty()) break; | │ │ │ │ │ +| | │ │ │ │ │ +| if (recv_buffer.size() < front_request.length) break; | │ │ │ │ │ +| | │ │ │ │ │ +| // if the response is chunked, we need to receive the last | │ │ │ │ │ +| // terminating chunk and the tail headers before we can proceed | │ │ │ │ │ +|_ _ _ _i_f_ _(_m___p_a_r_s_e_r_._c_h_u_n_k_e_d___e_n_c_o_d_i_n_g_(_)_ _&_&_ _m___c_h_u_n_k___p_o_s_ _>_=_ _0_)_ _b_r_e_a_k_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_s_e_s_s_i_o_n___h_a_n_d_l_e_._c_p_p_:_4_8_5_ _|_i_n_ _C_+_+_1_4_,_ _u_s_e_ _u_n_i_q_u_e___p_t_r_ _a_n_d_ _m_o_v_e_ _i_t_ _i_n_t_o_ _t_h_e_ _l_a_m_b_d_a_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** iinn CC++++1144,, uussee uunniiqquuee__ppttrr aanndd mmoovvee iitt iinnttoo tthhee llaammbbddaa ********** | │ │ │ │ │ |****** ....//ssrrcc//sseessssiioonn__hhaannddllee..ccpppp::448855 ****** | │ │ │ │ │ |async_add_torrent(add_torrent_params(params)); | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ | void session_handle::async_add_torrent(add_torrent_params&& params) | │ │ │ │ │ @@ -10463,280 +9948,583 @@ │ │ │ │ │ | p.save_path = save_path; | │ │ │ │ │ | if (resume_data.type() != entry::undefined_t) | │ │ │ │ │ | { | │ │ │ │ │ | bencode(std::back_inserter(p.resume_data), resume_data); | │ │ │ │ │ | } | │ │ │ │ │ | p.storage_mode = storage_mode; | │ │ │ │ │ |_ _ _i_f_ _(_a_d_d___p_a_u_s_e_d_)_ _p_._f_l_a_g_s_ _|_=_ _a_d_d___t_o_r_r_e_n_t___p_a_r_a_m_s_:_:_f_l_a_g___p_a_u_s_e_d_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_t_o_r_r_e_n_t___h_a_n_d_l_e_._c_p_p_:_5_8_9_ _|_s_u_p_p_o_r_t_ _m_o_v_i_n_g_ _f_i_l_e_s_ _i_n_t_o_ _t_h_i_s_ _c_a_l_l_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** ssuuppppoorrtt mmoovviinngg ffiilleess iinnttoo tthhiiss ccaallll ********** | │ │ │ │ │ -|****** ....//ssrrcc//ttoorrrreenntt__hhaannddllee..ccpppp::558899 ****** | │ │ │ │ │ -|auto retp = &prio; | │ │ │ │ │ -| sync_call(&torrent::piece_priorities, retp); | │ │ │ │ │ -| std::vector ret; | │ │ │ │ │ -| ret.reserve(prio.size()); | │ │ │ │ │ -| for (auto p : prio) | │ │ │ │ │ -| ret.push_back(int(static_cast(p))); | │ │ │ │ │ -| return ret; | │ │ │ │ │ +|relevance 0|_._._/_s_r_c_/_p_a_r_t___f_i_l_e_._c_p_p_:_3_0_0 |what do we do if someone is currently reading from the disk from this piece? does it matter? Since we won't actively erase the data | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_f_r_o_m_ _d_i_s_k_,_ _b_u_t_ _i_t_ _m_a_y_ _b_e_ _o_v_e_r_w_r_i_t_t_e_n_ _s_o_o_n_,_ _i_t_'_s_ _p_r_o_b_a_b_l_y_ _n_o_t_ _t_h_a_t_ _b_i_g_ _o_f_ _a_ _d_e_a_l_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** wwhhaatt ddoo wwee ddoo iiff ssoommeeoonnee iiss ccuurrrreennttllyy rreeaaddiinngg ffrroomm tthhee ddiisskk ffrroomm tthhiiss ppiieeccee?? ddooeess iitt mmaatttteerr?? SSiinnccee wwee wwoonn''tt aaccttiivveellyy eerraassee tthhee ddaattaa ffrroomm ddiisskk,, bbuutt iitt mmaayy bbee oovveerrwwrriitttteenn | │ │ │ │ │ +|ssoooonn,, iitt''ss pprroobbaabbllyy nnoott tthhaatt bbiigg ooff aa ddeeaall ********** | │ │ │ │ │ +|****** ....//ssrrcc//ppaarrtt__ffiillee..ccpppp::330000 ****** | │ │ │ │ │ +|create_directories(m_path, ec); | │ │ │ │ │ +| if (ec) return {}; | │ │ │ │ │ +| return aux::file_handle(fn, 0, mode); | │ │ │ │ │ +| } | │ │ │ │ │ +| return {}; | │ │ │ │ │ +| } | │ │ │ │ │ | } | │ │ │ │ │ -|#endif | │ │ │ │ │ -| | │ │ │ │ │ -| void torrent_handle::file_priority(file_index_t index, download_priority_t priority) const | │ │ │ │ │ +| catch (storage_error const& e) | │ │ │ │ │ | { | │ │ │ │ │ -| async_call(&torrent::set_file_priority, index, priority); | │ │ │ │ │ +| ec = e.ec; | │ │ │ │ │ +| return {}; | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -| download_priority_t torrent_handle::file_priority(file_index_t index) const | │ │ │ │ │ +| void part_file::free_piece(piece_index_t const piece) | │ │ │ │ │ | { | │ │ │ │ │ -| return sync_call_ret(dont_download, &torrent::file_priority, index); | │ │ │ │ │ -| } | │ │ │ │ │ +| std::lock_guard l(m_mutex); | │ │ │ │ │ | | │ │ │ │ │ -|void torrent_handle::prioritize_files(std::vector const& files) const | │ │ │ │ │ -|{ | │ │ │ │ │ -| async_call(&torrent::prioritize_files | │ │ │ │ │ -| , static_cast const&>(files)); | │ │ │ │ │ +| auto const i = m_piece_map.find(piece); | │ │ │ │ │ +| if (i == m_piece_map.end()) return; | │ │ │ │ │ +| | │ │ │ │ │ +| | │ │ │ │ │ +|m_free_slots.push_back(i->second); | │ │ │ │ │ +| m_piece_map.erase(i); | │ │ │ │ │ +| m_dirty_metadata = true; | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -| std::vector torrent_handle::get_file_priorities() const | │ │ │ │ │ +| void part_file::move_partfile(std::string const& path, error_code& ec) | │ │ │ │ │ | { | │ │ │ │ │ -| aux::vector ret; | │ │ │ │ │ -| auto retp = &ret; | │ │ │ │ │ -| sync_call(&torrent::file_priorities, retp); | │ │ │ │ │ -| return TORRENT_RVO(ret); | │ │ │ │ │ -| } | │ │ │ │ │ +| std::lock_guard l(m_mutex); | │ │ │ │ │ | | │ │ │ │ │ -|#if TORRENT_ABI_VERSION == 1 | │ │ │ │ │ +| flush_metadata_impl(ec); | │ │ │ │ │ +| if (ec) return; | │ │ │ │ │ | | │ │ │ │ │ -|// ============ start deprecation =============== | │ │ │ │ │ +| if (!m_piece_map.empty()) | │ │ │ │ │ +| { | │ │ │ │ │ +| std::string old_path = combine_path(m_path, m_name); | │ │ │ │ │ +| std::string new_path = combine_path(path, m_name); | │ │ │ │ │ | | │ │ │ │ │ -| void torrent_handle::prioritize_files(std::vector const& files) const | │ │ │ │ │ -| { | │ │ │ │ │ -| aux::vector file_prio; | │ │ │ │ │ -| file_prio.reserve(files.size()); | │ │ │ │ │ -| for (auto const p : files) { | │ │ │ │ │ -| file_prio.push_back(download_priority_t(static_cast(p))); | │ │ │ │ │ +| rename(old_path, new_path, ec); | │ │ │ │ │ +| if (ec == boost::system::errc::no_such_file_or_directory) | │ │ │ │ │ +| ec.clear(); | │ │ │ │ │ +| | │ │ │ │ │ +| if (ec) | │ │ │ │ │ +| { | │ │ │ │ │ +| storage_error se; | │ │ │ │ │ +| aux::copy_file(old_path, new_path, se); | │ │ │ │ │ +| ec = se.ec; | │ │ │ │ │ +| if (ec) return; | │ │ │ │ │ +| remove(old_path, ec); | │ │ │ │ │ +| } | │ │ │ │ │ +|_ _ _}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_p_a_r_t___f_i_l_e_._c_p_p_:_4_1_2_ _ _ _ _ _ _|_i_n_s_t_e_a_d_ _o_f_ _r_e_b_u_i_l_d_i_n_g_ _t_h_e_ _w_h_o_l_e_ _f_i_l_e_ _h_e_a_d_e_r_ _a_n_d_ _f_l_u_s_h_i_n_g_ _i_t_,_ _u_p_d_a_t_e_ _t_h_e_ _s_l_o_t_ _e_n_t_r_i_e_s_ _a_s_ _w_e_ _g_o_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** iinnsstteeaadd ooff rreebbuuiillddiinngg tthhee wwhhoollee ffiillee hheeaaddeerr aanndd fflluusshhiinngg iitt,, uuppddaattee tthhee sslloott eennttrriieess aass wwee ggoo ********** | │ │ │ │ │ +|****** ....//ssrrcc//ppaarrtt__ffiillee..ccpppp::441122 ****** | │ │ │ │ │ +|TORRENT_ASSERT(j->second == slot); | │ │ │ │ │ +| m_free_slots.push_back(j->second); | │ │ │ │ │ +| m_piece_map.erase(j); | │ │ │ │ │ +| m_dirty_metadata = true; | │ │ │ │ │ +| } | │ │ │ │ │ +| } | │ │ │ │ │ +| } | │ │ │ │ │ +| file_offset += block_to_copy; | │ │ │ │ │ +| piece_offset = 0; | │ │ │ │ │ +| size -= block_to_copy; | │ │ │ │ │ | } | │ │ │ │ │ -| async_call(&torrent::prioritize_files, file_prio); | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -| std::vector torrent_handle::file_priorities() const | │ │ │ │ │ +| void part_file::flush_metadata(error_code& ec) | │ │ │ │ │ | { | │ │ │ │ │ -|_ _ _a_u_x_:_:_v_e_c_t_o_r_<_d_o_w_n_l_o_a_d___p_r_i_o_r_i_t_y___t_,_ _f_i_l_e___i_n_d_e_x___t_>_ _p_r_i_o_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_s_r_c_/_k_a_d_e_m_l_i_a_/_n_o_d_e___i_d_._c_p_p_:_6_6|it's a little bit weird to return 159 - leading zeroes. It should probably be 160 - leading zeroes, but all other code in here is | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_t_u_n_e_d_ _t_o_ _t_h_i_s_ _e_x_p_e_c_t_a_t_i_o_n_ _n_o_w_,_ _a_n_d_ _i_t_ _d_o_e_s_n_'_t_ _r_e_a_l_l_y_ _m_a_t_t_e_r_ _(_o_t_h_e_r_ _t_h_a_n_ _c_o_m_p_l_e_x_i_t_y_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** iitt''ss aa lliittttllee bbiitt wweeiirrdd ttoo rreettuurrnn 115599 -- lleeaaddiinngg zzeerrooeess.. IItt sshhoouulldd pprroobbaabbllyy bbee 116600 -- lleeaaddiinngg zzeerrooeess,, bbuutt aallll ootthheerr ccooddee iinn hheerree iiss ttuunneedd ttoo tthhiiss eexxppeeccttaattiioonn nnooww,, aanndd iitt | │ │ │ │ │ -|ddooeessnn''tt rreeaallllyy mmaatttteerr ((ootthheerr tthhaann ccoommpplleexxiittyy)) ********** | │ │ │ │ │ -|****** ....//ssrrcc//kkaaddeemmlliiaa//nnooddee__iidd..ccpppp::6666 ****** | │ │ │ │ │ -|// returns the distance between the two nodes | │ │ │ │ │ -|// using the kademlia XOR-metric | │ │ │ │ │ -|node_id distance(node_id const& n1, node_id const& n2) | │ │ │ │ │ -|{ | │ │ │ │ │ -| return n1 ^ n2; | │ │ │ │ │ -|} | │ │ │ │ │ +| std::lock_guard l(m_mutex); | │ │ │ │ │ | | │ │ │ │ │ -|// returns true if: distance(n1, ref) < distance(n2, ref) | │ │ │ │ │ -|bool compare_ref(node_id const& n1, node_id const& n2, node_id const& ref) | │ │ │ │ │ -|{ | │ │ │ │ │ -| node_id const lhs = n1 ^ ref; | │ │ │ │ │ -| node_id const rhs = n2 ^ ref; | │ │ │ │ │ -| return lhs < rhs; | │ │ │ │ │ -|} | │ │ │ │ │ +| flush_metadata_impl(ec); | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -|// returns n in: 2^n <= distance(n1, n2) < 2^(n+1) | │ │ │ │ │ -|// useful for finding out which bucket a node belongs to | │ │ │ │ │ -|int distance_exp(node_id const& n1, node_id const& n2) | │ │ │ │ │ +|void part_file::flush_metadata_impl(error_code& ec) | │ │ │ │ │ |{ | │ │ │ │ │ -|return std::max(159 - distance(n1, n2).count_leading_zeroes(), 0); | │ │ │ │ │ -|} | │ │ │ │ │ +| // do we need to flush the metadata? | │ │ │ │ │ +| if (m_dirty_metadata == false) return; | │ │ │ │ │ | | │ │ │ │ │ -|int min_distance_exp(node_id const& n1, std::vector const& ids) | │ │ │ │ │ -|{ | │ │ │ │ │ -| TORRENT_ASSERT(ids.size() > 0); | │ │ │ │ │ +| if (m_piece_map.empty()) | │ │ │ │ │ +| { | │ │ │ │ │ +| // if we don't have any pieces left in the | │ │ │ │ │ +| // part file, remove it | │ │ │ │ │ +| std::string const p = combine_path(m_path, m_name); | │ │ │ │ │ +| remove(p, ec); | │ │ │ │ │ | | │ │ │ │ │ -| int min = 160; // see distance_exp for the why of this constant | │ │ │ │ │ -| for (auto const& node_id : ids) | │ │ │ │ │ -| { | │ │ │ │ │ -| min = std::min(min, distance_exp(n1, node_id)); | │ │ │ │ │ -| } | │ │ │ │ │ +| if (ec == boost::system::errc::no_such_file_or_directory) | │ │ │ │ │ +| ec.clear(); | │ │ │ │ │ +| return; | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -| return min; | │ │ │ │ │ -|} | │ │ │ │ │ +| auto f = open_file(aux::open_mode::write | aux::open_mode::hidden, ec); | │ │ │ │ │ +| if (ec) return; | │ │ │ │ │ | | │ │ │ │ │ -|node_id generate_id_impl(address const& ip_, std::uint32_t r) | │ │ │ │ │ -|{ | │ │ │ │ │ -| std::uint8_t* ip = nullptr; | │ │ │ │ │ +| std::vector header(static_cast(m_header_size)); | │ │ │ │ │ | | │ │ │ │ │ -| static std::uint8_t const v4mask[] = { 0x03, 0x0f, 0x3f, 0xff }; | │ │ │ │ │ -| static std::uint8_t const v6mask[] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff }; | │ │ │ │ │ -| std::uint8_t const* mask = nullptr; | │ │ │ │ │ -| int num_octets = 0; | │ │ │ │ │ +| using namespace libtorrent::aux; | │ │ │ │ │ | | │ │ │ │ │ -| address_v4::bytes_type b4{}; | │ │ │ │ │ -| address_v6::bytes_type b6{}; | │ │ │ │ │ -| if (ip_.is_v6()) | │ │ │ │ │ -| { | │ │ │ │ │ -| b6 = ip_.to_v6().to_bytes(); | │ │ │ │ │ -|_ _ _i_p_ _=_ _b_6_._d_a_t_a_(_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_k_a_d_e_m_l_i_a_/_i_t_e_m_._c_p_p_:_1_4_3_ _ _|_i_m_p_l_e_m_e_n_t_ _c_t_o_r_ _f_o_r_ _e_n_t_r_y_ _f_r_o_m_ _b_d_e_c_o_d_e___n_o_d_e_?_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** iimmpplleemmeenntt ccttoorr ffoorr eennttrryy ffrroomm bbddeeccooddee__nnooddee?? ********** | │ │ │ │ │ -|****** ....//ssrrcc//kkaaddeemmlliiaa//iitteemm..ccpppp::114433 ****** | │ │ │ │ │ -|, secret_key const& sk) | │ │ │ │ │ -|{ | │ │ │ │ │ -| char str[1200]; | │ │ │ │ │ -| int const len = canonical_string(v, seq, salt, str); | │ │ │ │ │ +| char* ptr = header.data(); | │ │ │ │ │ +| write_uint32(m_max_pieces, ptr); | │ │ │ │ │ +| write_uint32(m_piece_size, ptr); | │ │ │ │ │ | | │ │ │ │ │ -| return ed25519_sign({str, len}, pk, sk); | │ │ │ │ │ -|} | │ │ │ │ │ +| for (piece_index_t piece(0); piece < piece_index_t(m_max_pieces); ++piece) | │ │ │ │ │ +| { | │ │ │ │ │ +|_ _ _ _a_u_t_o_ _c_o_n_s_t_ _i_ _=_ _m___p_i_e_c_e___m_a_p_._f_i_n_d_(_p_i_e_c_e_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_s_r_c_/_u_t_p___s_o_c_k_e_t___m_a_n_a_g_e_r_._c_p_p_:|this should not be heap allocated, sockets should be movable | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_2_0_4_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tthhiiss sshhoouulldd nnoott bbee hheeaapp aallllooccaatteedd,, ssoocckkeettss sshhoouulldd bbee mmoovvaabbllee ********** | │ │ │ │ │ +|****** ....//ssrrcc//uuttpp__ssoocckkeett__mmaannaaggeerr..ccpppp::220044 ****** | │ │ │ │ │ +|// UTP_LOGV("incoming packet id:%d source:%s\n", id, print_endpoint(ep).c_str()); | │ │ │ │ │ | | │ │ │ │ │ -|item::item(public_key const& pk, span salt) | │ │ │ │ │ -| : m_salt(salt.data(), static_cast(salt.size())) | │ │ │ │ │ -| , m_pk(pk) | │ │ │ │ │ -| , m_mutable(true) | │ │ │ │ │ -|{} | │ │ │ │ │ +| if (!m_sett.get_bool(settings_pack::enable_incoming_utp)) | │ │ │ │ │ +| return false; | │ │ │ │ │ | | │ │ │ │ │ -|item::item(entry v) | │ │ │ │ │ -| : m_value(std::move(v)) | │ │ │ │ │ -|{} | │ │ │ │ │ +| // if not found, see if it's a SYN packet, if it is, | │ │ │ │ │ +| // create a new utp_stream | │ │ │ │ │ +| if (ph->get_type() == ST_SYN) | │ │ │ │ │ +| { | │ │ │ │ │ +| // possible SYN flood. Just ignore | │ │ │ │ │ +| if (int(m_utp_sockets.size()) > m_sett.get_int(settings_pack::connections_limit) * 2) | │ │ │ │ │ +| return false; | │ │ │ │ │ | | │ │ │ │ │ -|item::item(bdecode_node const& v) | │ │ │ │ │ -|{ | │ │ │ │ │ -|m_value = v; | │ │ │ │ │ -|} | │ │ │ │ │ +| TORRENT_ASSERT(m_new_connection == -1); | │ │ │ │ │ +| // create the new socket with this ID | │ │ │ │ │ +| m_new_connection = id; | │ │ │ │ │ | | │ │ │ │ │ -|item::item(entry v, span salt | │ │ │ │ │ -| , sequence_number const seq, public_key const& pk, secret_key const& sk) | │ │ │ │ │ -|{ | │ │ │ │ │ -| assign(std::move(v), salt, seq, pk, sk); | │ │ │ │ │ -|} | │ │ │ │ │ +|// UTP_LOGV("not found, new connection id:%d\n", m_new_connection); | │ │ │ │ │ | | │ │ │ │ │ -|void item::assign(entry v) | │ │ │ │ │ -|{ | │ │ │ │ │ -| m_mutable = false; | │ │ │ │ │ -| m_value = std::move(v); | │ │ │ │ │ -|} | │ │ │ │ │ +|aux::socket_type c(aux::instantiate_connection(m_ios, aux::proxy_settings(), m_ssl_context, this, true, false)); | │ │ │ │ │ | | │ │ │ │ │ -|void item::assign(entry v, span salt | │ │ │ │ │ -| , sequence_number const seq, public_key const& pk, secret_key const& sk) | │ │ │ │ │ -|{ | │ │ │ │ │ -| std::array buffer; | │ │ │ │ │ -| int const bsize = bencode(buffer.begin(), v); | │ │ │ │ │ -| TORRENT_ASSERT(bsize <= 1000); | │ │ │ │ │ -| m_sig = sign_mutable_item(span(buffer).first(bsize) | │ │ │ │ │ -| , salt, seq, pk, sk); | │ │ │ │ │ -| m_salt.assign(salt.data(), static_cast(salt.size())); | │ │ │ │ │ -| m_pk = pk; | │ │ │ │ │ -| m_seq = seq; | │ │ │ │ │ -| m_mutable = true; | │ │ │ │ │ -| m_value = std::move(v); | │ │ │ │ │ +| utp_stream* str = nullptr; | │ │ │ │ │ +|#ifdef TORRENT_SSL_PEERS | │ │ │ │ │ +| if (is_ssl(c)) | │ │ │ │ │ +| str = &boost::get>(c).next_layer(); | │ │ │ │ │ +| else | │ │ │ │ │ +|#endif | │ │ │ │ │ +| str = boost::get(&c); | │ │ │ │ │ +| | │ │ │ │ │ +| TORRENT_ASSERT(str); | │ │ │ │ │ +| int const mtu = mtu_for_dest(ep.address()); | │ │ │ │ │ +| str->get_impl()->init_mtu(mtu); | │ │ │ │ │ +| str->get_impl()->m_sock = std::move(socket); | │ │ │ │ │ +| bool const ret = str->get_impl()->incoming_packet(p, ep, receive_time); | │ │ │ │ │ +| if (!ret) return false; | │ │ │ │ │ +| m_last_socket = str->get_impl(); | │ │ │ │ │ +| m_cb(std::move(c)); | │ │ │ │ │ +| // the connection most likely changed its connection ID here | │ │ │ │ │ +| // we need to move it to the correct ID | │ │ │ │ │ +| return true; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| if (ph->get_type() == ST_RESET) return false; | │ │ │ │ │ +| | │ │ │ │ │ +| // #error send reset | │ │ │ │ │ +| | │ │ │ │ │ +| return false; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +|_ _v_o_i_d_ _u_t_p___s_o_c_k_e_t___m_a_n_a_g_e_r_:_:_s_u_b_s_c_r_i_b_e___w_r_i_t_a_b_l_e_(_u_t_p___s_o_c_k_e_t___i_m_p_l_*_ _s_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_c_h_o_k_e_r_._c_p_p_:_2_5_5_ _ _ _ _ _ _ _ _ _|_m_a_k_e_ _c_o_n_f_i_g_u_r_a_b_l_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** mmaakkee ccoonnffiigguurraabbllee ********** | │ │ │ │ │ +|****** ....//ssrrcc//cchhookkeerr..ccpppp::225555 ****** | │ │ │ │ │ +|// first reset the number of unchoke slots, because we'll calculate | │ │ │ │ │ +| // it purely based on the current state of our peers. | │ │ │ │ │ +| upload_slots = 0; | │ │ │ │ │ +| | │ │ │ │ │ +| int rate_threshold = sett.get_int(settings_pack::rate_choker_initial_threshold); | │ │ │ │ │ +| | │ │ │ │ │ +| std::sort(peers.begin(), peers.end() | │ │ │ │ │ +| , [](peer_connection const* lhs, peer_connection const* rhs) | │ │ │ │ │ +| { return upload_rate_compare(lhs, rhs); }); | │ │ │ │ │ +| | │ │ │ │ │ +| for (auto const* p : peers) | │ │ │ │ │ +| { | │ │ │ │ │ +| int const rate = int(p->uploaded_in_last_round() | │ │ │ │ │ +| * 1000 / total_milliseconds(unchoke_interval)); | │ │ │ │ │ +| | │ │ │ │ │ +| // always have at least 1 unchoke slot | │ │ │ │ │ +| if (rate < rate_threshold) break; | │ │ │ │ │ +| | │ │ │ │ │ +| ++upload_slots; | │ │ │ │ │ +| | │ │ │ │ │ +|rate_threshold += 2048; | │ │ │ │ │ |} | │ │ │ │ │ +| ++upload_slots; | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -|_v_o_i_d_ _i_t_e_m_:_:_a_s_s_i_g_n_(_b_d_e_c_o_d_e___n_o_d_e_ _c_o_n_s_t_&_ _v_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_s_r_c_/_k_a_d_e_m_l_i_a_/ |pick the closest node rather than the first | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_d_h_t___t_r_a_c_k_e_r_._c_p_p_:_3_1_7_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** ppiicckk tthhee cclloosseesstt nnooddee rraatthheerr tthhaann tthhee ffiirrsstt ********** | │ │ │ │ │ -|****** ....//ssrrcc//kkaaddeemmlliiaa//ddhhtt__ttrraacckkeerr..ccpppp::331177 ****** | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ -| m_log->log(dht_logger::tracker, "*** new write key*** %d nodes" | │ │ │ │ │ -| , int(m_nodes.size())); | │ │ │ │ │ +| // sorts the peers that are eligible for unchoke by download rate and | │ │ │ │ │ +| // secondary by total upload. The reason for this is, if all torrents are | │ │ │ │ │ +| // being seeded, the download rate will be 0, and the peers we have sent | │ │ │ │ │ +| // the least to should be unchoked | │ │ │ │ │ +| | │ │ │ │ │ +| // we use partial sort here, because we only care about the top | │ │ │ │ │ +| // upload_slots peers. | │ │ │ │ │ +| | │ │ │ │ │ +| int const slots = std::min(upload_slots, int(peers.size())); | │ │ │ │ │ +| | │ │ │ │ │ +| if (sett.get_int(settings_pack::seed_choking_algorithm) | │ │ │ │ │ +| == settings_pack::round_robin) | │ │ │ │ │ +| { | │ │ │ │ │ +| int const pieces = sett.get_int(settings_pack::seeding_piece_quota); | │ │ │ │ │ +| | │ │ │ │ │ +| std::nth_element(peers.begin(), peers.begin() | │ │ │ │ │ +| + slots, peers.end() | │ │ │ │ │ +| , [pieces](peer_connection const* lhs, peer_connection const* rhs) | │ │ │ │ │ +| { return unchoke_compare_rr(lhs, rhs, pieces); }); | │ │ │ │ │ +| } | │ │ │ │ │ +| else if (sett.get_int(settings_pack::seed_choking_algorithm) | │ │ │ │ │ +| == settings_pack::fastest_upload) | │ │ │ │ │ +| { | │ │ │ │ │ +| std::nth_element(peers.begin(), peers.begin() | │ │ │ │ │ +| + slots, peers.end() | │ │ │ │ │ +|_ _ _ _ _,_ _[_]_(_p_e_e_r___c_o_n_n_e_c_t_i_o_n_ _c_o_n_s_t_*_ _l_h_s_,_ _p_e_e_r___c_o_n_n_e_c_t_i_o_n_ _c_o_n_s_t_*_ _r_h_s_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_t_o_r_r_e_n_t___p_e_e_r_._c_p_p_:_1_8_1_ _ _ _|_h_o_w_ _d_o_ _w_e_ _d_e_a_l_ _w_i_t_h_ _o_u_r_ _e_x_t_e_r_n_a_l_ _a_d_d_r_e_s_s_ _c_h_a_n_g_i_n_g_?_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** hhooww ddoo wwee ddeeaall wwiitthh oouurr eexxtteerrnnaall aaddddrreessss cchhaannggiinngg?? ********** | │ │ │ │ │ +|****** ....//ssrrcc//ttoorrrreenntt__ppeeeerr..ccpppp::118811 ****** | │ │ │ │ │ +|// connections. If it fails, we'll | │ │ │ │ │ +| // retry with encryption | │ │ │ │ │ +| , pe_support(false) | │ │ │ │ │ +|#endif | │ │ │ │ │ +| , is_v6_addr(false) | │ │ │ │ │ +|#if TORRENT_USE_I2P | │ │ │ │ │ +| , is_i2p_addr(false) | │ │ │ │ │ |#endif | │ │ │ │ │ +| , on_parole(false) | │ │ │ │ │ +| , banned(false) | │ │ │ │ │ +| , supports_utp(true) // assume peers support utp | │ │ │ │ │ +| , confirmed_supports_utp(false) | │ │ │ │ │ +| , supports_holepunch(false) | │ │ │ │ │ +| , web_seed(false) | │ │ │ │ │ +| , protocol_v2(false) | │ │ │ │ │ +| {} | │ │ │ │ │ +| | │ │ │ │ │ +| std::uint32_t torrent_peer::rank(external_ip const& external, int external_port) const | │ │ │ │ │ +| { | │ │ │ │ │ +| TORRENT_ASSERT(in_use); | │ │ │ │ │ +|if (peer_rank == 0) | │ │ │ │ │ +|peer_rank = peer_priority( | │ │ │ │ │ +| tcp::endpoint(external.external_address(this->address()), std::uint16_t(external_port)) | │ │ │ │ │ +| , tcp::endpoint(this->address(), this->port)); | │ │ │ │ │ +| return peer_rank; | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -| void dht_tracker::update_storage_node_ids() | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ +| std::string torrent_peer::to_string() const | │ │ │ │ │ | { | │ │ │ │ │ -| std::vector ids; | │ │ │ │ │ -| for (auto& n : m_nodes) | │ │ │ │ │ -| ids.push_back(n.second.dht.nid()); | │ │ │ │ │ -| m_storage.update_node_ids(ids); | │ │ │ │ │ +| TORRENT_ASSERT(in_use); | │ │ │ │ │ +|#if TORRENT_USE_I2P | │ │ │ │ │ +| if (is_i2p_addr) return dest().to_string(); | │ │ │ │ │ +|#endif // TORRENT_USE_I2P | │ │ │ │ │ +| return address().to_string(); | │ │ │ │ │ | } | │ │ │ │ │ +|#endif | │ │ │ │ │ | | │ │ │ │ │ -| node* dht_tracker::get_node(node_id const& id, std::string const& family_name) | │ │ │ │ │ +| std::int64_t torrent_peer::total_download() const | │ │ │ │ │ | { | │ │ │ │ │ -| TORRENT_UNUSED(id); | │ │ │ │ │ -| for (auto& n : m_nodes) | │ │ │ │ │ +| TORRENT_ASSERT(in_use); | │ │ │ │ │ +| if (connection != nullptr) | │ │ │ │ │ | { | │ │ │ │ │ -|if (n.second.dht.protocol_family_name() == family_name) | │ │ │ │ │ -|return &n.second.dht; | │ │ │ │ │ +| TORRENT_ASSERT(prev_amount_download == 0); | │ │ │ │ │ +| return connection->statistics().total_payload_download(); | │ │ │ │ │ +| } | │ │ │ │ │ +| else | │ │ │ │ │ +| { | │ │ │ │ │ +| return std::int64_t(prev_amount_download) << 10; | │ │ │ │ │ | } | │ │ │ │ │ +|_ _}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_h_a_s_h___p_i_c_k_e_r_._c_p_p_:_3_0_9_ _ _ _ _|_u_s_e_ _s_t_r_u_c_t_u_r_e_d_ _b_i_n_d_i_n_g_s_ _i_n_ _C_+_+_1_7_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** uussee ssttrruuccttuurreedd bbiinnddiinnggss iinn CC++++1177 ********** | │ │ │ │ │ +|****** ....//ssrrcc//hhaasshh__ppiicckkeerr..ccpppp::330099 ****** | │ │ │ │ │ +|, int const offset, sha256_hash const& h) | │ │ │ │ │ +| { | │ │ │ │ │ +| TORRENT_ASSERT(offset >= 0); | │ │ │ │ │ +| auto const f = m_files.file_index_at_piece(piece); | │ │ │ │ │ | | │ │ │ │ │ -| return nullptr; | │ │ │ │ │ +| if (m_files.pad_file_at(f)) | │ │ │ │ │ +| return { set_block_hash_result::result::success, 0, 0 }; | │ │ │ │ │ +| | │ │ │ │ │ +| auto& merkle_tree = m_merkle_trees[f]; | │ │ │ │ │ +| piece_index_t const file_first_piece = m_files.piece_index_at_file(f); | │ │ │ │ │ +| std::int64_t const block_offset = static_cast(piece) * std::int64_t(m_files.piece_length()) | │ │ │ │ │ +| + offset - m_files.file_offset(f); | │ │ │ │ │ +| int const block_index = aux::numeric_cast(block_offset / default_block_size); | │ │ │ │ │ +| | │ │ │ │ │ +| if (h.is_all_zeros()) | │ │ │ │ │ +| { | │ │ │ │ │ +| TORRENT_ASSERT_FAIL(); | │ │ │ │ │ +| return set_block_hash_result::block_hash_failed(); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +|aux::merkle_tree::set_block_result result; | │ │ │ │ │ +|int leafs_index; | │ │ │ │ │ +| int leafs_size; | │ │ │ │ │ +| std::tie(result, leafs_index, leafs_size) = merkle_tree.set_block(block_index, h); | │ │ │ │ │ +| | │ │ │ │ │ +| if (result == aux::merkle_tree::set_block_result::unknown) | │ │ │ │ │ +| return set_block_hash_result::unknown(); | │ │ │ │ │ +| if (result == aux::merkle_tree::set_block_result::block_hash_failed) | │ │ │ │ │ +| return set_block_hash_result::block_hash_failed(); | │ │ │ │ │ +| | │ │ │ │ │ +| auto const status = (result == aux::merkle_tree::set_block_result::hash_failed) | │ │ │ │ │ +| ? set_block_hash_result::result::piece_hash_failed | │ │ │ │ │ +| : set_block_hash_result::result::success; | │ │ │ │ │ +| | │ │ │ │ │ +| int const blocks_per_piece = m_files.piece_length() / default_block_size; | │ │ │ │ │ +| | │ │ │ │ │ +| return { status | │ │ │ │ │ +| , int(leafs_index - static_cast(piece - file_first_piece) * blocks_per_piece) | │ │ │ │ │ +| , std::min(leafs_size, m_files.file_num_pieces(f) * blocks_per_piece - leafs_index) }; | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -| void dht_tracker::get_peers(sha1_hash const& ih | │ │ │ │ │ -| , std::function const&)> f) | │ │ │ │ │ +| void hash_picker::hashes_rejected(hash_request const& req) | │ │ │ │ │ | { | │ │ │ │ │ -| for (auto& n : m_nodes) | │ │ │ │ │ -| n.second.dht.get_peers(ih, f, {}, {}); | │ │ │ │ │ +| TORRENT_ASSERT(req.base == m_piece_layer && req.index % 512 == 0); | │ │ │ │ │ +| | │ │ │ │ │ +| for (int i = req.index; i < req.index + req.count; i += 512) | │ │ │ │ │ +| { | │ │ │ │ │ +| m_piece_hash_requested[req.file][i / 512].last_request = min_time(); | │ │ │ │ │ +| --m_piece_hash_requested[req.file][i / 512].num_requests; | │ │ │ │ │ +|_ _ _}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_s_r_c_/_d_i_s_a_b_l_e_d___d_i_s_k___i_o_._c_p_p_: |it would be nice to return a valid hash of zeroes here | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_1_0_6_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** iitt wwoouulldd bbee nniiccee ttoo rreettuurrnn aa vvaalliidd hhaasshh ooff zzeerrooeess hheerree ********** | │ │ │ │ │ +|****** ....//ssrrcc//ddiissaabblleedd__ddiisskk__iioo..ccpppp::110066 ****** | │ │ │ │ │ +|}); | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -| void dht_tracker::announce(sha1_hash const& ih, int listen_port | │ │ │ │ │ -| , announce_flags_t const flags | │ │ │ │ │ -| , std::function const&)> f) | │ │ │ │ │ +| bool async_write(storage_index_t | │ │ │ │ │ +| , peer_request const& r | │ │ │ │ │ +| , char const*, std::shared_ptr | │ │ │ │ │ +| , std::function handler | │ │ │ │ │ +| , disk_job_flags_t) override | │ │ │ │ │ | { | │ │ │ │ │ -| for (auto& n : m_nodes) | │ │ │ │ │ -| n.second.dht.announce(ih, listen_port, flags, f); | │ │ │ │ │ +| TORRENT_ASSERT(r.length <= default_block_size); | │ │ │ │ │ +| TORRENT_UNUSED(r); | │ │ │ │ │ +| | │ │ │ │ │ +| post(m_ios, [h = std::move(handler)] { h(storage_error{}); }); | │ │ │ │ │ +| return false; | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -| void dht_tracker::sample_infohashes(udp::endpoint const& ep, sha1_hash const& target | │ │ │ │ │ -| , std::function | │ │ │ │ │ -| , std::vector>)> f) | │ │ │ │ │ +| void async_hash(storage_index_t | │ │ │ │ │ +| , piece_index_t piece, span, disk_job_flags_t | │ │ │ │ │ +| , std::function handler) override | │ │ │ │ │ | { | │ │ │ │ │ -| for (auto& n : m_nodes) | │ │ │ │ │ -| { | │ │ │ │ │ -|_ _ _ _i_f_ _(_e_p_._p_r_o_t_o_c_o_l_(_)_ _!_=_ _(_n_._f_i_r_s_t_._g_e_t___e_x_t_e_r_n_a_l___a_d_d_r_e_s_s_(_)_._i_s___v_4_(_)_ _?_ _u_d_p_:_:_v_4_(_)_ _:_ _u_d_p_:_:_v_6_(_)_)_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_s_r_c_/_k_a_d_e_m_l_i_a_/_p_u_t___d_a_t_a_._c_p_p_: |what if o is not an instance of put_data_observer? This need to be redesigned for better type safety. | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_9_2_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** wwhhaatt iiff oo iiss nnoott aann iinnssttaannccee ooff ppuutt__ddaattaa__oobbsseerrvveerr?? TThhiiss nneeeedd ttoo bbee rreeddeessiiggnneedd ffoorr bbeetttteerr ttyyppee ssaaffeettyy.. ********** | │ │ │ │ │ -|****** ....//ssrrcc//kkaaddeemmlliiaa//ppuutt__ddaattaa..ccpppp::9922 ****** | │ │ │ │ │ -|} | │ │ │ │ │ +|post(m_ios, [h = std::move(handler), piece] { h(piece, sha1_hash{}, storage_error{}); }); | │ │ │ │ │ |} | │ │ │ │ │ | | │ │ │ │ │ -|void put_data::done() | │ │ │ │ │ -|{ | │ │ │ │ │ -| m_done = true; | │ │ │ │ │ +| void async_hash2(storage_index_t, piece_index_t piece, int | │ │ │ │ │ +| , disk_job_flags_t | │ │ │ │ │ +| , std::function handler) override | │ │ │ │ │ +| { | │ │ │ │ │ +| post(m_ios, [h = std::move(handler), piece]() { h(piece, sha256_hash{}, storage_error{}); }); | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ -| get_node().observer()->log(dht_logger::traversal, "[%u] %s DONE, response %d, timeout %d" | │ │ │ │ │ -| , id(), name(), num_responses(), num_timeouts()); | │ │ │ │ │ +| void async_move_storage(storage_index_t | │ │ │ │ │ +| , std::string p, move_flags_t | │ │ │ │ │ +| , std::function handler) override | │ │ │ │ │ +| { | │ │ │ │ │ +| post(m_ios, [h = std::move(handler), path = std::move(p)] () mutable | │ │ │ │ │ +| { h(status_t::no_error, std::move(path), storage_error{}); }); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| void async_release_files(storage_index_t, std::function handler) override | │ │ │ │ │ +| { | │ │ │ │ │ +| post(m_ios, [h = std::move(handler)] { h(); }); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| void async_delete_files(storage_index_t | │ │ │ │ │ +| , remove_flags_t, std::function handler) override | │ │ │ │ │ +| { | │ │ │ │ │ +| post(m_ios, [h = std::move(handler)] { h(storage_error{}); }); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| void async_check_files(storage_index_t | │ │ │ │ │ +|_ _ _,_ _a_d_d___t_o_r_r_e_n_t___p_a_r_a_m_s_ _c_o_n_s_t_*_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_m_m_a_p___d_i_s_k___i_o_._c_p_p_:_5_7_8_ _ _ _|_i_n_ _t_h_e_ _f_u_t_u_r_e_,_ _p_r_o_p_a_g_a_t_e_ _e_x_c_e_p_t_i_o_n_s_ _b_a_c_k_ _t_o_ _t_h_e_ _h_a_n_d_l_e_r_s_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** iinn tthhee ffuuttuurree,, pprrooppaaggaattee eexxcceeppttiioonnss bbaacckk ttoo tthhee hhaannddlleerrss ********** | │ │ │ │ │ +|****** ....//ssrrcc//mmmmaapp__ddiisskk__iioo..ccpppp::557788 ****** | │ │ │ │ │ +|#if DEBUG_DISK_THREAD | │ │ │ │ │ +| { | │ │ │ │ │ +| std::unique_lock l(m_job_mutex); | │ │ │ │ │ +| | │ │ │ │ │ +| DLOG("perform_job job: %s ( %s%s) piece: %d offset: %d outstanding: %d\n" | │ │ │ │ │ +| , job_action_name[j->action] | │ │ │ │ │ +| , (j->flags & mmap_disk_job::fence) ? "fence ": "" | │ │ │ │ │ +| , (j->flags & mmap_disk_job::force_copy) ? "force_copy ": "" | │ │ │ │ │ +| , static_cast(j->piece), j->d.io.offset | │ │ │ │ │ +| , j->storage ? j->storage->num_outstanding_jobs() : -1); | │ │ │ │ │ +| } | │ │ │ │ │ |#endif | │ │ │ │ │ | | │ │ │ │ │ -| m_put_callback(m_data, num_responses()); | │ │ │ │ │ -| traversal_algorithm::done(); | │ │ │ │ │ -|} | │ │ │ │ │ +| std::shared_ptr storage = j->storage; | │ │ │ │ │ | | │ │ │ │ │ -|bool put_data::invoke(observer_ptr o) | │ │ │ │ │ -|{ | │ │ │ │ │ -| if (m_done) return false; | │ │ │ │ │ +| TORRENT_ASSERT(static_cast(j->action) < int(job_functions.size())); | │ │ │ │ │ | | │ │ │ │ │ -|auto* po = static_cast(o.get()); | │ │ │ │ │ +| m_stats_counters.inc_stats_counter(counters::num_running_disk_jobs, 1); | │ │ │ │ │ | | │ │ │ │ │ -| entry e; | │ │ │ │ │ -| e["y"] = "q"; | │ │ │ │ │ -| e["q"] = "put"; | │ │ │ │ │ -| entry& a = e["a"]; | │ │ │ │ │ -| a["v"] = m_data.value(); | │ │ │ │ │ -| a["token"] = po->m_token; | │ │ │ │ │ -| if (m_data.is_mutable()) | │ │ │ │ │ -| { | │ │ │ │ │ -| a["k"] = m_data.pk().bytes; | │ │ │ │ │ -| a["seq"] = m_data.seq().value; | │ │ │ │ │ -| a["sig"] = m_data.sig().bytes; | │ │ │ │ │ -| if (!m_data.salt().empty()) | │ │ │ │ │ +| // call disk function | │ │ │ │ │ +|status_t ret = status_t::no_error; | │ │ │ │ │ +|try | │ │ │ │ │ | { | │ │ │ │ │ -| a["salt"] = m_data.salt(); | │ │ │ │ │ +| int const idx = static_cast(j->action); | │ │ │ │ │ +| ret = (this->*(job_functions[static_cast(idx)]))(j); | │ │ │ │ │ | } | │ │ │ │ │ +| catch (boost::system::system_error const& err) | │ │ │ │ │ +| { | │ │ │ │ │ +| ret = status_t::fatal_disk_error; | │ │ │ │ │ +| j->error.ec = err.code(); | │ │ │ │ │ +| j->error.operation = operation_t::exception; | │ │ │ │ │ +| } | │ │ │ │ │ +| catch (std::bad_alloc const&) | │ │ │ │ │ +| { | │ │ │ │ │ +| ret = status_t::fatal_disk_error; | │ │ │ │ │ +| j->error.ec = errors::no_memory; | │ │ │ │ │ +| j->error.operation = operation_t::exception; | │ │ │ │ │ +| } | │ │ │ │ │ +| catch (std::exception const&) | │ │ │ │ │ +| { | │ │ │ │ │ +| ret = status_t::fatal_disk_error; | │ │ │ │ │ +| j->error.ec = boost::asio::error::fault; | │ │ │ │ │ +| j->error.operation = operation_t::exception; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| // note that -2 errors are OK | │ │ │ │ │ +| TORRENT_ASSERT(ret != status_t::fatal_disk_error | │ │ │ │ │ +| || (j->error.ec && j->error.operation != operation_t::unknown)); | │ │ │ │ │ +| | │ │ │ │ │ +|_ _ _m___s_t_a_t_s___c_o_u_n_t_e_r_s_._i_n_c___s_t_a_t_s___c_o_u_n_t_e_r_(_c_o_u_n_t_e_r_s_:_:_n_u_m___r_u_n_n_i_n_g___d_i_s_k___j_o_b_s_,_ _-_1_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_s_r_c_/_m_m_a_p___d_i_s_k___i_o_._c_p_p_:_1_0_1_7 |this is potentially very expensive. One way to solve it would be to have a fence for just this one piece. but it hardly seems worth | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_t_h_e_ _c_o_m_p_l_e_x_i_t_y_ _a_n_d_ _c_o_s_t_ _j_u_s_t_ _f_o_r_ _t_h_e_ _e_d_g_e_ _c_a_s_e_ _o_f_ _r_e_c_e_i_v_i_n_g_ _a_ _c_o_r_r_u_p_t_ _p_i_e_c_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** tthhiiss iiss ppootteennttiiaallllyy vveerryy eexxppeennssiivvee.. OOnnee wwaayy ttoo ssoollvvee iitt wwoouulldd bbee ttoo hhaavvee aa ffeennccee ffoorr jjuusstt tthhiiss oonnee ppiieeccee.. bbuutt iitt hhaarrddllyy sseeeemmss wwoorrtthh tthhee ccoommpplleexxiittyy aanndd ccoosstt jjuusstt ffoorr tthhee | │ │ │ │ │ +|eeddggee ccaassee ooff rreecceeiivviinngg aa ccoorrrruupptt ppiieeccee ********** | │ │ │ │ │ +|****** ....//ssrrcc//mmmmaapp__ddiisskk__iioo..ccpppp::11001177 ****** | │ │ │ │ │ +|aux::mmap_disk_job* j = m_job_pool.allocate_job(aux::job_action_t::file_priority); | │ │ │ │ │ +| j->storage = m_torrents[storage]->shared_from_this(); | │ │ │ │ │ +| j->argument = std::move(prios); | │ │ │ │ │ +| j->callback = std::move(handler); | │ │ │ │ │ +| | │ │ │ │ │ +| add_fence_job(j); | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -| m_node.stats_counters().inc_stats_counter(counters::dht_put_out); | │ │ │ │ │ +| void mmap_disk_io::async_clear_piece(storage_index_t const storage | │ │ │ │ │ +| , piece_index_t const index, std::function handler) | │ │ │ │ │ +| { | │ │ │ │ │ +| aux::mmap_disk_job* j = m_job_pool.allocate_job(aux::job_action_t::clear_piece); | │ │ │ │ │ +| j->storage = m_torrents[storage]->shared_from_this(); | │ │ │ │ │ +| j->piece = index; | │ │ │ │ │ +| j->callback = std::move(handler); | │ │ │ │ │ | | │ │ │ │ │ -| return m_node.m_rpc.invoke(e, o->target_ep(), o); | │ │ │ │ │ +| // regular jobs are not guaranteed to be executed in-order | │ │ │ │ │ +| // since clear piece must guarantee that all write jobs that | │ │ │ │ │ +| // have been issued finish before the clear piece job completes | │ │ │ │ │ +| | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_s_r_c_/_m_m_a_p___d_i_s_k___i_o_._c_p_p_:_1_0_2_2 |Perhaps the job queue could be traversed and all jobs for this piece could be cancelled. If there are no threads currently writing | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_t_o_ _t_h_i_s_ _p_i_e_c_e_,_ _w_e_ _c_o_u_l_d_ _s_k_i_p_ _t_h_e_ _f_e_n_c_e_ _a_l_t_o_g_e_t_h_e_r_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** PPeerrhhaappss tthhee jjoobb qquueeuuee ccoouulldd bbee ttrraavveerrsseedd aanndd aallll jjoobbss ffoorr tthhiiss ppiieeccee ccoouulldd bbee ccaanncceelllleedd.. IIff tthheerree aarree nnoo tthhrreeaaddss ccuurrrreennttllyy wwrriittiinngg ttoo tthhiiss ppiieeccee,, wwee ccoouulldd sskkiipp tthhee ffeennccee| │ │ │ │ │ +|aallttooggeetthheerr ********** | │ │ │ │ │ +|****** ....//ssrrcc//mmmmaapp__ddiisskk__iioo..ccpppp::11002222 ****** | │ │ │ │ │ +|j->storage = m_torrents[storage]->shared_from_this(); | │ │ │ │ │ +| j->argument = std::move(prios); | │ │ │ │ │ +| j->callback = std::move(handler); | │ │ │ │ │ +| | │ │ │ │ │ +| add_fence_job(j); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| void mmap_disk_io::async_clear_piece(storage_index_t const storage | │ │ │ │ │ +| , piece_index_t const index, std::function handler) | │ │ │ │ │ +| { | │ │ │ │ │ +| aux::mmap_disk_job* j = m_job_pool.allocate_job(aux::job_action_t::clear_piece); | │ │ │ │ │ +| j->storage = m_torrents[storage]->shared_from_this(); | │ │ │ │ │ +| j->piece = index; | │ │ │ │ │ +| j->callback = std::move(handler); | │ │ │ │ │ +| | │ │ │ │ │ +| // regular jobs are not guaranteed to be executed in-order | │ │ │ │ │ +| // since clear piece must guarantee that all write jobs that | │ │ │ │ │ +| // have been issued finish before the clear piece job completes | │ │ │ │ │ +| | │ │ │ │ │ +| | │ │ │ │ │ +|add_fence_job(j); | │ │ │ │ │ |} | │ │ │ │ │ | | │ │ │ │ │ -|_}_ _}_ _/_/_ _n_a_m_e_s_p_a_c_e_ _l_i_b_t_o_r_r_e_n_t_:_:_d_h_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +| status_t mmap_disk_io::do_hash(aux::mmap_disk_job* j) | │ │ │ │ │ +| { | │ │ │ │ │ +| // we're not using a cache. This is the simple path | │ │ │ │ │ +| // just read straight from the file | │ │ │ │ │ +| TORRENT_ASSERT(m_magic == 0x1337); | │ │ │ │ │ +| | │ │ │ │ │ +| bool const v1 = bool(j->flags & disk_interface::v1_hash); | │ │ │ │ │ +| bool const v2 = !j->d.h.block_hashes.empty(); | │ │ │ │ │ +| | │ │ │ │ │ +| int const piece_size = v1 ? j->storage->files().piece_size(j->piece) : 0; | │ │ │ │ │ +| int const piece_size2 = v2 ? j->storage->files().piece_size2(j->piece) : 0; | │ │ │ │ │ +| int const blocks_in_piece = v1 ? (piece_size + default_block_size - 1) / default_block_size : 0; | │ │ │ │ │ +| int const blocks_in_piece2 = v2 ? j->storage->files().blocks_in_piece2(j->piece) : 0; | │ │ │ │ │ +| aux::open_mode_t const file_mode = file_mode_for_job(j); | │ │ │ │ │ +| | │ │ │ │ │ +| TORRENT_ASSERT(!v2 || int(j->d.h.block_hashes.size()) >= blocks_in_piece2); | │ │ │ │ │ +| TORRENT_ASSERT(v1 || v2); | │ │ │ │ │ +| | │ │ │ │ │ +| hasher h; | │ │ │ │ │ +| int ret = 0; | │ │ │ │ │ +| int offset = 0; | │ │ │ │ │ +| int const blocks_to_read = std::max(blocks_in_piece, blocks_in_piece2); | │ │ │ │ │ +| time_point const start_time = clock_type::now(); | │ │ │ │ │ +| for (int i = 0; i < blocks_to_read; ++i) | │ │ │ │ │ +| { | │ │ │ │ │ +| bool const v2_block = i < blocks_in_piece2; | │ │ │ │ │ +| | │ │ │ │ │ +|_ _ _ _D_L_O_G_(_"_d_o___h_a_s_h_:_ _r_e_a_d_i_n_g_ _(_p_i_e_c_e_:_ _%_d_ _b_l_o_c_k_:_ _%_d_)_\_n_"_,_ _i_n_t_(_j_-_>_p_i_e_c_e_)_,_ _i_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_u_t___m_e_t_a_d_a_t_a_._c_p_p_:_2_8_1_ _ _ _ _|_w_e_ _r_e_a_l_l_y_ _n_e_e_d_ _t_o_ _i_n_c_r_e_m_e_n_t_ _t_h_e_ _r_e_f_c_o_u_n_t_e_r_ _o_n_ _t_h_e_ _t_o_r_r_e_n_t_ _w_h_i_l_e_ _t_h_i_s_ _b_u_f_f_e_r_ _i_s_ _s_t_i_l_l_ _i_n_ _t_h_e_ _p_e_e_r_'_s_ _s_e_n_d_ _b_u_f_f_e_r_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** wwee rreeaallllyy nneeeedd ttoo iinnccrreemmeenntt tthhee rreeffccoouunntteerr oonn tthhee ttoorrrreenntt wwhhiillee tthhiiss bbuuffffeerr iiss ssttiillll iinn tthhee ppeeeerr''ss sseenndd bbuuffffeerr ********** | │ │ │ │ │ +|****** ....//ssrrcc//uutt__mmeettaaddaattaa..ccpppp::228811 ****** | │ │ │ │ │ +|int const offset = piece * 16 * 1024; | │ │ │ │ │ +| metadata = m_tp.metadata().data() + offset; | │ │ │ │ │ +| metadata_piece_size = std::min( | │ │ │ │ │ +| int(m_tp.metadata().size()) - offset, 16 * 1024); | │ │ │ │ │ +| TORRENT_ASSERT(metadata_piece_size > 0); | │ │ │ │ │ +| TORRENT_ASSERT(offset >= 0); | │ │ │ │ │ +| TORRENT_ASSERT(offset + metadata_piece_size <= m_tp.metadata().size()); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| char msg[200]; | │ │ │ │ │ +| char* header = msg; | │ │ │ │ │ +| char* p = &msg[6]; | │ │ │ │ │ +| int const len = bencode(p, e); | │ │ │ │ │ +| int const total_size = 2 + len + metadata_piece_size; | │ │ │ │ │ +| namespace io = aux; | │ │ │ │ │ +| io::write_uint32(total_size, header); | │ │ │ │ │ +| io::write_uint8(bt_peer_connection::msg_extended, header); | │ │ │ │ │ +| io::write_uint8(m_message_index, header); | │ │ │ │ │ +| | │ │ │ │ │ +| m_pc.send_buffer({msg, len + 6}); | │ │ │ │ │ +|if (metadata_piece_size) | │ │ │ │ │ +|{ | │ │ │ │ │ +| m_pc.append_const_send_buffer( | │ │ │ │ │ +| span(const_cast(metadata), metadata_piece_size), metadata_piece_size); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| m_pc.stats_counters().inc_stats_counter(counters::num_outgoing_extended); | │ │ │ │ │ +| m_pc.stats_counters().inc_stats_counter(counters::num_outgoing_metadata); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| bool on_extended(int const length | │ │ │ │ │ +| , int const extended_msg, span body) override | │ │ │ │ │ +| { | │ │ │ │ │ +| if (extended_msg != 2) return false; | │ │ │ │ │ +| if (m_message_index == 0) return false; | │ │ │ │ │ +| | │ │ │ │ │ +| if (length > 17 * 1024) | │ │ │ │ │ +| { | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ +| m_pc.peer_log(peer_log_alert::incoming_message, "UT_METADATA" | │ │ │ │ │ +| , "packet too big %d", length); | │ │ │ │ │ +|#endif | │ │ │ │ │ +| m_pc.disconnect(errors::invalid_metadata_message, operation_t::bittorrent, peer_connection_interface::peer_error); | │ │ │ │ │ +| return true; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| if (!m_pc.packet_finished()) return true; | │ │ │ │ │ +| | │ │ │ │ │ +| error_code ec; | │ │ │ │ │ +| bdecode_node msg = bdecode(body, ec); | │ │ │ │ │ +|_ _ _ _i_f_ _(_m_s_g_._t_y_p_e_(_)_ _!_=_ _b_d_e_c_o_d_e___n_o_d_e_:_:_d_i_c_t___t_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_k_a_d_e_m_l_i_a_/_n_o_d_e_._c_p_p_:_1_1_7_7_ _|_k_e_e_p_ _t_h_e_ _r_e_t_u_r_n_e_d_ _v_a_l_u_e_ _t_o_ _p_a_s_s_ _a_s_ _a_ _l_i_m_i_t_ _t_o_ _w_r_i_t_e___n_o_d_e_s___e_n_t_r_i_e_s_ _w_h_e_n_ _i_m_p_l_e_m_e_n_t_e_d_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** kkeeeepp tthhee rreettuurrnneedd vvaalluuee ttoo ppaassss aass aa lliimmiitt ttoo wwrriittee__nnooddeess__eennttrriieess wwhheenn iimmpplleemmeenntteedd ********** | │ │ │ │ │ |****** ....//ssrrcc//kkaaddeemmlliiaa//nnooddee..ccpppp::11117777 ****** | │ │ │ │ │ |} | │ │ │ │ │ | } | │ │ │ │ │ | else if (query == "sample_infohashes") | │ │ │ │ │ | { | │ │ │ │ │ @@ -10978,315 +10766,226 @@ │ │ │ │ │ | && m_buckets.back().replacements.empty()) | │ │ │ │ │ | { | │ │ │ │ │ | m_buckets.erase(m_buckets.end() - 1); | │ │ │ │ │ | } | │ │ │ │ │ |} | │ │ │ │ │ | | │ │ │ │ │ |_v_o_i_d_ _r_o_u_t_i_n_g___t_a_b_l_e_:_:_r_e_m_o_v_e___n_o_d_e_(_n_o_d_e___e_n_t_r_y_*_ _n_,_ _b_u_c_k_e_t___t_*_ _b_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |make this a string_view | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_i_2_p___s_t_r_e_a_m_._h_p_p_:_5_3_9_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** mmaakkee tthhiiss aa ssttrriinngg__vviieeww ********** | │ │ │ │ │ -|****** ....//iinncclluuddee//lliibbttoorrrreenntt//ii22pp__ssttrreeaamm..hhpppp::553399 ****** | │ │ │ │ │ -| char tmp[20]; | │ │ │ │ │ -| aux::random_bytes(tmp); | │ │ │ │ │ -| m_session_id.resize(sizeof(tmp)*2); | │ │ │ │ │ -| aux::to_hex(tmp, &m_session_id[0]); | │ │ │ │ │ +|relevance 0|_._._/_s_r_c_/_k_a_d_e_m_l_i_a_/_n_o_d_e___i_d_._c_p_p_:_6_6|it's a little bit weird to return 159 - leading zeroes. It should probably be 160 - leading zeroes, but all other code in here is | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_t_u_n_e_d_ _t_o_ _t_h_i_s_ _e_x_p_e_c_t_a_t_i_o_n_ _n_o_w_,_ _a_n_d_ _i_t_ _d_o_e_s_n_'_t_ _r_e_a_l_l_y_ _m_a_t_t_e_r_ _(_o_t_h_e_r_ _t_h_a_n_ _c_o_m_p_l_e_x_i_t_y_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** iitt''ss aa lliittttllee bbiitt wweeiirrdd ttoo rreettuurrnn 115599 -- lleeaaddiinngg zzeerrooeess.. IItt sshhoouulldd pprroobbaabbllyy bbee 116600 -- lleeaaddiinngg zzeerrooeess,, bbuutt aallll ootthheerr ccooddee iinn hheerree iiss ttuunneedd ttoo tthhiiss eexxppeeccttaattiioonn nnooww,, aanndd iitt | │ │ │ │ │ +|ddooeessnn''tt rreeaallllyy mmaatttteerr ((ootthheerr tthhaann ccoommpplleexxiittyy)) ********** | │ │ │ │ │ +|****** ....//ssrrcc//kkaaddeemmlliiaa//nnooddee__iidd..ccpppp::6666 ****** | │ │ │ │ │ +|// returns the distance between the two nodes | │ │ │ │ │ +|// using the kademlia XOR-metric | │ │ │ │ │ +|node_id distance(node_id const& n1, node_id const& n2) | │ │ │ │ │ +|{ | │ │ │ │ │ +| return n1 ^ n2; | │ │ │ │ │ +|} | │ │ │ │ │ | | │ │ │ │ │ -| m_sam_socket = std::make_shared(m_io_service); | │ │ │ │ │ -| m_sam_socket->set_proxy(m_hostname, m_port); | │ │ │ │ │ -| m_sam_socket->set_command(i2p_stream::cmd_create_session); | │ │ │ │ │ -| m_sam_socket->set_session_id(m_session_id.c_str()); | │ │ │ │ │ -| m_sam_socket->set_session_options(session_options); | │ │ │ │ │ +|// returns true if: distance(n1, ref) < distance(n2, ref) | │ │ │ │ │ +|bool compare_ref(node_id const& n1, node_id const& n2, node_id const& ref) | │ │ │ │ │ +|{ | │ │ │ │ │ +| node_id const lhs = n1 ^ ref; | │ │ │ │ │ +| node_id const rhs = n2 ^ ref; | │ │ │ │ │ +| return lhs < rhs; | │ │ │ │ │ +|} | │ │ │ │ │ | | │ │ │ │ │ -| ADD_OUTSTANDING_ASYNC("i2p_stream::on_sam_connect"); | │ │ │ │ │ -| m_sam_socket->async_connect(tcp::endpoint(), wrap_allocator( | │ │ │ │ │ -| [this,s=m_sam_socket](error_code const& ec, Handler hn) { | │ │ │ │ │ -| on_sam_connect(ec, s, std::move(hn)); | │ │ │ │ │ -| }, std::move(handler))); | │ │ │ │ │ -| } | │ │ │ │ │ -| void close(error_code&); | │ │ │ │ │ +|// returns n in: 2^n <= distance(n1, n2) < 2^(n+1) | │ │ │ │ │ +|// useful for finding out which bucket a node belongs to | │ │ │ │ │ +|int distance_exp(node_id const& n1, node_id const& n2) | │ │ │ │ │ +|{ | │ │ │ │ │ +|return std::max(159 - distance(n1, n2).count_leading_zeroes(), 0); | │ │ │ │ │ +|} | │ │ │ │ │ | | │ │ │ │ │ -|char const* session_id() const { return m_session_id.c_str(); } | │ │ │ │ │ -|std::string const& local_endpoint() const { return m_i2p_local_endpoint; } | │ │ │ │ │ +|int min_distance_exp(node_id const& n1, std::vector const& ids) | │ │ │ │ │ +|{ | │ │ │ │ │ +| TORRENT_ASSERT(ids.size() > 0); | │ │ │ │ │ | | │ │ │ │ │ -| template | │ │ │ │ │ -| void async_name_lookup(char const* name, Handler handler) | │ │ │ │ │ +| int min = 160; // see distance_exp for the why of this constant | │ │ │ │ │ +| for (auto const& node_id : ids) | │ │ │ │ │ | { | │ │ │ │ │ -| if (m_state == sam_idle && m_name_lookup.empty() && is_open()) | │ │ │ │ │ -| do_name_lookup(name, std::move(handler)); | │ │ │ │ │ -| else | │ │ │ │ │ -| m_name_lookup.emplace_back(std::string(name) | │ │ │ │ │ -| , std::move(handler)); | │ │ │ │ │ +| min = std::min(min, distance_exp(n1, node_id)); | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -|private: | │ │ │ │ │ -| | │ │ │ │ │ -| template | │ │ │ │ │ -| void on_sam_connect(error_code const& ec, std::shared_ptr, Handler h) | │ │ │ │ │ -| { | │ │ │ │ │ -| COMPLETE_ASYNC("i2p_stream::on_sam_connect"); | │ │ │ │ │ -| m_state = sam_idle; | │ │ │ │ │ -| | │ │ │ │ │ -| if (ec) | │ │ │ │ │ -| { | │ │ │ │ │ -| h(ec); | │ │ │ │ │ -| return; | │ │ │ │ │ -| } | │ │ │ │ │ +| return min; | │ │ │ │ │ +|} | │ │ │ │ │ | | │ │ │ │ │ -| do_name_lookup("ME", wrap_allocator( | │ │ │ │ │ -| [this](error_code const& e, char const* dst, Handler hn) { | │ │ │ │ │ -| set_local_endpoint(e, dst, std::move(hn)); | │ │ │ │ │ -|_ _ _ _}_,_ _s_t_d_:_:_m_o_v_e_(_h_)_)_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |support batched adding of block hashes for reduced overhead? | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_h_a_s_h___p_i_c_k_e_r_._h_p_p_:_1_5_5_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** ssuuppppoorrtt bbaattcchheedd aaddddiinngg ooff bblloocckk hhaasshheess ffoorr rreedduucceedd oovveerrhheeaadd?? ********** | │ │ │ │ │ -|****** ....//iinncclluuddee//lliibbttoorrrreenntt//hhaasshh__ppiicckkeerr..hhpppp::115555 ****** | │ │ │ │ │ -|// the number of hashes in the range | │ │ │ │ │ -| int count = 0; | │ │ │ │ │ -| int proof_layers = 0; | │ │ │ │ │ -| }; | │ │ │ │ │ +|node_id generate_id_impl(address const& ip_, std::uint32_t r) | │ │ │ │ │ +|{ | │ │ │ │ │ +| std::uint8_t* ip = nullptr; | │ │ │ │ │ | | │ │ │ │ │ -| // validates the hash_request, to ensure its invariant as well as matching | │ │ │ │ │ -| // the torrent's file_storage and the number of hashes accompanying the | │ │ │ │ │ -| // request | │ │ │ │ │ -| TORRENT_EXTRA_EXPORT | │ │ │ │ │ -| bool validate_hash_request(hash_request const& hr, file_storage const& fs); | │ │ │ │ │ +| static std::uint8_t const v4mask[] = { 0x03, 0x0f, 0x3f, 0xff }; | │ │ │ │ │ +| static std::uint8_t const v6mask[] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff }; | │ │ │ │ │ +| std::uint8_t const* mask = nullptr; | │ │ │ │ │ +| int num_octets = 0; | │ │ │ │ │ | | │ │ │ │ │ -| class TORRENT_EXTRA_EXPORT hash_picker | │ │ │ │ │ +| address_v4::bytes_type b4{}; | │ │ │ │ │ +| address_v6::bytes_type b6{}; | │ │ │ │ │ +| if (ip_.is_v6()) | │ │ │ │ │ | { | │ │ │ │ │ -| public: | │ │ │ │ │ -| hash_picker(file_storage const& files | │ │ │ │ │ -| , aux::vector& trees); | │ │ │ │ │ -| | │ │ │ │ │ -| hash_request pick_hashes(typed_bitfield const& pieces); | │ │ │ │ │ -| | │ │ │ │ │ -| add_hashes_result add_hashes(hash_request const& req, span hashes); | │ │ │ │ │ -|set_block_hash_result set_block_hash(piece_index_t piece, int offset, sha256_hash const& h); | │ │ │ │ │ -|void hashes_rejected(hash_request const& req); | │ │ │ │ │ -| void verify_block_hashes(piece_index_t index); | │ │ │ │ │ -| | │ │ │ │ │ -| // do we know the piece layer hash for a piece | │ │ │ │ │ -| bool have_hash(piece_index_t index) const; | │ │ │ │ │ -| // do we know all the block hashes for a file? | │ │ │ │ │ -| bool have_all(file_index_t file) const; | │ │ │ │ │ -| bool have_all() const; | │ │ │ │ │ -| bool piece_verified(piece_index_t piece) const; | │ │ │ │ │ +| b6 = ip_.to_v6().to_bytes(); | │ │ │ │ │ +|_ _ _i_p_ _=_ _b_6_._d_a_t_a_(_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_s_r_c_/_k_a_d_e_m_l_i_a_/_p_u_t___d_a_t_a_._c_p_p_: |what if o is not an instance of put_data_observer? This need to be redesigned for better type safety. | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_9_2_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** wwhhaatt iiff oo iiss nnoott aann iinnssttaannccee ooff ppuutt__ddaattaa__oobbsseerrvveerr?? TThhiiss nneeeedd ttoo bbee rreeddeessiiggnneedd ffoorr bbeetttteerr ttyyppee ssaaffeettyy.. ********** | │ │ │ │ │ +|****** ....//ssrrcc//kkaaddeemmlliiaa//ppuutt__ddaattaa..ccpppp::9922 ****** | │ │ │ │ │ +|} | │ │ │ │ │ +|} | │ │ │ │ │ | | │ │ │ │ │ -| int piece_layer() const { return m_piece_layer; } | │ │ │ │ │ +|void put_data::done() | │ │ │ │ │ +|{ | │ │ │ │ │ +| m_done = true; | │ │ │ │ │ | | │ │ │ │ │ -| private: | │ │ │ │ │ -| // returns the number of proof layers needed to verify the node's hash | │ │ │ │ │ -| int layers_to_verify(node_index idx) const; | │ │ │ │ │ -| int file_num_layers(file_index_t idx) const; | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ +| get_node().observer()->log(dht_logger::traversal, "[%u] %s DONE, response %d, timeout %d" | │ │ │ │ │ +| , id(), name(), num_responses(), num_timeouts()); | │ │ │ │ │ +|#endif | │ │ │ │ │ | | │ │ │ │ │ -| struct piece_hash_request | │ │ │ │ │ -| { | │ │ │ │ │ -| time_point last_request = min_time(); | │ │ │ │ │ -| int num_requests = 0; | │ │ │ │ │ -| bool have = false; | │ │ │ │ │ -| }; | │ │ │ │ │ +| m_put_callback(m_data, num_responses()); | │ │ │ │ │ +| traversal_algorithm::done(); | │ │ │ │ │ +|} | │ │ │ │ │ | | │ │ │ │ │ -| struct priority_block_request | │ │ │ │ │ -| { | │ │ │ │ │ -| priority_block_request(file_index_t const f, int const b) | │ │ │ │ │ -| : file(f), block(b) {} | │ │ │ │ │ -| file_index_t file; | │ │ │ │ │ -|_ _ _ _i_n_t_ _b_l_o_c_k_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |we could bind the socket here, since we know what the target endpoint is of the proxy | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_s_o_c_k_s_5___s_t_r_e_a_m_._h_p_p_:_1_9_7_ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** wwee ccoouulldd bbiinndd tthhee ssoocckkeett hheerree,, ssiinnccee wwee kknnooww wwhhaatt tthhee ttaarrggeett eennddppooiinntt iiss ooff tthhee pprrooxxyy ********** | │ │ │ │ │ -|****** ....//iinncclluuddee//lliibbttoorrrreenntt//ssoocckkss55__ssttrreeaamm..hhpppp::119977 ****** | │ │ │ │ │ -|}, std::move(handler))); | │ │ │ │ │ -| } | │ │ │ │ │ +|bool put_data::invoke(observer_ptr o) | │ │ │ │ │ +|{ | │ │ │ │ │ +| if (m_done) return false; | │ │ │ │ │ | | │ │ │ │ │ -|private: | │ │ │ │ │ +|auto* po = static_cast(o.get()); | │ │ │ │ │ | | │ │ │ │ │ -| template | │ │ │ │ │ -| void name_lookup(error_code const& e, tcp::resolver::results_type ips | │ │ │ │ │ -| , Handler h) | │ │ │ │ │ +| entry e; | │ │ │ │ │ +| e["y"] = "q"; | │ │ │ │ │ +| e["q"] = "put"; | │ │ │ │ │ +| entry& a = e["a"]; | │ │ │ │ │ +| a["v"] = m_data.value(); | │ │ │ │ │ +| a["token"] = po->m_token; | │ │ │ │ │ +| if (m_data.is_mutable()) | │ │ │ │ │ | { | │ │ │ │ │ -| COMPLETE_ASYNC("socks5_stream::name_lookup"); | │ │ │ │ │ -| if (handle_error(e, std::move(h))) return; | │ │ │ │ │ -| | │ │ │ │ │ -| auto i = ips.begin(); | │ │ │ │ │ -| if (!m_sock.is_open()) | │ │ │ │ │ +| a["k"] = m_data.pk().bytes; | │ │ │ │ │ +| a["seq"] = m_data.seq().value; | │ │ │ │ │ +| a["sig"] = m_data.sig().bytes; | │ │ │ │ │ +| if (!m_data.salt().empty()) | │ │ │ │ │ | { | │ │ │ │ │ -| error_code ec; | │ │ │ │ │ -| m_sock.open(i->endpoint().protocol(), ec); | │ │ │ │ │ -| if (handle_error(ec, std::move(h))) return; | │ │ │ │ │ +| a["salt"] = m_data.salt(); | │ │ │ │ │ | } | │ │ │ │ │ -| | │ │ │ │ │ -|ADD_OUTSTANDING_ASYNC("socks5_stream::connected"); | │ │ │ │ │ -|m_sock.async_connect(i->endpoint(), wrap_allocator( | │ │ │ │ │ -| [this](error_code const& ec, Handler hn) | │ │ │ │ │ -| { connected(ec, std::move(hn)); }, std::move(h))); | │ │ │ │ │ | } | │ │ │ │ │ | | │ │ │ │ │ -| template | │ │ │ │ │ -| void connected(error_code const& e, Handler h) | │ │ │ │ │ -| { | │ │ │ │ │ -| COMPLETE_ASYNC("socks5_stream::connected"); | │ │ │ │ │ -| if (handle_error(e, std::move(h))) return; | │ │ │ │ │ -| | │ │ │ │ │ -| using namespace libtorrent::aux; | │ │ │ │ │ -| if (m_version == 5) | │ │ │ │ │ -| { | │ │ │ │ │ -| // send SOCKS5 authentication methods | │ │ │ │ │ -| m_buffer.resize(m_user.empty()?3:4); | │ │ │ │ │ -| char* p = &m_buffer[0]; | │ │ │ │ │ -| write_uint8(5, p); // SOCKS VERSION 5 | │ │ │ │ │ -| if (m_user.empty()) | │ │ │ │ │ -| { | │ │ │ │ │ -| write_uint8(1, p); // 1 authentication method (no auth) | │ │ │ │ │ -| write_uint8(0, p); // no authentication | │ │ │ │ │ -| } | │ │ │ │ │ -| else | │ │ │ │ │ -| { | │ │ │ │ │ -| write_uint8(2, p); // 2 authentication methods | │ │ │ │ │ -| write_uint8(0, p); // no authentication | │ │ │ │ │ -| write_uint8(2, p); // username/password | │ │ │ │ │ -| } | │ │ │ │ │ -|_ _ _ _A_D_D___O_U_T_S_T_A_N_D_I_N_G___A_S_Y_N_C_(_"_s_o_c_k_s_5___s_t_r_e_a_m_:_:_h_a_n_d_s_h_a_k_e_1_"_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |move to aux | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_s_o_c_k_e_t___t_y_p_e_._h_p_p_:_6_0_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** mmoovvee ttoo aauuxx ********** | │ │ │ │ │ -|****** ....//iinncclluuddee//lliibbttoorrrreenntt//ssoocckkeett__ttyyppee..hhpppp::6600 ****** | │ │ │ │ │ -|namespace libtorrent { | │ │ │ │ │ -| | │ │ │ │ │ -|// A type describing kinds of sockets involved in various operations or events. | │ │ │ │ │ -|enum class socket_type_t : std::uint8_t { | │ │ │ │ │ -| tcp, | │ │ │ │ │ -| socks5, | │ │ │ │ │ -| http, | │ │ │ │ │ -| utp, | │ │ │ │ │ -| i2p, | │ │ │ │ │ -| tcp_ssl, | │ │ │ │ │ -| socks5_ssl, | │ │ │ │ │ -| http_ssl, | │ │ │ │ │ -| utp_ssl, | │ │ │ │ │ -| | │ │ │ │ │ -|#if TORRENT_ABI_VERSION <= 2 | │ │ │ │ │ -| udp TORRENT_DEPRECATED_ENUM = utp, | │ │ │ │ │ -|#endif | │ │ │ │ │ -|}; | │ │ │ │ │ -| | │ │ │ │ │ -|// return a short human readable name for types of socket | │ │ │ │ │ -|char const* socket_type_name(socket_type_t); | │ │ │ │ │ +| m_node.stats_counters().inc_stats_counter(counters::dht_put_out); | │ │ │ │ │ | | │ │ │ │ │ +| return m_node.m_rpc.invoke(e, o->target_ep(), o); | │ │ │ │ │ |} | │ │ │ │ │ | | │ │ │ │ │ -|_#_e_n_d_i_f_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |change the type to std::shared_ptr in C++17 it is used as if immutable, it cannot be const for technical reasons right now. | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_t_o_r_r_e_n_t___i_n_f_o_._h_p_p_:_7_2_9_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** cchhaannggee tthhee ttyyppee ttoo ssttdd::::sshhaarreedd__ppttrr iinn CC++++1177 iitt iiss uusseedd aass iiff iimmmmuuttaabbllee,, iitt ccaannnnoott bbee ccoonnsstt ffoorr tteecchhnniiccaall rreeaassoonnss rriigghhtt nnooww.. ********** | │ │ │ │ │ -|****** ....//iinncclluuddee//lliibbttoorrrreenntt//ttoorrrreenntt__iinnffoo..hhpppp::772299 ****** | │ │ │ │ │ -| // these are the collections from outside of the info-dict. These are | │ │ │ │ │ -| // owning strings, since we only keep the info-section around, these | │ │ │ │ │ -| // cannot be pointers into that buffer. | │ │ │ │ │ -| std::vector m_owned_collections; | │ │ │ │ │ -| | │ │ │ │ │ -|#if TORRENT_ABI_VERSION <= 2 | │ │ │ │ │ -| // if this is a merkle torrent, this is the merkle | │ │ │ │ │ -| // tree. It has space for merkle_num_nodes(merkle_num_leafs(num_pieces)) | │ │ │ │ │ -| // hashes | │ │ │ │ │ -| aux::vector m_merkle_tree; | │ │ │ │ │ +|_}_ _}_ _/_/_ _n_a_m_e_s_p_a_c_e_ _l_i_b_t_o_r_r_e_n_t_:_:_d_h_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_s_r_c_/_k_a_d_e_m_l_i_a_/ |pick the closest node rather than the first | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_d_h_t___t_r_a_c_k_e_r_._c_p_p_:_3_1_7_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** ppiicckk tthhee cclloosseesstt nnooddee rraatthheerr tthhaann tthhee ffiirrsstt ********** | │ │ │ │ │ +|****** ....//ssrrcc//kkaaddeemmlliiaa//ddhhtt__ttrraacckkeerr..ccpppp::331177 ****** | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ +| m_log->log(dht_logger::tracker, "*** new write key*** %d nodes" | │ │ │ │ │ +| , int(m_nodes.size())); | │ │ │ │ │ |#endif | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -| // v2 merkle tree for each file | │ │ │ │ │ -| // the actual hash buffers are always divisible by 32 (sha256_hash::size()) | │ │ │ │ │ -| aux::vector, file_index_t> m_piece_layers; | │ │ │ │ │ -| | │ │ │ │ │ -| // this is a copy of the info section from the torrent. | │ │ │ │ │ -| // it use maintained in this flat format in order to | │ │ │ │ │ -| // make it available through the metadata extension | │ │ │ │ │ -|boost::shared_array m_info_section; | │ │ │ │ │ -| | │ │ │ │ │ -| // if a comment is found in the torrent file | │ │ │ │ │ -| // this will be set to that comment | │ │ │ │ │ -| std::string m_comment; | │ │ │ │ │ -| | │ │ │ │ │ -| // an optional string naming the software used | │ │ │ │ │ -| // to create the torrent file | │ │ │ │ │ -| std::string m_created_by; | │ │ │ │ │ -| | │ │ │ │ │ -| // the info section parsed. points into m_info_section | │ │ │ │ │ -| // parsed lazily | │ │ │ │ │ -| mutable bdecode_node m_info_dict; | │ │ │ │ │ -| | │ │ │ │ │ -| // if a creation date is found in the torrent file | │ │ │ │ │ -| // this will be set to that, otherwise it'll be | │ │ │ │ │ -| // 1970, Jan 1 | │ │ │ │ │ -| std::time_t m_creation_date = 0; | │ │ │ │ │ -| | │ │ │ │ │ -| // the hash(es) that identify this torrent | │ │ │ │ │ -| info_hash_t m_info_hash; | │ │ │ │ │ +| void dht_tracker::update_storage_node_ids() | │ │ │ │ │ +| { | │ │ │ │ │ +| std::vector ids; | │ │ │ │ │ +| for (auto& n : m_nodes) | │ │ │ │ │ +| ids.push_back(n.second.dht.nid()); | │ │ │ │ │ +| m_storage.update_node_ids(ids); | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -| // this is the offset into the m_info_section buffer to the first byte of | │ │ │ │ │ -| // the first SHA-1 hash | │ │ │ │ │ -| std::int32_t m_piece_hashes = 0; | │ │ │ │ │ +| node* dht_tracker::get_node(node_id const& id, std::string const& family_name) | │ │ │ │ │ +| { | │ │ │ │ │ +| TORRENT_UNUSED(id); | │ │ │ │ │ +| for (auto& n : m_nodes) | │ │ │ │ │ +| { | │ │ │ │ │ +|if (n.second.dht.protocol_family_name() == family_name) | │ │ │ │ │ +|return &n.second.dht; | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -| // the number of bytes in m_info_section | │ │ │ │ │ -| std::int32_t m_info_section_size = 0; | │ │ │ │ │ +| return nullptr; | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -| // this is used when creating a torrent. If there's | │ │ │ │ │ -|_ _ _/_/_ _o_n_l_y_ _o_n_e_ _f_i_l_e_ _t_h_e_r_e_ _a_r_e_ _c_a_s_e_s_ _w_h_e_r_e_ _i_t_'_s_ _i_m_p_o_s_s_i_b_l_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |include the number of peers received from this tracker, at last announce | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_a_n_n_o_u_n_c_e___e_n_t_r_y_._h_p_p_:_7_6_ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** iinncclluuddee tthhee nnuummbbeerr ooff ppeeeerrss rreecceeiivveedd ffrroomm tthhiiss ttrraacckkeerr,, aatt llaasstt aannnnoouunnccee ********** | │ │ │ │ │ -|****** ....//iinncclluuddee//lliibbttoorrrreenntt//aannnnoouunnccee__eennttrryy..hhpppp::7766 ****** | │ │ │ │ │ -| struct TORRENT_EXPORT announce_infohash | │ │ │ │ │ +| void dht_tracker::get_peers(sha1_hash const& ih | │ │ │ │ │ +| , std::function const&)> f) | │ │ │ │ │ | { | │ │ │ │ │ -| // internal | │ │ │ │ │ -| TORRENT_UNEXPORT announce_infohash(); | │ │ │ │ │ -| | │ │ │ │ │ -| // if this tracker has returned an error or warning message | │ │ │ │ │ -| // that message is stored here | │ │ │ │ │ -| std::string message; | │ │ │ │ │ +| for (auto& n : m_nodes) | │ │ │ │ │ +| n.second.dht.get_peers(ih, f, {}, {}); | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -| // if this tracker failed the last time it was contacted | │ │ │ │ │ -| // this error code specifies what error occurred | │ │ │ │ │ -| error_code last_error; | │ │ │ │ │ +| void dht_tracker::announce(sha1_hash const& ih, int listen_port | │ │ │ │ │ +| , announce_flags_t const flags | │ │ │ │ │ +| , std::function const&)> f) | │ │ │ │ │ +| { | │ │ │ │ │ +| for (auto& n : m_nodes) | │ │ │ │ │ +| n.second.dht.announce(ih, listen_port, flags, f); | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -| // the time of next tracker announce | │ │ │ │ │ -| time_point32 next_announce = (time_point32::min)(); | │ │ │ │ │ +| void dht_tracker::sample_infohashes(udp::endpoint const& ep, sha1_hash const& target | │ │ │ │ │ +| , std::function | │ │ │ │ │ +| , std::vector>)> f) | │ │ │ │ │ +| { | │ │ │ │ │ +| for (auto& n : m_nodes) | │ │ │ │ │ +| { | │ │ │ │ │ +|_ _ _ _i_f_ _(_e_p_._p_r_o_t_o_c_o_l_(_)_ _!_=_ _(_n_._f_i_r_s_t_._g_e_t___e_x_t_e_r_n_a_l___a_d_d_r_e_s_s_(_)_._i_s___v_4_(_)_ _?_ _u_d_p_:_:_v_4_(_)_ _:_ _u_d_p_:_:_v_6_(_)_)_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_r_e_l_e_v_a_n_c_e_ _0_|_._._/_s_r_c_/_k_a_d_e_m_l_i_a_/_i_t_e_m_._c_p_p_:_1_4_3_ _ _|_i_m_p_l_e_m_e_n_t_ _c_t_o_r_ _f_o_r_ _e_n_t_r_y_ _f_r_o_m_ _b_d_e_c_o_d_e___n_o_d_e_?_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** iimmpplleemmeenntt ccttoorr ffoorr eennttrryy ffrroomm bbddeeccooddee__nnooddee?? ********** | │ │ │ │ │ +|****** ....//ssrrcc//kkaaddeemmlliiaa//iitteemm..ccpppp::114433 ****** | │ │ │ │ │ +|, secret_key const& sk) | │ │ │ │ │ +|{ | │ │ │ │ │ +| char str[1200]; | │ │ │ │ │ +| int const len = canonical_string(v, seq, salt, str); | │ │ │ │ │ | | │ │ │ │ │ -| // no announces before this time | │ │ │ │ │ -| time_point32 min_announce = (time_point32::min)(); | │ │ │ │ │ +| return ed25519_sign({str, len}, pk, sk); | │ │ │ │ │ +|} | │ │ │ │ │ | | │ │ │ │ │ +|item::item(public_key const& pk, span salt) | │ │ │ │ │ +| : m_salt(salt.data(), static_cast(salt.size())) | │ │ │ │ │ +| , m_pk(pk) | │ │ │ │ │ +| , m_mutable(true) | │ │ │ │ │ +|{} | │ │ │ │ │ | | │ │ │ │ │ -|// these are either -1 or the scrape information this tracker last | │ │ │ │ │ -| // responded with. *incomplete* is the current number of downloaders in | │ │ │ │ │ -| // the swarm, *complete* is the current number of seeds in the swarm and | │ │ │ │ │ -| // *downloaded* is the cumulative number of completed downloads of this | │ │ │ │ │ -| // torrent, since the beginning of time (from this tracker's point of | │ │ │ │ │ -| // view). | │ │ │ │ │ +|item::item(entry v) | │ │ │ │ │ +| : m_value(std::move(v)) | │ │ │ │ │ +|{} | │ │ │ │ │ | | │ │ │ │ │ -| // if this tracker has returned scrape data, these fields are filled in | │ │ │ │ │ -| // with valid numbers. Otherwise they are set to -1. ``incomplete`` counts | │ │ │ │ │ -| // the number of current downloaders. ``complete`` counts the number of | │ │ │ │ │ -| // current peers completed the download, or "seeds". ``downloaded`` is the | │ │ │ │ │ -| // cumulative number of completed downloads. | │ │ │ │ │ -| int scrape_incomplete = -1; | │ │ │ │ │ -| int scrape_complete = -1; | │ │ │ │ │ -| int scrape_downloaded = -1; | │ │ │ │ │ +|item::item(bdecode_node const& v) | │ │ │ │ │ +|{ | │ │ │ │ │ +|m_value = v; | │ │ │ │ │ +|} | │ │ │ │ │ | | │ │ │ │ │ -| // the number of times in a row we have failed to announce to this | │ │ │ │ │ -| // tracker. | │ │ │ │ │ -| std::uint8_t fails : 7; | │ │ │ │ │ +|item::item(entry v, span salt | │ │ │ │ │ +| , sequence_number const seq, public_key const& pk, secret_key const& sk) | │ │ │ │ │ +|{ | │ │ │ │ │ +| assign(std::move(v), salt, seq, pk, sk); | │ │ │ │ │ +|} | │ │ │ │ │ | | │ │ │ │ │ -| // true while we're waiting for a response from the tracker. | │ │ │ │ │ -| bool updating : 1; | │ │ │ │ │ +|void item::assign(entry v) | │ │ │ │ │ +|{ | │ │ │ │ │ +| m_mutable = false; | │ │ │ │ │ +| m_value = std::move(v); | │ │ │ │ │ +|} | │ │ │ │ │ | | │ │ │ │ │ -| // set to true when we get a valid response from an announce | │ │ │ │ │ -| // with event=started. If it is set, we won't send start in the subsequent | │ │ │ │ │ -| // announces. | │ │ │ │ │ -| bool start_sent : 1; | │ │ │ │ │ +|void item::assign(entry v, span salt | │ │ │ │ │ +| , sequence_number const seq, public_key const& pk, secret_key const& sk) | │ │ │ │ │ +|{ | │ │ │ │ │ +| std::array buffer; | │ │ │ │ │ +| int const bsize = bencode(buffer.begin(), v); | │ │ │ │ │ +| TORRENT_ASSERT(bsize <= 1000); | │ │ │ │ │ +| m_sig = sign_mutable_item(span(buffer).first(bsize) | │ │ │ │ │ +| , salt, seq, pk, sk); | │ │ │ │ │ +| m_salt.assign(salt.data(), static_cast(salt.size())); | │ │ │ │ │ +| m_pk = pk; | │ │ │ │ │ +| m_seq = seq; | │ │ │ │ │ +| m_mutable = true; | │ │ │ │ │ +| m_value = std::move(v); | │ │ │ │ │ +|} | │ │ │ │ │ | | │ │ │ │ │ -| // set to true when we send a event=completed. | │ │ │ │ │ -|_ _ _b_o_o_l_ _c_o_m_p_l_e_t_e___s_e_n_t_ _:_ _1_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|_v_o_i_d_ _i_t_e_m_:_:_a_s_s_i_g_n_(_b_d_e_c_o_d_e___n_o_d_e_ _c_o_n_s_t_&_ _v_)_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |make this a raw pointer. perhaps keep the shared_ptr around further down the object to maintain an owner | │ │ │ │ │ |_ _ _ _ _ _ _ _ _ _ _ _|_t_o_r_r_e_n_t_._h_p_p_:_2_8_0_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** mmaakkee tthhiiss aa rraaww ppooiinntteerr.. ppeerrhhaappss kkeeeepp tthhee sshhaarreedd__ppttrr aarroouunndd ffuurrtthheerr ddoowwnn tthhee oobbjjeecctt ttoo mmaaiinnttaaiinn aann oowwnneerr ********** | │ │ │ │ │ |****** ....//iinncclluuddee//lliibbttoorrrreenntt//ttoorrrreenntt..hhpppp::228800 ****** | │ │ │ │ │ |#endif | │ │ │ │ │ | }; | │ │ │ │ │ | | │ │ │ │ │ @@ -11552,14 +11251,68 @@ │ │ │ │ │ | // remember that this is an SSL torrent, so that we don't | │ │ │ │ │ | // accidentally start seeding it without any authentication. | │ │ │ │ │ | bool m_ssl_torrent:1; | │ │ │ │ │ | | │ │ │ │ │ | // this is set to true if we're trying to delete the | │ │ │ │ │ | // files belonging to it. When set, don't write any | │ │ │ │ │ |_ _ _/_/_ _m_o_r_e_ _b_l_o_c_k_s_ _t_o_ _d_i_s_k_!_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |change the type to std::shared_ptr in C++17 it is used as if immutable, it cannot be const for technical reasons right now. | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_t_o_r_r_e_n_t___i_n_f_o_._h_p_p_:_7_2_9_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** cchhaannggee tthhee ttyyppee ttoo ssttdd::::sshhaarreedd__ppttrr iinn CC++++1177 iitt iiss uusseedd aass iiff iimmmmuuttaabbllee,, iitt ccaannnnoott bbee ccoonnsstt ffoorr tteecchhnniiccaall rreeaassoonnss rriigghhtt nnooww.. ********** | │ │ │ │ │ +|****** ....//iinncclluuddee//lliibbttoorrrreenntt//ttoorrrreenntt__iinnffoo..hhpppp::772299 ****** | │ │ │ │ │ +| // these are the collections from outside of the info-dict. These are | │ │ │ │ │ +| // owning strings, since we only keep the info-section around, these | │ │ │ │ │ +| // cannot be pointers into that buffer. | │ │ │ │ │ +| std::vector m_owned_collections; | │ │ │ │ │ +| | │ │ │ │ │ +|#if TORRENT_ABI_VERSION <= 2 | │ │ │ │ │ +| // if this is a merkle torrent, this is the merkle | │ │ │ │ │ +| // tree. It has space for merkle_num_nodes(merkle_num_leafs(num_pieces)) | │ │ │ │ │ +| // hashes | │ │ │ │ │ +| aux::vector m_merkle_tree; | │ │ │ │ │ +|#endif | │ │ │ │ │ +| | │ │ │ │ │ +| // v2 merkle tree for each file | │ │ │ │ │ +| // the actual hash buffers are always divisible by 32 (sha256_hash::size()) | │ │ │ │ │ +| aux::vector, file_index_t> m_piece_layers; | │ │ │ │ │ +| | │ │ │ │ │ +| // this is a copy of the info section from the torrent. | │ │ │ │ │ +| // it use maintained in this flat format in order to | │ │ │ │ │ +| // make it available through the metadata extension | │ │ │ │ │ +|boost::shared_array m_info_section; | │ │ │ │ │ +| | │ │ │ │ │ +| // if a comment is found in the torrent file | │ │ │ │ │ +| // this will be set to that comment | │ │ │ │ │ +| std::string m_comment; | │ │ │ │ │ +| | │ │ │ │ │ +| // an optional string naming the software used | │ │ │ │ │ +| // to create the torrent file | │ │ │ │ │ +| std::string m_created_by; | │ │ │ │ │ +| | │ │ │ │ │ +| // the info section parsed. points into m_info_section | │ │ │ │ │ +| // parsed lazily | │ │ │ │ │ +| mutable bdecode_node m_info_dict; | │ │ │ │ │ +| | │ │ │ │ │ +| // if a creation date is found in the torrent file | │ │ │ │ │ +| // this will be set to that, otherwise it'll be | │ │ │ │ │ +| // 1970, Jan 1 | │ │ │ │ │ +| std::time_t m_creation_date = 0; | │ │ │ │ │ +| | │ │ │ │ │ +| // the hash(es) that identify this torrent | │ │ │ │ │ +| info_hash_t m_info_hash; | │ │ │ │ │ +| | │ │ │ │ │ +| // this is the offset into the m_info_section buffer to the first byte of | │ │ │ │ │ +| // the first SHA-1 hash | │ │ │ │ │ +| std::int32_t m_piece_hashes = 0; | │ │ │ │ │ +| | │ │ │ │ │ +| // the number of bytes in m_info_section | │ │ │ │ │ +| std::int32_t m_info_section_size = 0; | │ │ │ │ │ +| | │ │ │ │ │ +| // this is used when creating a torrent. If there's | │ │ │ │ │ +|_ _ _/_/_ _o_n_l_y_ _o_n_e_ _f_i_l_e_ _t_h_e_r_e_ _a_r_e_ _c_a_s_e_s_ _w_h_e_r_e_ _i_t_'_s_ _i_m_p_o_s_s_i_b_l_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |it would be nice to remember the bind port and bind once we know where the proxy is m_sock.bind(endpoint, ec); | │ │ │ │ │ |_ _ _ _ _ _ _ _ _ _ _ _|_p_r_o_x_y___b_a_s_e_._h_p_p_:_2_0_7_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** iitt wwoouulldd bbee nniiccee ttoo rreemmeemmbbeerr tthhee bbiinndd ppoorrtt aanndd bbiinndd oonnccee wwee kknnooww wwhheerree tthhee pprrooxxyy iiss mm__ssoocckk..bbiinndd((eennddppooiinntt,, eecc));; ********** | │ │ │ │ │ |****** ....//iinncclluuddee//lliibbttoorrrreenntt//pprrooxxyy__bbaassee..hhpppp::220077 ****** | │ │ │ │ │ | void cancel() | │ │ │ │ │ | { | │ │ │ │ │ | m_sock.cancel(); | │ │ │ │ │ @@ -11606,14 +11359,54 @@ │ │ │ │ │ | | │ │ │ │ │ | void close(error_code& ec) | │ │ │ │ │ | { | │ │ │ │ │ | m_remote_endpoint = endpoint_type(); | │ │ │ │ │ | m_sock.close(ec); | │ │ │ │ │ | m_resolver.cancel(); | │ │ │ │ │ |_ _}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |some space could be saved here by making gauges 32 bits | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_p_e_r_f_o_r_m_a_n_c_e___c_o_u_n_t_e_r_s_._h_p_p_:_4_8_5_ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** ssoommee ssppaaccee ccoouulldd bbee ssaavveedd hheerree bbyy mmaakkiinngg ggaauuggeess 3322 bbiittss ********** | │ │ │ │ │ +|_**_**_**_ _.._.._//_ii_nn_cc_ll_uu_dd_ee_//_ll_ii_bb_tt_oo_rr_rr_ee_nn_tt_//_pp_ee_rr_ff_oo_rr_mm_aa_nn_cc_ee____cc_oo_uu_nn_tt_ee_rr_ss_.._hh_pp_pp_::_44_88_55_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |restore these to regular integers. Instead have one copy of the counters per thread and collect them at convenient synchronization | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_p_e_r_f_o_r_m_a_n_c_e___c_o_u_n_t_e_r_s_._h_p_p_:_4_8_6_ _ _|_p_o_i_n_t_s_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** rreessttoorree tthheessee ttoo rreegguullaarr iinntteeggeerrss.. IInnsstteeaadd hhaavvee oonnee ccooppyy ooff tthhee ccoouunntteerrss ppeerr tthhrreeaadd aanndd ccoolllleecctt tthheemm aatt ccoonnvveenniieenntt ssyynncchhrroonniizzaattiioonn ppooiinnttss ********** | │ │ │ │ │ +|****** ....//iinncclluuddee//lliibbttoorrrreenntt//ppeerrffoorrmmaannccee__ccoouunntteerrss..hhpppp::448866 ****** | │ │ │ │ │ +|#ifdef ATOMIC_LLONG_LOCK_FREE | │ │ │ │ │ +|#define TORRENT_COUNTER_NOEXCEPT noexcept | │ │ │ │ │ +|#else | │ │ │ │ │ +|#define TORRENT_COUNTER_NOEXCEPT | │ │ │ │ │ +|#endif | │ │ │ │ │ +| | │ │ │ │ │ +| counters() TORRENT_COUNTER_NOEXCEPT; | │ │ │ │ │ +| | │ │ │ │ │ +| counters(counters const&) TORRENT_COUNTER_NOEXCEPT; | │ │ │ │ │ +| counters& operator=(counters const&) & TORRENT_COUNTER_NOEXCEPT; | │ │ │ │ │ +| | │ │ │ │ │ +| // returns the new value | │ │ │ │ │ +| std::int64_t inc_stats_counter(int c, std::int64_t value = 1) TORRENT_COUNTER_NOEXCEPT; | │ │ │ │ │ +| std::int64_t operator[](int i) const TORRENT_COUNTER_NOEXCEPT; | │ │ │ │ │ +| | │ │ │ │ │ +| void set_value(int c, std::int64_t value) TORRENT_COUNTER_NOEXCEPT; | │ │ │ │ │ +| void blend_stats_counter(int c, std::int64_t value, int ratio) TORRENT_COUNTER_NOEXCEPT; | │ │ │ │ │ +| | │ │ │ │ │ +| private: | │ │ │ │ │ +| | │ │ │ │ │ +|#ifdef ATOMIC_LLONG_LOCK_FREE | │ │ │ │ │ +|aux::array, num_counters> m_stats_counter; | │ │ │ │ │ +|#else | │ │ │ │ │ +| // if the atomic type isn't lock-free, use a single lock instead, for | │ │ │ │ │ +| // the whole array | │ │ │ │ │ +| mutable std::mutex m_mutex; | │ │ │ │ │ +| aux::array m_stats_counter; | │ │ │ │ │ +|#endif | │ │ │ │ │ +| }; | │ │ │ │ │ +|} | │ │ │ │ │ +| | │ │ │ │ │ +|_#_e_n_d_i_f_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ | |_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ | | │ │ │ │ │ |relevance 0|_p_e_e_r___c_o_n_n_e_c_t_i_o_n___i_n_t_e_r_f_a_c_e_._h_p_p_:|make this interface smaller! | │ │ │ │ │ |_ _ _ _ _ _ _ _ _ _ _ _|_5_1_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** mmaakkee tthhiiss iinntteerrffaaccee ssmmaalllleerr!! ********** | │ │ │ │ │ |****** ....//iinncclluuddee//lliibbttoorrrreenntt//ppeeeerr__ccoonnnneeccttiioonn__iinntteerrffaaccee..hhpppp::5511 ****** | │ │ │ │ │ |*/ | │ │ │ │ │ | | │ │ │ │ │ @@ -11661,14 +11454,121 @@ │ │ │ │ │ | virtual stat const& statistics() const = 0; | │ │ │ │ │ | virtual void get_peer_info(peer_info& p) const = 0; | │ │ │ │ │ |#ifndef TORRENT_DISABLE_LOGGING | │ │ │ │ │ | virtual bool should_log(peer_log_alert::direction_t direction) const = 0; | │ │ │ │ │ | virtual void peer_log(peer_log_alert::direction_t direction | │ │ │ │ │ | , char const* event, char const* fmt = "", ...) const noexcept TORRENT_FORMAT(4,5) = 0; | │ │ │ │ │ |_#_e_n_d_i_f_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |should this be allocated lazily? | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_p_i_e_c_e___p_i_c_k_e_r_._h_p_p_:_8_0_2_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** sshhoouulldd tthhiiss bbee aallllooccaatteedd llaazziillyy?? ********** | │ │ │ │ │ +|****** ....//iinncclluuddee//lliibbttoorrrreenntt//ppiieeccee__ppiicckkeerr..hhpppp::880022 ****** | │ │ │ │ │ +|// download list it may live in now | │ │ │ │ │ +| std::vector::iterator update_piece_state( | │ │ │ │ │ +| std::vector::iterator dp); | │ │ │ │ │ +| | │ │ │ │ │ +| private: | │ │ │ │ │ +| | │ │ │ │ │ +|#if TORRENT_USE_ASSERTS || TORRENT_USE_INVARIANT_CHECKS | │ │ │ │ │ +| index_range categories() const | │ │ │ │ │ +| { return {{}, piece_picker::piece_pos::num_download_categories}; } | │ │ │ │ │ +|#endif | │ │ │ │ │ +| | │ │ │ │ │ +| // the following vectors are mutable because they sometimes may | │ │ │ │ │ +| // be updated lazily, triggered by const functions | │ │ │ │ │ +| | │ │ │ │ │ +| // this maps indices to number of peers that has this piece and | │ │ │ │ │ +| // index into the m_piece_info vectors. | │ │ │ │ │ +| // piece_pos::we_have_index means that we have the piece, so it | │ │ │ │ │ +| // doesn't exist in the piece_info buckets | │ │ │ │ │ +| // pieces with the filtered flag set doesn't have entries in | │ │ │ │ │ +| // the m_piece_info buckets either | │ │ │ │ │ +|mutable aux::vector m_piece_map; | │ │ │ │ │ +| | │ │ │ │ │ +| // tracks the number of bytes in a specific piece that are part of a pad | │ │ │ │ │ +| // file. The padding is assumed to be at the end of the piece, and the | │ │ │ │ │ +| // blocks covered by the pad bytes are not picked by the piece picker | │ │ │ │ │ +| std::unordered_map m_pads_in_piece; | │ │ │ │ │ +| | │ │ │ │ │ +| // when the adjacent_piece affinity is enabled, this contains the most | │ │ │ │ │ +| // recent "extents" of adjacent pieces that have been requested from | │ │ │ │ │ +| // this is mutable because it's updated by functions to pick pieces, which | │ │ │ │ │ +| // are const. That's an efficient place to update it, since it's being | │ │ │ │ │ +| // traversed already. | │ │ │ │ │ +| mutable std::vector m_recent_extents; | │ │ │ │ │ +| | │ │ │ │ │ +| // the number of bytes of pad file set in this piece picker | │ │ │ │ │ +| int m_num_pad_bytes = 0; | │ │ │ │ │ +| | │ │ │ │ │ +| // the number of pad blocks that we already have | │ │ │ │ │ +| int m_have_pad_bytes = 0; | │ │ │ │ │ +| | │ │ │ │ │ +| // the number of pad blocks part of filtered pieces we don't have | │ │ │ │ │ +| int m_filtered_pad_bytes = 0; | │ │ │ │ │ +| | │ │ │ │ │ +| // the number of pad blocks we have that are also filtered | │ │ │ │ │ +| int m_have_filtered_pad_bytes = 0; | │ │ │ │ │ +| | │ │ │ │ │ +| // the number of seeds. These are not added to | │ │ │ │ │ +| // the availability counters of the pieces | │ │ │ │ │ +| int m_seeds = 0; | │ │ │ │ │ +| | │ │ │ │ │ +|_ _ _/_/_ _t_h_e_ _n_u_m_b_e_r_ _o_f_ _p_i_e_c_e_s_ _t_h_a_t_ _h_a_v_e_ _p_a_s_s_e_d_ _t_h_e_ _h_a_s_h_ _c_h_e_c_k_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |it would be more intuitive to account "wanted" pieces instead of filtered | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_p_i_e_c_e___p_i_c_k_e_r_._h_p_p_:_8_7_7_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** iitt wwoouulldd bbee mmoorree iinnttuuiittiivvee ttoo aaccccoouunntt ""wwaanntteedd"" ppiieecceess iinnsstteeaadd ooff ffiilltteerreedd ********** | │ │ │ │ │ +|****** ....//iinncclluuddee//lliibbttoorrrreenntt//ppiieeccee__ppiicckkeerr..hhpppp::887777 ****** | │ │ │ │ │ +| // this holds the information of the blocks in partially downloaded | │ │ │ │ │ +| // pieces. the downloading_piece::info index point into this vector for | │ │ │ │ │ +| // its storage | │ │ │ │ │ +| aux::vector m_block_info; | │ │ │ │ │ +| | │ │ │ │ │ +| // these are block ranges in m_block_info that are free. The numbers | │ │ │ │ │ +| // in here, when multiplied by blocks_per_piece is the index to the | │ │ │ │ │ +| // first block in the range that's free to use by a new downloading_piece. | │ │ │ │ │ +| // this is a free-list. | │ │ │ │ │ +| std::vector m_free_block_infos; | │ │ │ │ │ +| | │ │ │ │ │ +| std::uint16_t m_blocks_in_last_piece = 0; | │ │ │ │ │ +| int m_piece_size = 0; | │ │ │ │ │ +| std::int64_t m_total_size = 0; | │ │ │ │ │ +| | │ │ │ │ │ +| // the number of filtered pieces that we don't already | │ │ │ │ │ +| // have. total_number_of_pieces - number_of_pieces_we_have | │ │ │ │ │ +| // - num_filtered is supposed to the number of pieces | │ │ │ │ │ +| // we still want to download | │ │ │ │ │ +|int m_num_filtered = 0; | │ │ │ │ │ +| | │ │ │ │ │ +| // the number of pieces we have that also are filtered | │ │ │ │ │ +| int m_num_have_filtered = 0; | │ │ │ │ │ +| | │ │ │ │ │ +| // we have all pieces in the range [0, m_cursor) | │ │ │ │ │ +| // m_cursor is the first piece we don't have | │ │ │ │ │ +| piece_index_t m_cursor{0}; | │ │ │ │ │ +| | │ │ │ │ │ +| // we have all pieces in the range [m_reverse_cursor, end) | │ │ │ │ │ +| // m_reverse_cursor is the first piece where we also have | │ │ │ │ │ +| // all the subsequent pieces | │ │ │ │ │ +| piece_index_t m_reverse_cursor{0}; | │ │ │ │ │ +| | │ │ │ │ │ +| // the number of pieces we have (i.e. passed + flushed). | │ │ │ │ │ +| // This includes pieces that we have filtered but still have | │ │ │ │ │ +| int m_num_have = 0; | │ │ │ │ │ +| | │ │ │ │ │ +| // if this is set to true, it means update_pieces() | │ │ │ │ │ +| // has to be called before accessing m_pieces. | │ │ │ │ │ +| mutable bool m_dirty = false; | │ │ │ │ │ +| public: | │ │ │ │ │ +| | │ │ │ │ │ +| enum { max_pieces = (std::numeric_limits::max)() - 1 }; | │ │ │ │ │ +| | │ │ │ │ │ +| }; | │ │ │ │ │ +|} | │ │ │ │ │ +| | │ │ │ │ │ +|_#_e_n_d_i_f_ _/_/_ _T_O_R_R_E_N_T___P_I_E_C_E___P_I_C_K_E_R___H_P_P___I_N_C_L_U_D_E_D_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |support using the windows API for UPnP operations as well | │ │ │ │ │ |_ _ _ _ _ _ _ _ _ _ _ _|_u_p_n_p_._h_p_p_:_1_6_2_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** ssuuppppoorrtt uussiinngg tthhee wwiinnddoowwss AAPPII ffoorr UUPPnnPP ooppeerraattiioonnss aass wweellll ********** | │ │ │ │ │ |****** ....//iinncclluuddee//lliibbttoorrrreenntt//uuppnnpp..hhpppp::116622 ****** | │ │ │ │ │ |{ | │ │ │ │ │ | bool in_error_code = false; | │ │ │ │ │ | bool exit = false; | │ │ │ │ │ @@ -11716,54 +11616,288 @@ │ │ │ │ │ | // ``local_port`` is the port in the local machine that the mapping should forward | │ │ │ │ │ | // to. | │ │ │ │ │ | // | │ │ │ │ │ | // The return value is an index that identifies this port mapping. This is used | │ │ │ │ │ | // to refer to mappings that fails or succeeds in the portmap_error_alert_ and | │ │ │ │ │ | // portmap_alert_ respectively. If The mapping fails immediately, the return value | │ │ │ │ │ |_ _/_/_ _i_s_ _-_1_,_ _w_h_i_c_h_ _m_e_a_n_s_ _f_a_i_l_u_r_e_._ _T_h_e_r_e_ _w_i_l_l_ _n_o_t_ _b_e_ _a_n_y_ _e_r_r_o_r_ _a_l_e_r_t_ _n_o_t_i_f_i_c_a_t_i_o_n_ _f_o_r_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |some space could be saved here by making gauges 32 bits | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_p_e_r_f_o_r_m_a_n_c_e___c_o_u_n_t_e_r_s_._h_p_p_:_4_8_5_ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** ssoommee ssppaaccee ccoouulldd bbee ssaavveedd hheerree bbyy mmaakkiinngg ggaauuggeess 3322 bbiittss ********** | │ │ │ │ │ -|_**_**_**_ _.._.._//_ii_nn_cc_ll_uu_dd_ee_//_ll_ii_bb_tt_oo_rr_rr_ee_nn_tt_//_pp_ee_rr_ff_oo_rr_mm_aa_nn_cc_ee____cc_oo_uu_nn_tt_ee_rr_ss_.._hh_pp_pp_::_44_88_55_ _**_**_**_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |restore these to regular integers. Instead have one copy of the counters per thread and collect them at convenient synchronization | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_p_e_r_f_o_r_m_a_n_c_e___c_o_u_n_t_e_r_s_._h_p_p_:_4_8_6_ _ _|_p_o_i_n_t_s_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** rreessttoorree tthheessee ttoo rreegguullaarr iinntteeggeerrss.. IInnsstteeaadd hhaavvee oonnee ccooppyy ooff tthhee ccoouunntteerrss ppeerr tthhrreeaadd aanndd ccoolllleecctt tthheemm aatt ccoonnvveenniieenntt ssyynncchhrroonniizzaattiioonn ppooiinnttss ********** | │ │ │ │ │ -|****** ....//iinncclluuddee//lliibbttoorrrreenntt//ppeerrffoorrmmaannccee__ccoouunntteerrss..hhpppp::448866 ****** | │ │ │ │ │ -|#ifdef ATOMIC_LLONG_LOCK_FREE | │ │ │ │ │ -|#define TORRENT_COUNTER_NOEXCEPT noexcept | │ │ │ │ │ -|#else | │ │ │ │ │ -|#define TORRENT_COUNTER_NOEXCEPT | │ │ │ │ │ -|#endif | │ │ │ │ │ +|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |we could bind the socket here, since we know what the target endpoint is of the proxy | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_s_o_c_k_s_5___s_t_r_e_a_m_._h_p_p_:_1_9_7_ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** wwee ccoouulldd bbiinndd tthhee ssoocckkeett hheerree,, ssiinnccee wwee kknnooww wwhhaatt tthhee ttaarrggeett eennddppooiinntt iiss ooff tthhee pprrooxxyy ********** | │ │ │ │ │ +|****** ....//iinncclluuddee//lliibbttoorrrreenntt//ssoocckkss55__ssttrreeaamm..hhpppp::119977 ****** | │ │ │ │ │ +|}, std::move(handler))); | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -| counters() TORRENT_COUNTER_NOEXCEPT; | │ │ │ │ │ +|private: | │ │ │ │ │ | | │ │ │ │ │ -| counters(counters const&) TORRENT_COUNTER_NOEXCEPT; | │ │ │ │ │ -| counters& operator=(counters const&) & TORRENT_COUNTER_NOEXCEPT; | │ │ │ │ │ +| template | │ │ │ │ │ +| void name_lookup(error_code const& e, tcp::resolver::results_type ips | │ │ │ │ │ +| , Handler h) | │ │ │ │ │ +| { | │ │ │ │ │ +| COMPLETE_ASYNC("socks5_stream::name_lookup"); | │ │ │ │ │ +| if (handle_error(e, std::move(h))) return; | │ │ │ │ │ | | │ │ │ │ │ -| // returns the new value | │ │ │ │ │ -| std::int64_t inc_stats_counter(int c, std::int64_t value = 1) TORRENT_COUNTER_NOEXCEPT; | │ │ │ │ │ -| std::int64_t operator[](int i) const TORRENT_COUNTER_NOEXCEPT; | │ │ │ │ │ +| auto i = ips.begin(); | │ │ │ │ │ +| if (!m_sock.is_open()) | │ │ │ │ │ +| { | │ │ │ │ │ +| error_code ec; | │ │ │ │ │ +| m_sock.open(i->endpoint().protocol(), ec); | │ │ │ │ │ +| if (handle_error(ec, std::move(h))) return; | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -| void set_value(int c, std::int64_t value) TORRENT_COUNTER_NOEXCEPT; | │ │ │ │ │ -| void blend_stats_counter(int c, std::int64_t value, int ratio) TORRENT_COUNTER_NOEXCEPT; | │ │ │ │ │ +|ADD_OUTSTANDING_ASYNC("socks5_stream::connected"); | │ │ │ │ │ +|m_sock.async_connect(i->endpoint(), wrap_allocator( | │ │ │ │ │ +| [this](error_code const& ec, Handler hn) | │ │ │ │ │ +| { connected(ec, std::move(hn)); }, std::move(h))); | │ │ │ │ │ +| } | │ │ │ │ │ | | │ │ │ │ │ -| private: | │ │ │ │ │ +| template | │ │ │ │ │ +| void connected(error_code const& e, Handler h) | │ │ │ │ │ +| { | │ │ │ │ │ +| COMPLETE_ASYNC("socks5_stream::connected"); | │ │ │ │ │ +| if (handle_error(e, std::move(h))) return; | │ │ │ │ │ | | │ │ │ │ │ -|#ifdef ATOMIC_LLONG_LOCK_FREE | │ │ │ │ │ -|aux::array, num_counters> m_stats_counter; | │ │ │ │ │ -|#else | │ │ │ │ │ -| // if the atomic type isn't lock-free, use a single lock instead, for | │ │ │ │ │ -| // the whole array | │ │ │ │ │ -| mutable std::mutex m_mutex; | │ │ │ │ │ -| aux::array m_stats_counter; | │ │ │ │ │ +| using namespace libtorrent::aux; | │ │ │ │ │ +| if (m_version == 5) | │ │ │ │ │ +| { | │ │ │ │ │ +| // send SOCKS5 authentication methods | │ │ │ │ │ +| m_buffer.resize(m_user.empty()?3:4); | │ │ │ │ │ +| char* p = &m_buffer[0]; | │ │ │ │ │ +| write_uint8(5, p); // SOCKS VERSION 5 | │ │ │ │ │ +| if (m_user.empty()) | │ │ │ │ │ +| { | │ │ │ │ │ +| write_uint8(1, p); // 1 authentication method (no auth) | │ │ │ │ │ +| write_uint8(0, p); // no authentication | │ │ │ │ │ +| } | │ │ │ │ │ +| else | │ │ │ │ │ +| { | │ │ │ │ │ +| write_uint8(2, p); // 2 authentication methods | │ │ │ │ │ +| write_uint8(0, p); // no authentication | │ │ │ │ │ +| write_uint8(2, p); // username/password | │ │ │ │ │ +| } | │ │ │ │ │ +|_ _ _ _A_D_D___O_U_T_S_T_A_N_D_I_N_G___A_S_Y_N_C_(_"_s_o_c_k_s_5___s_t_r_e_a_m_:_:_h_a_n_d_s_h_a_k_e_1_"_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |replace this by the standard string_view in C++17 | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_s_t_r_i_n_g___v_i_e_w_._h_p_p_:_4_0_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** rreeppllaaccee tthhiiss bbyy tthhee ssttaannddaarrdd ssttrriinngg__vviieeww iinn CC++++1177 ********** | │ │ │ │ │ +|****** ....//iinncclluuddee//lliibbttoorrrreenntt//ssttrriinngg__vviieeww..hhpppp::4400 ****** | │ │ │ │ │ +|AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | │ │ │ │ │ +|IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | │ │ │ │ │ +|ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | │ │ │ │ │ +|LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | │ │ │ │ │ +|CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | │ │ │ │ │ +|SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | │ │ │ │ │ +|INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | │ │ │ │ │ +|CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | │ │ │ │ │ +|ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | │ │ │ │ │ +|POSSIBILITY OF SUCH DAMAGE. | │ │ │ │ │ +| | │ │ │ │ │ +|*/ | │ │ │ │ │ +| | │ │ │ │ │ +|#ifndef TORRENT_STRING_VIEW_HPP_INCLUDED | │ │ │ │ │ +|#define TORRENT_STRING_VIEW_HPP_INCLUDED | │ │ │ │ │ +| | │ │ │ │ │ +|#include | │ │ │ │ │ +| | │ │ │ │ │ +|#include "libtorrent/aux_/disable_warnings_push.hpp" | │ │ │ │ │ +| | │ │ │ │ │ +| | │ │ │ │ │ +|#if BOOST_VERSION < 106100 | │ │ │ │ │ +|#include | │ │ │ │ │ +|#include // for strchr | │ │ │ │ │ +|namespace libtorrent { | │ │ │ │ │ +| | │ │ │ │ │ +|using string_view = boost::string_ref; | │ │ │ │ │ +|using wstring_view = boost::wstring_ref; | │ │ │ │ │ +| | │ │ │ │ │ +|// internal | │ │ │ │ │ +|inline string_view::size_type find_first_of(string_view const v, char const c | │ │ │ │ │ +| , string_view::size_type pos) | │ │ │ │ │ +|{ | │ │ │ │ │ +| while (pos < v.size()) | │ │ │ │ │ +| { | │ │ │ │ │ +| if (v[pos] == c) return pos; | │ │ │ │ │ +| ++pos; | │ │ │ │ │ +| } | │ │ │ │ │ +| return string_view::npos; | │ │ │ │ │ +|} | │ │ │ │ │ +| | │ │ │ │ │ +|// internal | │ │ │ │ │ +|inline string_view::size_type find_first_of(string_view const v, char const* c | │ │ │ │ │ +| , string_view::size_type pos) | │ │ │ │ │ +|{ | │ │ │ │ │ +| while (pos < v.size()) | │ │ │ │ │ +| { | │ │ │ │ │ +| if (std::strchr(c, v[pos]) != nullptr) return pos; | │ │ │ │ │ +| ++pos; | │ │ │ │ │ +| } | │ │ │ │ │ +|_ _r_e_t_u_r_n_ _s_t_r_i_n_g___v_i_e_w_:_:_n_p_o_s_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |hide this declaration when deprecated functions are disabled, and remove its internal use | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_i_d_e_n_t_i_f_y___c_l_i_e_n_t_._h_p_p_:_4_8_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** hhiiddee tthhiiss ddeeccllaarraattiioonn wwhheenn ddeepprreeccaatteedd ffuunnccttiioonnss aarree ddiissaabblleedd,, aanndd rreemmoovvee iittss iinntteerrnnaall uussee ********** | │ │ │ │ │ +|****** ....//iinncclluuddee//lliibbttoorrrreenntt//iiddeennttiiffyy__cclliieenntt..hhpppp::4488 ****** | │ │ │ │ │ +|CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | │ │ │ │ │ +|ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | │ │ │ │ │ +|POSSIBILITY OF SUCH DAMAGE. | │ │ │ │ │ +| | │ │ │ │ │ +|*/ | │ │ │ │ │ +| | │ │ │ │ │ +|#ifndef TORRENT_IDENTIFY_CLIENT_HPP_INCLUDED | │ │ │ │ │ +|#define TORRENT_IDENTIFY_CLIENT_HPP_INCLUDED | │ │ │ │ │ +| | │ │ │ │ │ +|#include "libtorrent/config.hpp" | │ │ │ │ │ +| | │ │ │ │ │ +|#if TORRENT_ABI_VERSION == 1 | │ │ │ │ │ +|#include "libtorrent/aux_/disable_warnings_push.hpp" | │ │ │ │ │ +|#include | │ │ │ │ │ +|#include "libtorrent/aux_/disable_warnings_pop.hpp" | │ │ │ │ │ |#endif | │ │ │ │ │ -| }; | │ │ │ │ │ +| | │ │ │ │ │ +|#include "libtorrent/peer_id.hpp" | │ │ │ │ │ +|#include "libtorrent/fingerprint.hpp" | │ │ │ │ │ +| | │ │ │ │ │ +|namespace libtorrent { | │ │ │ │ │ +| | │ │ │ │ │ +|namespace aux { | │ │ │ │ │ +| | │ │ │ │ │ +| TORRENT_EXTRA_EXPORT | │ │ │ │ │ +| std::string identify_client_impl(const peer_id& p); | │ │ │ │ │ +| | │ │ │ │ │ |} | │ │ │ │ │ | | │ │ │ │ │ -|_#_e_n_d_i_f_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +| // these functions don't really need to be public. This mechanism of | │ │ │ │ │ +| // advertising client software and version is also out-dated. | │ │ │ │ │ +| | │ │ │ │ │ +| // This function can can be used 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. | │ │ │ │ │ +| TORRENT_DEPRECATED_EXPORT | │ │ │ │ │ +| std::string identify_client(const peer_id& p); | │ │ │ │ │ +| | │ │ │ │ │ +|#if TORRENT_ABI_VERSION == 1 | │ │ │ │ │ +| | │ │ │ │ │ +|#include "libtorrent/aux_/disable_deprecation_warnings_push.hpp" | │ │ │ │ │ +| | │ │ │ │ │ +| // Returns an optional fingerprint if any can be identified from the peer | │ │ │ │ │ +| // id. This can be used to automate the identification of clients. It will | │ │ │ │ │ +| // not be able to identify peers with non- standard encodings. Only Azureus | │ │ │ │ │ +| // style, Shadow's style and Mainline style. | │ │ │ │ │ +| TORRENT_DEPRECATED_EXPORT | │ │ │ │ │ +| boost::optional | │ │ │ │ │ +| client_fingerprint(peer_id const& p); | │ │ │ │ │ +| | │ │ │ │ │ +|_#_i_n_c_l_u_d_e_ _"_l_i_b_t_o_r_r_e_n_t_/_a_u_x___/_d_i_s_a_b_l_e___w_a_r_n_i_n_g_s___p_o_p_._h_p_p_"_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |make this a string_view | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_i_2_p___s_t_r_e_a_m_._h_p_p_:_5_3_9_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** mmaakkee tthhiiss aa ssttrriinngg__vviieeww ********** | │ │ │ │ │ +|****** ....//iinncclluuddee//lliibbttoorrrreenntt//ii22pp__ssttrreeaamm..hhpppp::553399 ****** | │ │ │ │ │ +| char tmp[20]; | │ │ │ │ │ +| aux::random_bytes(tmp); | │ │ │ │ │ +| m_session_id.resize(sizeof(tmp)*2); | │ │ │ │ │ +| aux::to_hex(tmp, &m_session_id[0]); | │ │ │ │ │ +| | │ │ │ │ │ +| m_sam_socket = std::make_shared(m_io_service); | │ │ │ │ │ +| m_sam_socket->set_proxy(m_hostname, m_port); | │ │ │ │ │ +| m_sam_socket->set_command(i2p_stream::cmd_create_session); | │ │ │ │ │ +| m_sam_socket->set_session_id(m_session_id.c_str()); | │ │ │ │ │ +| m_sam_socket->set_session_options(session_options); | │ │ │ │ │ +| | │ │ │ │ │ +| ADD_OUTSTANDING_ASYNC("i2p_stream::on_sam_connect"); | │ │ │ │ │ +| m_sam_socket->async_connect(tcp::endpoint(), wrap_allocator( | │ │ │ │ │ +| [this,s=m_sam_socket](error_code const& ec, Handler hn) { | │ │ │ │ │ +| on_sam_connect(ec, s, std::move(hn)); | │ │ │ │ │ +| }, std::move(handler))); | │ │ │ │ │ +| } | │ │ │ │ │ +| void close(error_code&); | │ │ │ │ │ +| | │ │ │ │ │ +|char const* session_id() const { return m_session_id.c_str(); } | │ │ │ │ │ +|std::string const& local_endpoint() const { return m_i2p_local_endpoint; } | │ │ │ │ │ +| | │ │ │ │ │ +| template | │ │ │ │ │ +| void async_name_lookup(char const* name, Handler handler) | │ │ │ │ │ +| { | │ │ │ │ │ +| if (m_state == sam_idle && m_name_lookup.empty() && is_open()) | │ │ │ │ │ +| do_name_lookup(name, std::move(handler)); | │ │ │ │ │ +| else | │ │ │ │ │ +| m_name_lookup.emplace_back(std::string(name) | │ │ │ │ │ +| , std::move(handler)); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +|private: | │ │ │ │ │ +| | │ │ │ │ │ +| template | │ │ │ │ │ +| void on_sam_connect(error_code const& ec, std::shared_ptr, Handler h) | │ │ │ │ │ +| { | │ │ │ │ │ +| COMPLETE_ASYNC("i2p_stream::on_sam_connect"); | │ │ │ │ │ +| m_state = sam_idle; | │ │ │ │ │ +| | │ │ │ │ │ +| if (ec) | │ │ │ │ │ +| { | │ │ │ │ │ +| h(ec); | │ │ │ │ │ +| return; | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +| do_name_lookup("ME", wrap_allocator( | │ │ │ │ │ +| [this](error_code const& e, char const* dst, Handler hn) { | │ │ │ │ │ +| set_local_endpoint(e, dst, std::move(hn)); | │ │ │ │ │ +|_ _ _ _}_,_ _s_t_d_:_:_m_o_v_e_(_h_)_)_)_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |support batched adding of block hashes for reduced overhead? | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_h_a_s_h___p_i_c_k_e_r_._h_p_p_:_1_5_5_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** ssuuppppoorrtt bbaattcchheedd aaddddiinngg ooff bblloocckk hhaasshheess ffoorr rreedduucceedd oovveerrhheeaadd?? ********** | │ │ │ │ │ +|****** ....//iinncclluuddee//lliibbttoorrrreenntt//hhaasshh__ppiicckkeerr..hhpppp::115555 ****** | │ │ │ │ │ +|// the number of hashes in the range | │ │ │ │ │ +| int count = 0; | │ │ │ │ │ +| int proof_layers = 0; | │ │ │ │ │ +| }; | │ │ │ │ │ +| | │ │ │ │ │ +| // validates the hash_request, to ensure its invariant as well as matching | │ │ │ │ │ +| // the torrent's file_storage and the number of hashes accompanying the | │ │ │ │ │ +| // request | │ │ │ │ │ +| TORRENT_EXTRA_EXPORT | │ │ │ │ │ +| bool validate_hash_request(hash_request const& hr, file_storage const& fs); | │ │ │ │ │ +| | │ │ │ │ │ +| class TORRENT_EXTRA_EXPORT hash_picker | │ │ │ │ │ +| { | │ │ │ │ │ +| public: | │ │ │ │ │ +| hash_picker(file_storage const& files | │ │ │ │ │ +| , aux::vector& trees); | │ │ │ │ │ +| | │ │ │ │ │ +| hash_request pick_hashes(typed_bitfield const& pieces); | │ │ │ │ │ +| | │ │ │ │ │ +| add_hashes_result add_hashes(hash_request const& req, span hashes); | │ │ │ │ │ +|set_block_hash_result set_block_hash(piece_index_t piece, int offset, sha256_hash const& h); | │ │ │ │ │ +|void hashes_rejected(hash_request const& req); | │ │ │ │ │ +| void verify_block_hashes(piece_index_t index); | │ │ │ │ │ +| | │ │ │ │ │ +| // do we know the piece layer hash for a piece | │ │ │ │ │ +| bool have_hash(piece_index_t index) const; | │ │ │ │ │ +| // do we know all the block hashes for a file? | │ │ │ │ │ +| bool have_all(file_index_t file) const; | │ │ │ │ │ +| bool have_all() const; | │ │ │ │ │ +| bool piece_verified(piece_index_t piece) const; | │ │ │ │ │ +| | │ │ │ │ │ +| int piece_layer() const { return m_piece_layer; } | │ │ │ │ │ +| | │ │ │ │ │ +| private: | │ │ │ │ │ +| // returns the number of proof layers needed to verify the node's hash | │ │ │ │ │ +| int layers_to_verify(node_index idx) const; | │ │ │ │ │ +| int file_num_layers(file_index_t idx) const; | │ │ │ │ │ +| | │ │ │ │ │ +| struct piece_hash_request | │ │ │ │ │ +| { | │ │ │ │ │ +| time_point last_request = min_time(); | │ │ │ │ │ +| int num_requests = 0; | │ │ │ │ │ +| bool have = false; | │ │ │ │ │ +| }; | │ │ │ │ │ +| | │ │ │ │ │ +| struct priority_block_request | │ │ │ │ │ +| { | │ │ │ │ │ +| priority_block_request(file_index_t const f, int const b) | │ │ │ │ │ +| : file(f), block(b) {} | │ │ │ │ │ +| file_index_t file; | │ │ │ │ │ +|_ _ _ _i_n_t_ _b_l_o_c_k_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |make this a raw pointer (to save size in the first cache line) and make the constructor take a raw pointer. torrent objects should | │ │ │ │ │ |_ _ _ _ _ _ _ _ _ _ _ _|_p_e_e_r___c_o_n_n_e_c_t_i_o_n_._h_p_p_:_2_1_8_ _ _ _ _ _ _ _|_a_l_w_a_y_s_ _o_u_t_l_i_v_e_ _t_h_e_i_r_ _p_e_e_r_s_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** mmaakkee tthhiiss aa rraaww ppooiinntteerr ((ttoo ssaavvee ssiizzee iinn tthhee ffiirrsstt ccaacchhee lliinnee)) aanndd mmaakkee tthhee ccoonnssttrruuccttoorr ttaakkee aa rraaww ppooiinntteerr.. ttoorrrreenntt oobbjjeeccttss sshhoouulldd aallwwaayyss oouuttlliivvee tthheeiirr ppeeeerrss ********** | │ │ │ │ │ |****** ....//iinncclluuddee//lliibbttoorrrreenntt//ppeeeerr__ccoonnnneeccttiioonn..hhpppp::221188 ****** | │ │ │ │ │ |, m_snubbed(false) | │ │ │ │ │ | , m_interesting(false) | │ │ │ │ │ | , m_choked(true) | │ │ │ │ │ @@ -11865,271 +11999,97 @@ │ │ │ │ │ | // let plugins control flags that should always be set | │ │ │ │ │ | picker_options_t m_picker_options{}; | │ │ │ │ │ | | │ │ │ │ │ | // the number of invalid piece-requests | │ │ │ │ │ | // we have got from this peer. If the request | │ │ │ │ │ | // queue gets empty, and there have been | │ │ │ │ │ |_ _ _/_/_ _i_n_v_a_l_i_d_ _r_e_q_u_e_s_t_s_,_ _w_e_ _c_a_n_ _a_s_s_u_m_e_ _t_h_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |hide this declaration when deprecated functions are disabled, and remove its internal use | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_i_d_e_n_t_i_f_y___c_l_i_e_n_t_._h_p_p_:_4_8_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** hhiiddee tthhiiss ddeeccllaarraattiioonn wwhheenn ddeepprreeccaatteedd ffuunnccttiioonnss aarree ddiissaabblleedd,, aanndd rreemmoovvee iittss iinntteerrnnaall uussee ********** | │ │ │ │ │ -|****** ....//iinncclluuddee//lliibbttoorrrreenntt//iiddeennttiiffyy__cclliieenntt..hhpppp::4488 ****** | │ │ │ │ │ -|CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | │ │ │ │ │ -|ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | │ │ │ │ │ -|POSSIBILITY OF SUCH DAMAGE. | │ │ │ │ │ -| | │ │ │ │ │ -|*/ | │ │ │ │ │ -| | │ │ │ │ │ -|#ifndef TORRENT_IDENTIFY_CLIENT_HPP_INCLUDED | │ │ │ │ │ -|#define TORRENT_IDENTIFY_CLIENT_HPP_INCLUDED | │ │ │ │ │ -| | │ │ │ │ │ -|#include "libtorrent/config.hpp" | │ │ │ │ │ -| | │ │ │ │ │ -|#if TORRENT_ABI_VERSION == 1 | │ │ │ │ │ -|#include "libtorrent/aux_/disable_warnings_push.hpp" | │ │ │ │ │ -|#include | │ │ │ │ │ -|#include "libtorrent/aux_/disable_warnings_pop.hpp" | │ │ │ │ │ -|#endif | │ │ │ │ │ -| | │ │ │ │ │ -|#include "libtorrent/peer_id.hpp" | │ │ │ │ │ -|#include "libtorrent/fingerprint.hpp" | │ │ │ │ │ -| | │ │ │ │ │ +|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |move to aux | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_s_o_c_k_e_t___t_y_p_e_._h_p_p_:_6_0_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** mmoovvee ttoo aauuxx ********** | │ │ │ │ │ +|****** ....//iinncclluuddee//lliibbttoorrrreenntt//ssoocckkeett__ttyyppee..hhpppp::6600 ****** | │ │ │ │ │ |namespace libtorrent { | │ │ │ │ │ | | │ │ │ │ │ -|namespace aux { | │ │ │ │ │ -| | │ │ │ │ │ -| TORRENT_EXTRA_EXPORT | │ │ │ │ │ -| std::string identify_client_impl(const peer_id& p); | │ │ │ │ │ -| | │ │ │ │ │ -|} | │ │ │ │ │ -| | │ │ │ │ │ -| // these functions don't really need to be public. This mechanism of | │ │ │ │ │ -| // advertising client software and version is also out-dated. | │ │ │ │ │ -| | │ │ │ │ │ -| // This function can can be used 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. | │ │ │ │ │ -| TORRENT_DEPRECATED_EXPORT | │ │ │ │ │ -| std::string identify_client(const peer_id& p); | │ │ │ │ │ -| | │ │ │ │ │ -|#if TORRENT_ABI_VERSION == 1 | │ │ │ │ │ -| | │ │ │ │ │ -|#include "libtorrent/aux_/disable_deprecation_warnings_push.hpp" | │ │ │ │ │ -| | │ │ │ │ │ -| // Returns an optional fingerprint if any can be identified from the peer | │ │ │ │ │ -| // id. This can be used to automate the identification of clients. It will | │ │ │ │ │ -| // not be able to identify peers with non- standard encodings. Only Azureus | │ │ │ │ │ -| // style, Shadow's style and Mainline style. | │ │ │ │ │ -| TORRENT_DEPRECATED_EXPORT | │ │ │ │ │ -| boost::optional | │ │ │ │ │ -| client_fingerprint(peer_id const& p); | │ │ │ │ │ -| | │ │ │ │ │ -|_#_i_n_c_l_u_d_e_ _"_l_i_b_t_o_r_r_e_n_t_/_a_u_x___/_d_i_s_a_b_l_e___w_a_r_n_i_n_g_s___p_o_p_._h_p_p_"_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |replace this by the standard string_view in C++17 | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_s_t_r_i_n_g___v_i_e_w_._h_p_p_:_4_0_ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** rreeppllaaccee tthhiiss bbyy tthhee ssttaannddaarrdd ssttrriinngg__vviieeww iinn CC++++1177 ********** | │ │ │ │ │ -|****** ....//iinncclluuddee//lliibbttoorrrreenntt//ssttrriinngg__vviieeww..hhpppp::4400 ****** | │ │ │ │ │ -|AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | │ │ │ │ │ -|IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | │ │ │ │ │ -|ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | │ │ │ │ │ -|LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | │ │ │ │ │ -|CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | │ │ │ │ │ -|SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | │ │ │ │ │ -|INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | │ │ │ │ │ -|CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | │ │ │ │ │ -|ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | │ │ │ │ │ -|POSSIBILITY OF SUCH DAMAGE. | │ │ │ │ │ -| | │ │ │ │ │ -|*/ | │ │ │ │ │ -| | │ │ │ │ │ -|#ifndef TORRENT_STRING_VIEW_HPP_INCLUDED | │ │ │ │ │ -|#define TORRENT_STRING_VIEW_HPP_INCLUDED | │ │ │ │ │ -| | │ │ │ │ │ -|#include | │ │ │ │ │ -| | │ │ │ │ │ -|#include "libtorrent/aux_/disable_warnings_push.hpp" | │ │ │ │ │ -| | │ │ │ │ │ +|// A type describing kinds of sockets involved in various operations or events. | │ │ │ │ │ +|enum class socket_type_t : std::uint8_t { | │ │ │ │ │ +| tcp, | │ │ │ │ │ +| socks5, | │ │ │ │ │ +| http, | │ │ │ │ │ +| utp, | │ │ │ │ │ +| i2p, | │ │ │ │ │ +| tcp_ssl, | │ │ │ │ │ +| socks5_ssl, | │ │ │ │ │ +| http_ssl, | │ │ │ │ │ +| utp_ssl, | │ │ │ │ │ | | │ │ │ │ │ -|#if BOOST_VERSION < 106100 | │ │ │ │ │ -|#include | │ │ │ │ │ -|#include // for strchr | │ │ │ │ │ -|namespace libtorrent { | │ │ │ │ │ +|#if TORRENT_ABI_VERSION <= 2 | │ │ │ │ │ +| udp TORRENT_DEPRECATED_ENUM = utp, | │ │ │ │ │ +|#endif | │ │ │ │ │ +|}; | │ │ │ │ │ | | │ │ │ │ │ -|using string_view = boost::string_ref; | │ │ │ │ │ -|using wstring_view = boost::wstring_ref; | │ │ │ │ │ +|// return a short human readable name for types of socket | │ │ │ │ │ +|char const* socket_type_name(socket_type_t); | │ │ │ │ │ | | │ │ │ │ │ -|// internal | │ │ │ │ │ -|inline string_view::size_type find_first_of(string_view const v, char const c | │ │ │ │ │ -| , string_view::size_type pos) | │ │ │ │ │ -|{ | │ │ │ │ │ -| while (pos < v.size()) | │ │ │ │ │ -| { | │ │ │ │ │ -| if (v[pos] == c) return pos; | │ │ │ │ │ -| ++pos; | │ │ │ │ │ -| } | │ │ │ │ │ -| return string_view::npos; | │ │ │ │ │ |} | │ │ │ │ │ | | │ │ │ │ │ -|// internal | │ │ │ │ │ -|inline string_view::size_type find_first_of(string_view const v, char const* c | │ │ │ │ │ -| , string_view::size_type pos) | │ │ │ │ │ -|{ | │ │ │ │ │ -| while (pos < v.size()) | │ │ │ │ │ +|_#_e_n_d_i_f_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |include the number of peers received from this tracker, at last announce | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_a_n_n_o_u_n_c_e___e_n_t_r_y_._h_p_p_:_7_6_ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** iinncclluuddee tthhee nnuummbbeerr ooff ppeeeerrss rreecceeiivveedd ffrroomm tthhiiss ttrraacckkeerr,, aatt llaasstt aannnnoouunnccee ********** | │ │ │ │ │ +|****** ....//iinncclluuddee//lliibbttoorrrreenntt//aannnnoouunnccee__eennttrryy..hhpppp::7766 ****** | │ │ │ │ │ +| struct TORRENT_EXPORT announce_infohash | │ │ │ │ │ | { | │ │ │ │ │ -| if (std::strchr(c, v[pos]) != nullptr) return pos; | │ │ │ │ │ -| ++pos; | │ │ │ │ │ -| } | │ │ │ │ │ -|_ _r_e_t_u_r_n_ _s_t_r_i_n_g___v_i_e_w_:_:_n_p_o_s_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |should this be allocated lazily? | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_p_i_e_c_e___p_i_c_k_e_r_._h_p_p_:_8_0_2_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** sshhoouulldd tthhiiss bbee aallllooccaatteedd llaazziillyy?? ********** | │ │ │ │ │ -|****** ....//iinncclluuddee//lliibbttoorrrreenntt//ppiieeccee__ppiicckkeerr..hhpppp::880022 ****** | │ │ │ │ │ -|// download list it may live in now | │ │ │ │ │ -| std::vector::iterator update_piece_state( | │ │ │ │ │ -| std::vector::iterator dp); | │ │ │ │ │ -| | │ │ │ │ │ -| private: | │ │ │ │ │ -| | │ │ │ │ │ -|#if TORRENT_USE_ASSERTS || TORRENT_USE_INVARIANT_CHECKS | │ │ │ │ │ -| index_range categories() const | │ │ │ │ │ -| { return {{}, piece_picker::piece_pos::num_download_categories}; } | │ │ │ │ │ -|#endif | │ │ │ │ │ -| | │ │ │ │ │ -| // the following vectors are mutable because they sometimes may | │ │ │ │ │ -| // be updated lazily, triggered by const functions | │ │ │ │ │ -| | │ │ │ │ │ -| // this maps indices to number of peers that has this piece and | │ │ │ │ │ -| // index into the m_piece_info vectors. | │ │ │ │ │ -| // piece_pos::we_have_index means that we have the piece, so it | │ │ │ │ │ -| // doesn't exist in the piece_info buckets | │ │ │ │ │ -| // pieces with the filtered flag set doesn't have entries in | │ │ │ │ │ -| // the m_piece_info buckets either | │ │ │ │ │ -|mutable aux::vector m_piece_map; | │ │ │ │ │ -| | │ │ │ │ │ -| // tracks the number of bytes in a specific piece that are part of a pad | │ │ │ │ │ -| // file. The padding is assumed to be at the end of the piece, and the | │ │ │ │ │ -| // blocks covered by the pad bytes are not picked by the piece picker | │ │ │ │ │ -| std::unordered_map m_pads_in_piece; | │ │ │ │ │ -| | │ │ │ │ │ -| // when the adjacent_piece affinity is enabled, this contains the most | │ │ │ │ │ -| // recent "extents" of adjacent pieces that have been requested from | │ │ │ │ │ -| // this is mutable because it's updated by functions to pick pieces, which | │ │ │ │ │ -| // are const. That's an efficient place to update it, since it's being | │ │ │ │ │ -| // traversed already. | │ │ │ │ │ -| mutable std::vector m_recent_extents; | │ │ │ │ │ -| | │ │ │ │ │ -| // the number of bytes of pad file set in this piece picker | │ │ │ │ │ -| int m_num_pad_bytes = 0; | │ │ │ │ │ -| | │ │ │ │ │ -| // the number of pad blocks that we already have | │ │ │ │ │ -| int m_have_pad_bytes = 0; | │ │ │ │ │ -| | │ │ │ │ │ -| // the number of pad blocks part of filtered pieces we don't have | │ │ │ │ │ -| int m_filtered_pad_bytes = 0; | │ │ │ │ │ -| | │ │ │ │ │ -| // the number of pad blocks we have that are also filtered | │ │ │ │ │ -| int m_have_filtered_pad_bytes = 0; | │ │ │ │ │ -| | │ │ │ │ │ -| // the number of seeds. These are not added to | │ │ │ │ │ -| // the availability counters of the pieces | │ │ │ │ │ -| int m_seeds = 0; | │ │ │ │ │ -| | │ │ │ │ │ -|_ _ _/_/_ _t_h_e_ _n_u_m_b_e_r_ _o_f_ _p_i_e_c_e_s_ _t_h_a_t_ _h_a_v_e_ _p_a_s_s_e_d_ _t_h_e_ _h_a_s_h_ _c_h_e_c_k_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |it would be more intuitive to account "wanted" pieces instead of filtered | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_p_i_e_c_e___p_i_c_k_e_r_._h_p_p_:_8_7_7_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** iitt wwoouulldd bbee mmoorree iinnttuuiittiivvee ttoo aaccccoouunntt ""wwaanntteedd"" ppiieecceess iinnsstteeaadd ooff ffiilltteerreedd ********** | │ │ │ │ │ -|****** ....//iinncclluuddee//lliibbttoorrrreenntt//ppiieeccee__ppiicckkeerr..hhpppp::887777 ****** | │ │ │ │ │ -| // this holds the information of the blocks in partially downloaded | │ │ │ │ │ -| // pieces. the downloading_piece::info index point into this vector for | │ │ │ │ │ -| // its storage | │ │ │ │ │ -| aux::vector m_block_info; | │ │ │ │ │ -| | │ │ │ │ │ -| // these are block ranges in m_block_info that are free. The numbers | │ │ │ │ │ -| // in here, when multiplied by blocks_per_piece is the index to the | │ │ │ │ │ -| // first block in the range that's free to use by a new downloading_piece. | │ │ │ │ │ -| // this is a free-list. | │ │ │ │ │ -| std::vector m_free_block_infos; | │ │ │ │ │ -| | │ │ │ │ │ -| std::uint16_t m_blocks_in_last_piece = 0; | │ │ │ │ │ -| int m_piece_size = 0; | │ │ │ │ │ -| std::int64_t m_total_size = 0; | │ │ │ │ │ -| | │ │ │ │ │ -| // the number of filtered pieces that we don't already | │ │ │ │ │ -| // have. total_number_of_pieces - number_of_pieces_we_have | │ │ │ │ │ -| // - num_filtered is supposed to the number of pieces | │ │ │ │ │ -| // we still want to download | │ │ │ │ │ -|int m_num_filtered = 0; | │ │ │ │ │ -| | │ │ │ │ │ -| // the number of pieces we have that also are filtered | │ │ │ │ │ -| int m_num_have_filtered = 0; | │ │ │ │ │ -| | │ │ │ │ │ -| // we have all pieces in the range [0, m_cursor) | │ │ │ │ │ -| // m_cursor is the first piece we don't have | │ │ │ │ │ -| piece_index_t m_cursor{0}; | │ │ │ │ │ +| // internal | │ │ │ │ │ +| TORRENT_UNEXPORT announce_infohash(); | │ │ │ │ │ | | │ │ │ │ │ -| // we have all pieces in the range [m_reverse_cursor, end) | │ │ │ │ │ -| // m_reverse_cursor is the first piece where we also have | │ │ │ │ │ -| // all the subsequent pieces | │ │ │ │ │ -| piece_index_t m_reverse_cursor{0}; | │ │ │ │ │ +| // if this tracker has returned an error or warning message | │ │ │ │ │ +| // that message is stored here | │ │ │ │ │ +| std::string message; | │ │ │ │ │ | | │ │ │ │ │ -| // the number of pieces we have (i.e. passed + flushed). | │ │ │ │ │ -| // This includes pieces that we have filtered but still have | │ │ │ │ │ -| int m_num_have = 0; | │ │ │ │ │ +| // if this tracker failed the last time it was contacted | │ │ │ │ │ +| // this error code specifies what error occurred | │ │ │ │ │ +| error_code last_error; | │ │ │ │ │ | | │ │ │ │ │ -| // if this is set to true, it means update_pieces() | │ │ │ │ │ -| // has to be called before accessing m_pieces. | │ │ │ │ │ -| mutable bool m_dirty = false; | │ │ │ │ │ -| public: | │ │ │ │ │ +| // the time of next tracker announce | │ │ │ │ │ +| time_point32 next_announce = (time_point32::min)(); | │ │ │ │ │ | | │ │ │ │ │ -| enum { max_pieces = (std::numeric_limits::max)() - 1 }; | │ │ │ │ │ +| // no announces before this time | │ │ │ │ │ +| time_point32 min_announce = (time_point32::min)(); | │ │ │ │ │ | | │ │ │ │ │ -| }; | │ │ │ │ │ -|} | │ │ │ │ │ | | │ │ │ │ │ -|_#_e_n_d_i_f_ _/_/_ _T_O_R_R_E_N_T___P_I_E_C_E___P_I_C_K_E_R___H_P_P___I_N_C_L_U_D_E_D_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |move this to its own .hpp/.cpp pair? | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_k_a_d_e_m_l_i_a_/_m_s_g_._h_p_p_:_8_7_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** mmoovvee tthhiiss ttoo iittss oowwnn ..hhpppp//..ccpppp ppaaiirr?? ********** | │ │ │ │ │ -|****** ....//iinncclluuddee//lliibbttoorrrreenntt//kkaaddeemmlliiaa//mmssgg..hhpppp::8877 ****** | │ │ │ │ │ -|int flags; | │ │ │ │ │ +|// these are either -1 or the scrape information this tracker last | │ │ │ │ │ +| // responded with. *incomplete* is the current number of downloaders in | │ │ │ │ │ +| // the swarm, *complete* is the current number of seeds in the swarm and | │ │ │ │ │ +| // *downloaded* is the cumulative number of completed downloads of this | │ │ │ │ │ +| // torrent, since the beginning of time (from this tracker's point of | │ │ │ │ │ +| // view). | │ │ │ │ │ | | │ │ │ │ │ -| enum { | │ │ │ │ │ -| // this argument is optional, parsing will not | │ │ │ │ │ -| // fail if it's not present | │ │ │ │ │ -| optional = 1, | │ │ │ │ │ -| // for dictionaries, the following entries refer | │ │ │ │ │ -| // to child nodes to this node, up until and including | │ │ │ │ │ -| // the next item that has the last_child flag set. | │ │ │ │ │ -| // these flags are nestable | │ │ │ │ │ -| parse_children = 2, | │ │ │ │ │ -| // this is the last item in a child dictionary | │ │ │ │ │ -| last_child = 4, | │ │ │ │ │ -| // the size argument refers to that the size | │ │ │ │ │ -| // has to be divisible by the number, instead | │ │ │ │ │ -| // of having that exact size | │ │ │ │ │ -| size_divisible = 8 | │ │ │ │ │ -| }; | │ │ │ │ │ -|}; | │ │ │ │ │ +| // if this tracker has returned scrape data, these fields are filled in | │ │ │ │ │ +| // with valid numbers. Otherwise they are set to -1. ``incomplete`` counts | │ │ │ │ │ +| // the number of current downloaders. ``complete`` counts the number of | │ │ │ │ │ +| // current peers completed the download, or "seeds". ``downloaded`` is the | │ │ │ │ │ +| // cumulative number of completed downloads. | │ │ │ │ │ +| int scrape_incomplete = -1; | │ │ │ │ │ +| int scrape_complete = -1; | │ │ │ │ │ +| int scrape_downloaded = -1; | │ │ │ │ │ | | │ │ │ │ │ -|TORRENT_EXTRA_EXPORT bool verify_message_impl(bdecode_node const& message, span desc | │ │ │ │ │ -|, span ret, span error); | │ │ │ │ │ +| // the number of times in a row we have failed to announce to this | │ │ │ │ │ +| // tracker. | │ │ │ │ │ +| std::uint8_t fails : 7; | │ │ │ │ │ | | │ │ │ │ │ -|// verifies that a message has all the required | │ │ │ │ │ -|// entries and returns them in ret | │ │ │ │ │ -|template | │ │ │ │ │ -|bool verify_message(bdecode_node const& msg, key_desc_t const (&desc)[Size] | │ │ │ │ │ -| , bdecode_node (&ret)[Size], span error) | │ │ │ │ │ -|{ | │ │ │ │ │ -| return verify_message_impl(msg, desc, ret, error); | │ │ │ │ │ -|} | │ │ │ │ │ +| // true while we're waiting for a response from the tracker. | │ │ │ │ │ +| bool updating : 1; | │ │ │ │ │ | | │ │ │ │ │ -|} | │ │ │ │ │ -|} | │ │ │ │ │ +| // set to true when we get a valid response from an announce | │ │ │ │ │ +| // with event=started. If it is set, we won't send start in the subsequent | │ │ │ │ │ +| // announces. | │ │ │ │ │ +| bool start_sent : 1; | │ │ │ │ │ | | │ │ │ │ │ -|_#_e_n_d_i_f_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +| // set to true when we send a event=completed. | │ │ │ │ │ +|_ _ _b_o_o_l_ _c_o_m_p_l_e_t_e___s_e_n_t_ _:_ _1_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |since this is a public function, it should probably be moved out of this header and into one with other public functions. | │ │ │ │ │ |_ _ _ _ _ _ _ _ _ _ _ _|_k_a_d_e_m_l_i_a_/_i_t_e_m_._h_p_p_:_6_1_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** ssiinnccee tthhiiss iiss aa ppuubblliicc ffuunnccttiioonn,, iitt sshhoouulldd pprroobbaabbllyy bbee mmoovveedd oouutt ooff tthhiiss hheeaaddeerr aanndd iinnttoo oonnee wwiitthh ootthheerr ppuubblliicc ffuunnccttiioonnss.. ********** | │ │ │ │ │ |****** ....//iinncclluuddee//lliibbttoorrrreenntt//kkaaddeemmlliiaa//iitteemm..hhpppp::6611 ****** | │ │ │ │ │ |#include | │ │ │ │ │ |#include | │ │ │ │ │ | | │ │ │ │ │ @@ -12177,53 +12137,271 @@ │ │ │ │ │ | , secret_key const& sk); | │ │ │ │ │ | explicit item(bdecode_node const& v); | │ │ │ │ │ | | │ │ │ │ │ | void assign(entry v); | │ │ │ │ │ | void assign(entry v, span salt | │ │ │ │ │ | , sequence_number seq | │ │ │ │ │ |_ _ _,_ _p_u_b_l_i_c___k_e_y_ _c_o_n_s_t_&_ _p_k_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/_a_u_x___/ |ensure the alignment is good here | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_p_o_o_l_._h_p_p_:_4_9_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** eennssuurree tthhee aalliiggnnmmeenntt iiss ggoooodd hheerree ********** | │ │ │ │ │ -|****** ....//iinncclluuddee//lliibbttoorrrreenntt//aauuxx__//ppooooll..hhpppp::4499 ****** | │ │ │ │ │ -|POSSIBILITY OF SUCH DAMAGE. | │ │ │ │ │ +|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/ |move this to its own .hpp/.cpp pair? | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_k_a_d_e_m_l_i_a_/_m_s_g_._h_p_p_:_8_7_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** mmoovvee tthhiiss ttoo iittss oowwnn ..hhpppp//..ccpppp ppaaiirr?? ********** | │ │ │ │ │ +|****** ....//iinncclluuddee//lliibbttoorrrreenntt//kkaaddeemmlliiaa//mmssgg..hhpppp::8877 ****** | │ │ │ │ │ +|int flags; | │ │ │ │ │ | | │ │ │ │ │ -|*/ | │ │ │ │ │ +| enum { | │ │ │ │ │ +| // this argument is optional, parsing will not | │ │ │ │ │ +| // fail if it's not present | │ │ │ │ │ +| optional = 1, | │ │ │ │ │ +| // for dictionaries, the following entries refer | │ │ │ │ │ +| // to child nodes to this node, up until and including | │ │ │ │ │ +| // the next item that has the last_child flag set. | │ │ │ │ │ +| // these flags are nestable | │ │ │ │ │ +| parse_children = 2, | │ │ │ │ │ +| // this is the last item in a child dictionary | │ │ │ │ │ +| last_child = 4, | │ │ │ │ │ +| // the size argument refers to that the size | │ │ │ │ │ +| // has to be divisible by the number, instead | │ │ │ │ │ +| // of having that exact size | │ │ │ │ │ +| size_divisible = 8 | │ │ │ │ │ +| }; | │ │ │ │ │ +|}; | │ │ │ │ │ | | │ │ │ │ │ -|#ifndef TORRENT_POOL_HPP | │ │ │ │ │ -|#define TORRENT_POOL_HPP | │ │ │ │ │ +|TORRENT_EXTRA_EXPORT bool verify_message_impl(bdecode_node const& message, span desc | │ │ │ │ │ +|, span ret, span error); | │ │ │ │ │ | | │ │ │ │ │ -|#include "libtorrent/aux_/disable_warnings_push.hpp" | │ │ │ │ │ -|#include | │ │ │ │ │ -|#include | │ │ │ │ │ -|#include "libtorrent/aux_/disable_warnings_pop.hpp" | │ │ │ │ │ +|// verifies that a message has all the required | │ │ │ │ │ +|// entries and returns them in ret | │ │ │ │ │ +|template | │ │ │ │ │ +|bool verify_message(bdecode_node const& msg, key_desc_t const (&desc)[Size] | │ │ │ │ │ +| , bdecode_node (&ret)[Size], span error) | │ │ │ │ │ +|{ | │ │ │ │ │ +| return verify_message_impl(msg, desc, ret, error); | │ │ │ │ │ +|} | │ │ │ │ │ | | │ │ │ │ │ -|namespace libtorrent { | │ │ │ │ │ -|namespace aux { | │ │ │ │ │ +|} | │ │ │ │ │ +|} | │ │ │ │ │ | | │ │ │ │ │ -|struct allocator_new_delete | │ │ │ │ │ +|_#_e_n_d_i_f_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/_a_u_x___/ |remove this constructor. Don't support "uninitialized" trees. This also requires not constructing these for pad-files and small | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_m_e_r_k_l_e___t_r_e_e_._h_p_p_:_8_5_ _ _ _ _ _ _ _ _ _ _ _ _|_f_i_l_e_s_ _a_s_ _w_e_l_l_._ _S_o_,_ _a_ _s_p_a_r_s_e_ _h_a_s_h_ _l_i_s_t_ _i_n_ _t_o_r_r_e_n_t___i_n_f_o_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** rreemmoovvee tthhiiss ccoonnssttrruuccttoorr.. DDoonn''tt ssuuppppoorrtt ""uunniinniittiiaalliizzeedd"" ttrreeeess.. TThhiiss aallssoo rreeqquuiirreess nnoott ccoonnssttrruuccttiinngg tthheessee ffoorr ppaadd--ffiilleess aanndd ssmmaallll ffiilleess aass wweellll.. SSoo,, aa ssppaarrssee hhaasshh lliisstt iinn | │ │ │ │ │ +|ttoorrrreenntt__iinnffoo ********** | │ │ │ │ │ +|****** ....//iinncclluuddee//lliibbttoorrrreenntt//aauuxx__//mmeerrkkllee__ttrreeee..hhpppp::8855 ****** | │ │ │ │ │ +|// The invariant of the tree is that all interior nodes (i.e. all but the very | │ │ │ │ │ +|// bottom leaf nodes, representing block hashes) are either set and valid, or | │ │ │ │ │ +|// clear. No invalid hashes are allowed, and they can only be added by also | │ │ │ │ │ +|// providing proof of being valid. | │ │ │ │ │ +| | │ │ │ │ │ +|// The leaf blocks on the other hand, MAY be invalid. For instance, when adding | │ │ │ │ │ +|// a magnet link for a torrent that we already have files for. Once we have the | │ │ │ │ │ +|// metadata, we have files on disk but no hashes. We won't know whether the data | │ │ │ │ │ +|// on disk is valid or not, until we've downloaded the hashes to validate them. | │ │ │ │ │ +| | │ │ │ │ │ +|// Idea for future space optimization: | │ │ │ │ │ +|// while downloading, we need to store interior nodes of this tree. However, we | │ │ │ │ │ +|// don't need to store the padding. a SHA-256 is 32 bytes. Instead of storing | │ │ │ │ │ +|// the full (padded) tree of SHA-256 hashes, store the full tree of 32 bit | │ │ │ │ │ +|// signed integers, being indices into the actual storage for the tree. We could | │ │ │ │ │ +|// even grow the storage lazily. Instead of storing the padding hashes, use | │ │ │ │ │ +|// negative indices to refer to fixed SHA-256(0), and SHA-256(SHA-256(0)) and so | │ │ │ │ │ +|// on | │ │ │ │ │ +|struct TORRENT_EXTRA_EXPORT merkle_tree | │ │ │ │ │ |{ | │ │ │ │ │ -| using size_type = std::size_t; | │ │ │ │ │ -| using difference_type = std::ptrdiff_t; | │ │ │ │ │ +|merkle_tree() = default; | │ │ │ │ │ +|merkle_tree(int num_blocks, int blocks_per_piece, char const* r); | │ │ │ │ │ | | │ │ │ │ │ -|static char* malloc(size_type const bytes) | │ │ │ │ │ -|{ return new char[bytes]; } | │ │ │ │ │ -| static void free(char* const block) | │ │ │ │ │ -| { delete [] block; } | │ │ │ │ │ -|}; | │ │ │ │ │ +| sha256_hash root() const; | │ │ │ │ │ | | │ │ │ │ │ -|using pool = boost::pool; | │ │ │ │ │ +| void load_tree(span t, std::vector const& verified); | │ │ │ │ │ +| void load_sparse_tree(span t, std::vector const& mask | │ │ │ │ │ +| , std::vector const& verified); | │ │ │ │ │ +| void load_verified_bits(std::vector const& verified); | │ │ │ │ │ | | │ │ │ │ │ -|template | │ │ │ │ │ -|using object_pool = boost::object_pool; | │ │ │ │ │ +| std::size_t size() const; | │ │ │ │ │ +| int end_index() const { return int(size()); } | │ │ │ │ │ | | │ │ │ │ │ -|} | │ │ │ │ │ -|} | │ │ │ │ │ +| bool has_node(int idx) const; | │ │ │ │ │ | | │ │ │ │ │ -|_#_e_n_d_i_f_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +| bool compare_node(int idx, sha256_hash const& h) const; | │ │ │ │ │ +| | │ │ │ │ │ +| sha256_hash operator[](int idx) const; | │ │ │ │ │ +| | │ │ │ │ │ +| std::vector build_vector() const; | │ │ │ │ │ +| std::pair, aux::vector> build_sparse_vector() const; | │ │ │ │ │ +| | │ │ │ │ │ +| // get bits indicating if each leaf hash is verified | │ │ │ │ │ +| std::vector verified_leafs() const; | │ │ │ │ │ +| | │ │ │ │ │ +| // returns true if the entire tree is known and verified | │ │ │ │ │ +| bool is_complete() const; | │ │ │ │ │ +| | │ │ │ │ │ +| // returns true if all block hashes in the specified range have been verified | │ │ │ │ │ +|_ _b_o_o_l_ _b_l_o_c_k_s___v_e_r_i_f_i_e_d_(_i_n_t_ _b_l_o_c_k___i_d_x_,_ _i_n_t_ _n_u_m___b_l_o_c_k_s_)_ _c_o_n_s_t_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/_a_u_x___/ |make this a std::unique_ptr | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_m_e_r_k_l_e___t_r_e_e_._h_p_p_:_1_7_5_ _ _ _ _ _ _ _ _ _ _ _|_]_>_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** mmaakkee tthhiiss aa ssttdd::::uunniiqquuee__ppttrr]]>> ********** | │ │ │ │ │ +|****** ....//iinncclluuddee//lliibbttoorrrreenntt//aauuxx__//mmeerrkkllee__ttrreeee..hhpppp::117755 ****** | │ │ │ │ │ +| int blocks_per_piece() const { return 1 << m_blocks_per_piece_log; } | │ │ │ │ │ +| // the number tree levels per piece. This is 0 if the block layer is also | │ │ │ │ │ +| // the piece layer. | │ │ │ │ │ +| int piece_levels() const { return m_blocks_per_piece_log; } | │ │ │ │ │ +| | │ │ │ │ │ +| int block_layer_start() const; | │ │ │ │ │ +| int piece_layer_start() const; | │ │ │ │ │ +| int num_pieces() const; | │ │ │ │ │ +| int num_leafs() const; | │ │ │ │ │ +| | │ │ │ │ │ +| void optimize_storage(); | │ │ │ │ │ +| void optimize_storage_piece_layer(); | │ │ │ │ │ +| void allocate_full(); | │ │ │ │ │ +| | │ │ │ │ │ +| // a pointer to the root hash for this file. | │ │ │ │ │ +| char const* m_root = nullptr; | │ │ │ │ │ +| | │ │ │ │ │ +| // this is either the full tree, or some sparse representation of it, | │ │ │ │ │ +| // depending on m_mode | │ │ │ │ │ +|aux::vector m_tree; | │ │ │ │ │ +| | │ │ │ │ │ +| // when the full tree is allocated, this has one bit for each block hash. a | │ │ │ │ │ +| // 1 means we have verified the block hash to be correct, otherwise the block | │ │ │ │ │ +| // hash may represent what's on disk, but we haven't been able to verify it | │ │ │ │ │ +| // yet | │ │ │ │ │ +| bitfield m_block_verified; | │ │ │ │ │ +| | │ │ │ │ │ +| // number of blocks in the file this tree represents. The number of leafs in | │ │ │ │ │ +| // the tree is rounded up to an even power of 2. | │ │ │ │ │ +| int m_num_blocks = 0; | │ │ │ │ │ +| | │ │ │ │ │ +| // the number of blocks per piece, specified as how many steps to shift | │ │ │ │ │ +| // right 1 to get the number of blocks in one piece. This is a compact | │ │ │ │ │ +| // representation that's valid because pieces are always powers of 2. | │ │ │ │ │ +| // this is necessary to know which layer in the tree the piece layer is. | │ │ │ │ │ +| std::uint8_t m_blocks_per_piece_log = 0; | │ │ │ │ │ +| | │ │ │ │ │ +| enum class mode_t : std::uint8_t | │ │ │ │ │ +| { | │ │ │ │ │ +| // a default constructed tree is truly empty. It does not even have a | │ │ │ │ │ +| // root hash | │ │ │ │ │ +| uninitialized_tree, | │ │ │ │ │ +| | │ │ │ │ │ +| // we don't have any hashes in this tree. m_tree should be empty | │ │ │ │ │ +| // an empty tree still always have the root hash (available as root()) | │ │ │ │ │ +| empty_tree, | │ │ │ │ │ +| | │ │ │ │ │ +| // in this mode, m_tree represents the full tree, including padding. | │ │ │ │ │ +|_ _ _f_u_l_l___t_r_e_e_,_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/_a_u_x___/ |in C++17, Handler and Storage could just use "auto" | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_a_l_l_o_c_a_t_i_n_g___h_a_n_d_l_e_r_._h_p_p_:_3_1_7_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** iinn CC++++1177,, HHaannddlleerr aanndd SSttoorraaggee ccoouulldd jjuusstt uussee ""aauuttoo"" ********** | │ │ │ │ │ +|****** ....//iinncclluuddee//lliibbttoorrrreenntt//aauuxx__//aallllooccaattiinngg__hhaannddlleerr..hhpppp::331177 ****** | │ │ │ │ │ +| private: | │ │ │ │ │ +| | │ │ │ │ │ +| Handler handler; | │ │ │ │ │ +| handler_storage* storage; | │ │ │ │ │ +|#ifndef BOOST_NO_EXCEPTIONS | │ │ │ │ │ +| error_handler_interface* error_handler; | │ │ │ │ │ +|#endif | │ │ │ │ │ +| }; | │ │ │ │ │ +| | │ │ │ │ │ +| template | │ │ │ │ │ +| aux::allocating_handler | │ │ │ │ │ +| make_handler(Handler handler | │ │ │ │ │ +| , handler_storage& storage | │ │ │ │ │ +| , error_handler_interface& err_handler) | │ │ │ │ │ +| { | │ │ │ │ │ +| return aux::allocating_handler( | │ │ │ │ │ +| std::forward(handler), &storage, &err_handler); | │ │ │ │ │ +| } | │ │ │ │ │ +| | │ │ │ │ │ +|template | │ │ │ │ │ +| struct handler | │ │ │ │ │ +| { | │ │ │ │ │ +| explicit handler(std::shared_ptr p) : ptr_(std::move(p)) {} | │ │ │ │ │ +| | │ │ │ │ │ +| std::shared_ptr ptr_; | │ │ │ │ │ +| | │ │ │ │ │ +| template | │ │ │ │ │ +| void operator()(A&&... a) | │ │ │ │ │ +| { | │ │ │ │ │ +|#ifdef BOOST_NO_EXCEPTIONS | │ │ │ │ │ +| (ptr_.get()->*Handler)(std::forward(a)...); | │ │ │ │ │ +|#else | │ │ │ │ │ +| try | │ │ │ │ │ +| { | │ │ │ │ │ +| (ptr_.get()->*Handler)(std::forward(a)...); | │ │ │ │ │ +| } | │ │ │ │ │ +| catch (system_error const& e) | │ │ │ │ │ +| { | │ │ │ │ │ +| (ptr_.get()->*ErrorHandler)(e.code()); | │ │ │ │ │ +| } | │ │ │ │ │ +| catch (std::exception const& e) | │ │ │ │ │ +| { | │ │ │ │ │ +| (ptr_.get()->*ExceptHandler)(e); | │ │ │ │ │ +|_ _ _ _}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/_a_u_x___/ |it would be nice to not have this be part of session_interface | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_s_e_s_s_i_o_n___i_n_t_e_r_f_a_c_e_._h_p_p_:_2_1_2_ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** iitt wwoouulldd bbee nniiccee ttoo nnoott hhaavvee tthhiiss bbee ppaarrtt ooff sseessssiioonn__iinntteerrffaaccee ********** | │ │ │ │ │ +|****** ....//iinncclluuddee//lliibbttoorrrreenntt//aauuxx__//sseessssiioonn__iinntteerrffaaccee..hhpppp::221122 ****** | │ │ │ │ │ +|virtual void deferred_submit_jobs() = 0; | │ │ │ │ │ +| | │ │ │ │ │ +| virtual std::uint16_t listen_port() const = 0; | │ │ │ │ │ +| virtual std::uint16_t ssl_listen_port() const = 0; | │ │ │ │ │ +| | │ │ │ │ │ +| virtual int listen_port(aux::transport ssl, address const& local_addr) = 0; | │ │ │ │ │ +| | │ │ │ │ │ +| virtual void for_each_listen_socket(std::function f) = 0; | │ │ │ │ │ +| | │ │ │ │ │ +| // ask for which interface and port to bind outgoing peer connections on | │ │ │ │ │ +| virtual tcp::endpoint bind_outgoing_socket(socket_type& s, address const& | │ │ │ │ │ +| remote_address, error_code& ec) const = 0; | │ │ │ │ │ +| virtual bool verify_bound_address(address const& addr, bool utp | │ │ │ │ │ +| , error_code& ec) = 0; | │ │ │ │ │ +| | │ │ │ │ │ +|#ifndef TORRENT_DISABLE_MUTABLE_TORRENTS | │ │ │ │ │ +| virtual std::vector> find_collection( | │ │ │ │ │ +| std::string const& collection) const = 0; | │ │ │ │ │ +|#endif | │ │ │ │ │ +| | │ │ │ │ │ +|virtual proxy_settings proxy() const = 0; | │ │ │ │ │ +| | │ │ │ │ │ +|#if TORRENT_USE_I2P | │ │ │ │ │ +| virtual char const* i2p_session() const = 0; | │ │ │ │ │ +| virtual std::string const& local_i2p_endpoint() const = 0; | │ │ │ │ │ +|#endif | │ │ │ │ │ +| | │ │ │ │ │ +| virtual void prioritize_connections(std::weak_ptr t) = 0; | │ │ │ │ │ +| | │ │ │ │ │ +| virtual void trigger_auto_manage() = 0; | │ │ │ │ │ +| | │ │ │ │ │ +| virtual void apply_settings_pack(std::shared_ptr pack) = 0; | │ │ │ │ │ +| virtual session_settings const& settings() const = 0; | │ │ │ │ │ +| | │ │ │ │ │ +| virtual void queue_tracker_request(tracker_request req | │ │ │ │ │ +| , std::weak_ptr c) = 0; | │ │ │ │ │ +| | │ │ │ │ │ +| // peer-classes | │ │ │ │ │ +| virtual void set_peer_classes(peer_class_set* s, address const& a, socket_type_t st) = 0; | │ │ │ │ │ +| virtual peer_class_pool const& peer_classes() const = 0; | │ │ │ │ │ +| virtual peer_class_pool& peer_classes() = 0; | │ │ │ │ │ +| virtual bool ignore_unchoke_slots_set(peer_class_set const& set) const = 0; | │ │ │ │ │ +| virtual int copy_pertinent_channels(peer_class_set const& set | │ │ │ │ │ +| , int channel, bandwidth_channel** dst, int m) = 0; | │ │ │ │ │ +| virtual int use_quota_overhead(peer_class_set& set, int amount_down, int amount_up) = 0; | │ │ │ │ │ +| | │ │ │ │ │ +| virtual bandwidth_manager* get_bandwidth_manager(int channel) = 0; | │ │ │ │ │ +| | │ │ │ │ │ +| virtual void sent_bytes(int bytes_payload, int bytes_protocol) = 0; | │ │ │ │ │ +| virtual void received_bytes(int bytes_payload, int bytes_protocol) = 0; | │ │ │ │ │ +|_ _ _v_i_r_t_u_a_l_ _v_o_i_d_ _t_r_a_n_c_i_e_v_e___i_p___p_a_c_k_e_t_(_i_n_t_ _b_y_t_e_s_,_ _b_o_o_l_ _i_p_v_6_)_ _=_ _0_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/_a_u_x___/ |make these direct members and generate shared_ptrs to them which alias the listen_socket_t shared_ptr | │ │ │ │ │ |_ _ _ _ _ _ _ _ _ _ _ _|_s_e_s_s_i_o_n___i_m_p_l_._h_p_p_:_2_6_5_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** mmaakkee tthheessee ddiirreecctt mmeemmbbeerrss aanndd ggeenneerraattee sshhaarreedd__ppttrrss ttoo tthheemm wwhhiicchh aalliiaass tthhee lliisstteenn__ssoocckkeett__tt sshhaarreedd__ppttrr ********** | │ │ │ │ │ |****** ....//iinncclluuddee//lliibbttoorrrreenntt//aauuxx__//sseessssiioonn__iimmppll..hhpppp::226655 ****** | │ │ │ │ │ |if (udp_sock) return udp_sock->sock.local_port(); | │ │ │ │ │ | return 0; | │ │ │ │ │ | } | │ │ │ │ │ @@ -12492,231 +12670,14 @@ │ │ │ │ │ | // set to true when we get a valid response from an announce | │ │ │ │ │ | // with event=started. If it is set, we won't send start in the subsequent | │ │ │ │ │ | // announces. | │ │ │ │ │ | bool start_sent : 1; | │ │ │ │ │ | | │ │ │ │ │ | // set to true when we send a event=completed. | │ │ │ │ │ |_ _ _b_o_o_l_ _c_o_m_p_l_e_t_e___s_e_n_t_ _:_ _1_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/_a_u_x___/ |it would be nice to not have this be part of session_interface | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_s_e_s_s_i_o_n___i_n_t_e_r_f_a_c_e_._h_p_p_:_2_1_2_ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** iitt wwoouulldd bbee nniiccee ttoo nnoott hhaavvee tthhiiss bbee ppaarrtt ooff sseessssiioonn__iinntteerrffaaccee ********** | │ │ │ │ │ -|****** ....//iinncclluuddee//lliibbttoorrrreenntt//aauuxx__//sseessssiioonn__iinntteerrffaaccee..hhpppp::221122 ****** | │ │ │ │ │ -|virtual void deferred_submit_jobs() = 0; | │ │ │ │ │ -| | │ │ │ │ │ -| virtual std::uint16_t listen_port() const = 0; | │ │ │ │ │ -| virtual std::uint16_t ssl_listen_port() const = 0; | │ │ │ │ │ -| | │ │ │ │ │ -| virtual int listen_port(aux::transport ssl, address const& local_addr) = 0; | │ │ │ │ │ -| | │ │ │ │ │ -| virtual void for_each_listen_socket(std::function f) = 0; | │ │ │ │ │ -| | │ │ │ │ │ -| // ask for which interface and port to bind outgoing peer connections on | │ │ │ │ │ -| virtual tcp::endpoint bind_outgoing_socket(socket_type& s, address const& | │ │ │ │ │ -| remote_address, error_code& ec) const = 0; | │ │ │ │ │ -| virtual bool verify_bound_address(address const& addr, bool utp | │ │ │ │ │ -| , error_code& ec) = 0; | │ │ │ │ │ -| | │ │ │ │ │ -|#ifndef TORRENT_DISABLE_MUTABLE_TORRENTS | │ │ │ │ │ -| virtual std::vector> find_collection( | │ │ │ │ │ -| std::string const& collection) const = 0; | │ │ │ │ │ -|#endif | │ │ │ │ │ -| | │ │ │ │ │ -|virtual proxy_settings proxy() const = 0; | │ │ │ │ │ -| | │ │ │ │ │ -|#if TORRENT_USE_I2P | │ │ │ │ │ -| virtual char const* i2p_session() const = 0; | │ │ │ │ │ -| virtual std::string const& local_i2p_endpoint() const = 0; | │ │ │ │ │ -|#endif | │ │ │ │ │ -| | │ │ │ │ │ -| virtual void prioritize_connections(std::weak_ptr t) = 0; | │ │ │ │ │ -| | │ │ │ │ │ -| virtual void trigger_auto_manage() = 0; | │ │ │ │ │ -| | │ │ │ │ │ -| virtual void apply_settings_pack(std::shared_ptr pack) = 0; | │ │ │ │ │ -| virtual session_settings const& settings() const = 0; | │ │ │ │ │ -| | │ │ │ │ │ -| virtual void queue_tracker_request(tracker_request req | │ │ │ │ │ -| , std::weak_ptr c) = 0; | │ │ │ │ │ -| | │ │ │ │ │ -| // peer-classes | │ │ │ │ │ -| virtual void set_peer_classes(peer_class_set* s, address const& a, socket_type_t st) = 0; | │ │ │ │ │ -| virtual peer_class_pool const& peer_classes() const = 0; | │ │ │ │ │ -| virtual peer_class_pool& peer_classes() = 0; | │ │ │ │ │ -| virtual bool ignore_unchoke_slots_set(peer_class_set const& set) const = 0; | │ │ │ │ │ -| virtual int copy_pertinent_channels(peer_class_set const& set | │ │ │ │ │ -| , int channel, bandwidth_channel** dst, int m) = 0; | │ │ │ │ │ -| virtual int use_quota_overhead(peer_class_set& set, int amount_down, int amount_up) = 0; | │ │ │ │ │ -| | │ │ │ │ │ -| virtual bandwidth_manager* get_bandwidth_manager(int channel) = 0; | │ │ │ │ │ -| | │ │ │ │ │ -| virtual void sent_bytes(int bytes_payload, int bytes_protocol) = 0; | │ │ │ │ │ -| virtual void received_bytes(int bytes_payload, int bytes_protocol) = 0; | │ │ │ │ │ -|_ _ _v_i_r_t_u_a_l_ _v_o_i_d_ _t_r_a_n_c_i_e_v_e___i_p___p_a_c_k_e_t_(_i_n_t_ _b_y_t_e_s_,_ _b_o_o_l_ _i_p_v_6_)_ _=_ _0_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/_a_u_x___/ |remove this constructor. Don't support "uninitialized" trees. This also requires not constructing these for pad-files and small | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_m_e_r_k_l_e___t_r_e_e_._h_p_p_:_8_5_ _ _ _ _ _ _ _ _ _ _ _ _|_f_i_l_e_s_ _a_s_ _w_e_l_l_._ _S_o_,_ _a_ _s_p_a_r_s_e_ _h_a_s_h_ _l_i_s_t_ _i_n_ _t_o_r_r_e_n_t___i_n_f_o_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** rreemmoovvee tthhiiss ccoonnssttrruuccttoorr.. DDoonn''tt ssuuppppoorrtt ""uunniinniittiiaalliizzeedd"" ttrreeeess.. TThhiiss aallssoo rreeqquuiirreess nnoott ccoonnssttrruuccttiinngg tthheessee ffoorr ppaadd--ffiilleess aanndd ssmmaallll ffiilleess aass wweellll.. SSoo,, aa ssppaarrssee hhaasshh lliisstt iinn | │ │ │ │ │ -|ttoorrrreenntt__iinnffoo ********** | │ │ │ │ │ -|****** ....//iinncclluuddee//lliibbttoorrrreenntt//aauuxx__//mmeerrkkllee__ttrreeee..hhpppp::8855 ****** | │ │ │ │ │ -|// The invariant of the tree is that all interior nodes (i.e. all but the very | │ │ │ │ │ -|// bottom leaf nodes, representing block hashes) are either set and valid, or | │ │ │ │ │ -|// clear. No invalid hashes are allowed, and they can only be added by also | │ │ │ │ │ -|// providing proof of being valid. | │ │ │ │ │ -| | │ │ │ │ │ -|// The leaf blocks on the other hand, MAY be invalid. For instance, when adding | │ │ │ │ │ -|// a magnet link for a torrent that we already have files for. Once we have the | │ │ │ │ │ -|// metadata, we have files on disk but no hashes. We won't know whether the data | │ │ │ │ │ -|// on disk is valid or not, until we've downloaded the hashes to validate them. | │ │ │ │ │ -| | │ │ │ │ │ -|// Idea for future space optimization: | │ │ │ │ │ -|// while downloading, we need to store interior nodes of this tree. However, we | │ │ │ │ │ -|// don't need to store the padding. a SHA-256 is 32 bytes. Instead of storing | │ │ │ │ │ -|// the full (padded) tree of SHA-256 hashes, store the full tree of 32 bit | │ │ │ │ │ -|// signed integers, being indices into the actual storage for the tree. We could | │ │ │ │ │ -|// even grow the storage lazily. Instead of storing the padding hashes, use | │ │ │ │ │ -|// negative indices to refer to fixed SHA-256(0), and SHA-256(SHA-256(0)) and so | │ │ │ │ │ -|// on | │ │ │ │ │ -|struct TORRENT_EXTRA_EXPORT merkle_tree | │ │ │ │ │ -|{ | │ │ │ │ │ -|merkle_tree() = default; | │ │ │ │ │ -|merkle_tree(int num_blocks, int blocks_per_piece, char const* r); | │ │ │ │ │ -| | │ │ │ │ │ -| sha256_hash root() const; | │ │ │ │ │ -| | │ │ │ │ │ -| void load_tree(span t, std::vector const& verified); | │ │ │ │ │ -| void load_sparse_tree(span t, std::vector const& mask | │ │ │ │ │ -| , std::vector const& verified); | │ │ │ │ │ -| void load_verified_bits(std::vector const& verified); | │ │ │ │ │ -| | │ │ │ │ │ -| std::size_t size() const; | │ │ │ │ │ -| int end_index() const { return int(size()); } | │ │ │ │ │ -| | │ │ │ │ │ -| bool has_node(int idx) const; | │ │ │ │ │ -| | │ │ │ │ │ -| bool compare_node(int idx, sha256_hash const& h) const; | │ │ │ │ │ -| | │ │ │ │ │ -| sha256_hash operator[](int idx) const; | │ │ │ │ │ -| | │ │ │ │ │ -| std::vector build_vector() const; | │ │ │ │ │ -| std::pair, aux::vector> build_sparse_vector() const; | │ │ │ │ │ -| | │ │ │ │ │ -| // get bits indicating if each leaf hash is verified | │ │ │ │ │ -| std::vector verified_leafs() const; | │ │ │ │ │ -| | │ │ │ │ │ -| // returns true if the entire tree is known and verified | │ │ │ │ │ -| bool is_complete() const; | │ │ │ │ │ -| | │ │ │ │ │ -| // returns true if all block hashes in the specified range have been verified | │ │ │ │ │ -|_ _b_o_o_l_ _b_l_o_c_k_s___v_e_r_i_f_i_e_d_(_i_n_t_ _b_l_o_c_k___i_d_x_,_ _i_n_t_ _n_u_m___b_l_o_c_k_s_)_ _c_o_n_s_t_;_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/_a_u_x___/ |make this a std::unique_ptr | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_m_e_r_k_l_e___t_r_e_e_._h_p_p_:_1_7_5_ _ _ _ _ _ _ _ _ _ _ _|_]_>_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** mmaakkee tthhiiss aa ssttdd::::uunniiqquuee__ppttrr]]>> ********** | │ │ │ │ │ -|****** ....//iinncclluuddee//lliibbttoorrrreenntt//aauuxx__//mmeerrkkllee__ttrreeee..hhpppp::117755 ****** | │ │ │ │ │ -| int blocks_per_piece() const { return 1 << m_blocks_per_piece_log; } | │ │ │ │ │ -| // the number tree levels per piece. This is 0 if the block layer is also | │ │ │ │ │ -| // the piece layer. | │ │ │ │ │ -| int piece_levels() const { return m_blocks_per_piece_log; } | │ │ │ │ │ -| | │ │ │ │ │ -| int block_layer_start() const; | │ │ │ │ │ -| int piece_layer_start() const; | │ │ │ │ │ -| int num_pieces() const; | │ │ │ │ │ -| int num_leafs() const; | │ │ │ │ │ -| | │ │ │ │ │ -| void optimize_storage(); | │ │ │ │ │ -| void optimize_storage_piece_layer(); | │ │ │ │ │ -| void allocate_full(); | │ │ │ │ │ -| | │ │ │ │ │ -| // a pointer to the root hash for this file. | │ │ │ │ │ -| char const* m_root = nullptr; | │ │ │ │ │ -| | │ │ │ │ │ -| // this is either the full tree, or some sparse representation of it, | │ │ │ │ │ -| // depending on m_mode | │ │ │ │ │ -|aux::vector m_tree; | │ │ │ │ │ -| | │ │ │ │ │ -| // when the full tree is allocated, this has one bit for each block hash. a | │ │ │ │ │ -| // 1 means we have verified the block hash to be correct, otherwise the block | │ │ │ │ │ -| // hash may represent what's on disk, but we haven't been able to verify it | │ │ │ │ │ -| // yet | │ │ │ │ │ -| bitfield m_block_verified; | │ │ │ │ │ -| | │ │ │ │ │ -| // number of blocks in the file this tree represents. The number of leafs in | │ │ │ │ │ -| // the tree is rounded up to an even power of 2. | │ │ │ │ │ -| int m_num_blocks = 0; | │ │ │ │ │ -| | │ │ │ │ │ -| // the number of blocks per piece, specified as how many steps to shift | │ │ │ │ │ -| // right 1 to get the number of blocks in one piece. This is a compact | │ │ │ │ │ -| // representation that's valid because pieces are always powers of 2. | │ │ │ │ │ -| // this is necessary to know which layer in the tree the piece layer is. | │ │ │ │ │ -| std::uint8_t m_blocks_per_piece_log = 0; | │ │ │ │ │ -| | │ │ │ │ │ -| enum class mode_t : std::uint8_t | │ │ │ │ │ -| { | │ │ │ │ │ -| // a default constructed tree is truly empty. It does not even have a | │ │ │ │ │ -| // root hash | │ │ │ │ │ -| uninitialized_tree, | │ │ │ │ │ -| | │ │ │ │ │ -| // we don't have any hashes in this tree. m_tree should be empty | │ │ │ │ │ -| // an empty tree still always have the root hash (available as root()) | │ │ │ │ │ -| empty_tree, | │ │ │ │ │ -| | │ │ │ │ │ -| // in this mode, m_tree represents the full tree, including padding. | │ │ │ │ │ -|_ _ _f_u_l_l___t_r_e_e_,_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/_a_u_x___/ |in C++17, Handler and Storage could just use "auto" | │ │ │ │ │ -|_ _ _ _ _ _ _ _ _ _ _ _|_a_l_l_o_c_a_t_i_n_g___h_a_n_d_l_e_r_._h_p_p_:_3_1_7_ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ -|********** iinn CC++++1177,, HHaannddlleerr aanndd SSttoorraaggee ccoouulldd jjuusstt uussee ""aauuttoo"" ********** | │ │ │ │ │ -|****** ....//iinncclluuddee//lliibbttoorrrreenntt//aauuxx__//aallllooccaattiinngg__hhaannddlleerr..hhpppp::331177 ****** | │ │ │ │ │ -| private: | │ │ │ │ │ -| | │ │ │ │ │ -| Handler handler; | │ │ │ │ │ -| handler_storage* storage; | │ │ │ │ │ -|#ifndef BOOST_NO_EXCEPTIONS | │ │ │ │ │ -| error_handler_interface* error_handler; | │ │ │ │ │ -|#endif | │ │ │ │ │ -| }; | │ │ │ │ │ -| | │ │ │ │ │ -| template | │ │ │ │ │ -| aux::allocating_handler | │ │ │ │ │ -| make_handler(Handler handler | │ │ │ │ │ -| , handler_storage& storage | │ │ │ │ │ -| , error_handler_interface& err_handler) | │ │ │ │ │ -| { | │ │ │ │ │ -| return aux::allocating_handler( | │ │ │ │ │ -| std::forward(handler), &storage, &err_handler); | │ │ │ │ │ -| } | │ │ │ │ │ -| | │ │ │ │ │ -|template | │ │ │ │ │ -| struct handler | │ │ │ │ │ -| { | │ │ │ │ │ -| explicit handler(std::shared_ptr p) : ptr_(std::move(p)) {} | │ │ │ │ │ -| | │ │ │ │ │ -| std::shared_ptr ptr_; | │ │ │ │ │ -| | │ │ │ │ │ -| template | │ │ │ │ │ -| void operator()(A&&... a) | │ │ │ │ │ -| { | │ │ │ │ │ -|#ifdef BOOST_NO_EXCEPTIONS | │ │ │ │ │ -| (ptr_.get()->*Handler)(std::forward(a)...); | │ │ │ │ │ -|#else | │ │ │ │ │ -| try | │ │ │ │ │ -| { | │ │ │ │ │ -| (ptr_.get()->*Handler)(std::forward(a)...); | │ │ │ │ │ -| } | │ │ │ │ │ -| catch (system_error const& e) | │ │ │ │ │ -| { | │ │ │ │ │ -| (ptr_.get()->*ErrorHandler)(e.code()); | │ │ │ │ │ -| } | │ │ │ │ │ -| catch (std::exception const& e) | │ │ │ │ │ -| { | │ │ │ │ │ -| (ptr_.get()->*ExceptHandler)(e); | │ │ │ │ │ -|_ _ _ _}_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/_a_u_x___/ |figure out which version of clang this is supported in | │ │ │ │ │ |_ _ _ _ _ _ _ _ _ _ _ _|_d_e_p_r_e_c_a_t_e_d_._h_p_p_:_4_7_ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ |********** ffiigguurree oouutt wwhhiicchh vveerrssiioonn ooff ccllaanngg tthhiiss iiss ssuuppppoorrtteedd iinn ********** | │ │ │ │ │ |****** ....//iinncclluuddee//lliibbttoorrrreenntt//aauuxx__//ddeepprreeccaatteedd..hhpppp::4477 ****** | │ │ │ │ │ |CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | │ │ │ │ │ |ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | │ │ │ │ │ |POSSIBILITY OF SUCH DAMAGE. | │ │ │ │ │ @@ -12754,7 +12715,46 @@ │ │ │ │ │ |#endif | │ │ │ │ │ | | │ │ │ │ │ |#ifndef TORRENT_DEPRECATED_ENUM | │ │ │ │ │ |#define TORRENT_DEPRECATED_ENUM | │ │ │ │ │ |#endif | │ │ │ │ │ | | │ │ │ │ │ |_#_e_n_d_i_f_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|relevance 0|_._._/_i_n_c_l_u_d_e_/_l_i_b_t_o_r_r_e_n_t_/_a_u_x___/ |ensure the alignment is good here | │ │ │ │ │ +|_ _ _ _ _ _ _ _ _ _ _ _|_p_o_o_l_._h_p_p_:_4_9_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | │ │ │ │ │ +|********** eennssuurree tthhee aalliiggnnmmeenntt iiss ggoooodd hheerree ********** | │ │ │ │ │ +|****** ....//iinncclluuddee//lliibbttoorrrreenntt//aauuxx__//ppooooll..hhpppp::4499 ****** | │ │ │ │ │ +|POSSIBILITY OF SUCH DAMAGE. | │ │ │ │ │ +| | │ │ │ │ │ +|*/ | │ │ │ │ │ +| | │ │ │ │ │ +|#ifndef TORRENT_POOL_HPP | │ │ │ │ │ +|#define TORRENT_POOL_HPP | │ │ │ │ │ +| | │ │ │ │ │ +|#include "libtorrent/aux_/disable_warnings_push.hpp" | │ │ │ │ │ +|#include | │ │ │ │ │ +|#include | │ │ │ │ │ +|#include "libtorrent/aux_/disable_warnings_pop.hpp" | │ │ │ │ │ +| | │ │ │ │ │ +|namespace libtorrent { | │ │ │ │ │ +|namespace aux { | │ │ │ │ │ +| | │ │ │ │ │ +|struct allocator_new_delete | │ │ │ │ │ +|{ | │ │ │ │ │ +| using size_type = std::size_t; | │ │ │ │ │ +| using difference_type = std::ptrdiff_t; | │ │ │ │ │ +| | │ │ │ │ │ +|static char* malloc(size_type const bytes) | │ │ │ │ │ +|{ return new char[bytes]; } | │ │ │ │ │ +| static void free(char* const block) | │ │ │ │ │ +| { delete [] block; } | │ │ │ │ │ +|}; | │ │ │ │ │ +| | │ │ │ │ │ +|using pool = boost::pool; | │ │ │ │ │ +| | │ │ │ │ │ +|template | │ │ │ │ │ +|using object_pool = boost::object_pool; | │ │ │ │ │ +| | │ │ │ │ │ +|} | │ │ │ │ │ +|} | │ │ │ │ │ +| | │ │ │ │ │ +|_#_e_n_d_i_f_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |