From e003bb8ad57e333d571da1c468725abfb70705a9 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Wed, 6 Jul 2005 00:58:23 +0000 Subject: [PATCH] added ip filters and fixed torrent_info::create_torrent() --- Jamfile | 7 +- docs/manual.html | 586 ++++++++++++++++++++-------- docs/manual.rst | 342 ++++++++++++++-- examples/client_test.cpp | 51 ++- examples/make_torrent.cpp | 2 +- include/libtorrent/ip_filter.hpp | 77 ++++ include/libtorrent/session.hpp | 7 +- include/libtorrent/socket.hpp | 2 + include/libtorrent/torrent_info.hpp | 4 +- src/session.cpp | 32 +- src/torrent.cpp | 62 ++- src/torrent_info.cpp | 9 +- 12 files changed, 934 insertions(+), 247 deletions(-) create mode 100644 include/libtorrent/ip_filter.hpp diff --git a/Jamfile b/Jamfile index f92e62222..25b683dbd 100755 --- a/Jamfile +++ b/Jamfile @@ -52,6 +52,7 @@ SOURCES = escape_string.cpp file.cpp identify_client.cpp + ip_filter.cpp peer_connection.cpp piece_picker.cpp policy.cpp @@ -93,8 +94,10 @@ LIBS = ; LIBS += wsock32 ; } -variant release_log : release : TORRENT_VERBOSE_LOGGING ; -variant debug_log : debug : TORRENT_VERBOSE_LOGGING ; +variant release_vlog : release : TORRENT_VERBOSE_LOGGING ; +variant release_log : release : TORRENT_LOGGING ; +variant debug_vlog : debug : TORRENT_VERBOSE_LOGGING ; +variant debug_log : debug : TORRENT_LOGGING ; lib torrent diff --git a/docs/manual.html b/docs/manual.html index 1505e11b8..7d564f802 100755 --- a/docs/manual.html +++ b/docs/manual.html @@ -22,115 +22,126 @@

Contents

@@ -268,9 +279,15 @@ invariant checks and general debug code will be removed. This option takes precedence over other debug settings. +TORRENT_LOGGING +This macro will enable logging of the session +events, such as tracker announces and incoming +connections (as well as blocked connections). + TORRENT_VERBOSE_LOGGING If you define this macro, every peer connection -will log its traffic to a log file. +will log its traffic to a log file as well as +the session log. TORRENT_STORAGE_DEBUG This will enable extra expensive invariant @@ -281,6 +298,17 @@ piece sorting.

If you experience that libtorrent uses unreasonable amounts of cpu, it will definately help to define NDEBUG, since it will remove the invariant checks within the library.

+

The Jamfile has the following build variants:

+
+
    +
  • release - release version without any logging
  • +
  • release_log - release version with standard logging
  • +
  • release_vlog - release version with verbose logging (all peer connections are logged)
  • +
  • debug - debug version without any logging
  • +
  • debug_log - debug version with standard logging
  • +
  • debug_vlog - debug version with verbose logging
  • +
+
@@ -314,53 +342,55 @@ the session, it conta

session

The session class has the following synopsis:

-class session: public boost::noncopyable
-{
+  class session: public boost::noncopyable
+  {
 
-        session(const fingerprint& print = libtorrent::fingerprint("LT", 0, 1, 0, 0));
+          session(const fingerprint& print = libtorrent::fingerprint("LT", 0, 1, 0, 0));
 
-        session(
-                const fingerprint& print
-                , std::pair<int, int> listen_port_range
-                , const char* listen_interface = 0);
+          session(
+                  const fingerprint& print
+                  , std::pair<int, int> listen_port_range
+                  , const char* listen_interface = 0);
 
-        torrent_handle add_torrent(
-                entry const& e
-                , boost::filesystem::path const& save_path
-                , entry const& resume_data = entry()
- , bool compact_mode = true);
+          torrent_handle add_torrent(
+                  entry const& e
+                  , boost::filesystem::path const& save_path
+                  , entry const& resume_data = entry()
+                  , bool compact_mode = true);
 
-        torrent_handle add_torrent(
-                char const* tracker_url
-                , sha1_hash const& info_hash
-                , boost::filesystem::path const& save_path
-                , entry const& resume_data = entry()
- , bool compact_mode = true);
+          torrent_handle add_torrent(
+                  char const* tracker_url
+                  , sha1_hash const& info_hash
+                  , boost::filesystem::path const& save_path
+                  , entry const& resume_data = entry()
+                  , bool compact_mode = true);
 
-        void remove_torrent(torrent_handle const& h);
+          void remove_torrent(torrent_handle const& h);
 
-        void disable_extensions();
-        void enable_extension(peer_connection::extension_index);
+          void disable_extensions();
+          void enable_extension(peer_connection::extension_index);
 
-        void set_http_settings(const http_settings& settings);
+          void set_http_settings(const http_settings& settings);
 
-        void set_upload_rate_limit(int bytes_per_second);
-        void set_download_rate_limit(int bytes_per_second);
-        void set_max_uploads(int limit);
-        void set_max_connections(int limit);
+          void set_upload_rate_limit(int bytes_per_second);
+          void set_download_rate_limit(int bytes_per_second);
+          void set_max_uploads(int limit);
+          void set_max_connections(int limit);
 
-        session_status status() const;
+void set_ip_filter(ip_filter const& f);
 
-        bool is_listening() const;
-        unsigned short listen_port() const;
-        bool listen_on(
-                std::pair<int, int> const& port_range
-                , char const* interface = 0);
+          session_status status() const;
+
+          bool is_listening() const;
+          unsigned short listen_port() const;
+          bool listen_on(
+                  std::pair<int, int> const& port_range
+                  , char const* interface = 0);
 
 
-        std::auto_ptr<alert> pop_alert();
-        void set_severity_level(alert::severity_t s);
-};
+          std::auto_ptr<alert> pop_alert();
+          void set_severity_level(alert::severity_t s);
+  };
 

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

@@ -368,11 +398,10 @@ The main thread will be idle as long it doesn't have any torrents to participate

session()

-session(const fingerprint& print = libtorrent::fingerprint("LT", 0, 1, 0, 0));
-session(
-        const fingerprint& print
+session(fingerprint const& print = libtorrent::fingerprint("LT", 0, 1, 0, 0));
+session(fingerprint const& print
         , std::pair<int, int> listen_port_range
-        , const char* listen_interface = 0);
+        , char const* listen_interface = 0);
 

If the fingerprint in the first overload is ommited, the client will get a default @@ -495,6 +524,18 @@ minimum of at least two connections per torrent, so if you set a too low connections limit, and open too many torrents, the limit will not be met. The number of uploads is at least one per torrent.

+
+

set_ip_filter()

+
+
+void set_ip_filter(ip_filter const& filter);
+
+
+

Sets a filter that will be used to reject and accept incoming as well as outgoing +connections based on their originating ip address. The default filter will allow +connections to any ip address. To build a set of rules for which addresses are +accepted and not, see ip_filter.

+

status()

@@ -603,21 +644,21 @@ public: data_type type() const; - entry(const dictionary_type&); - entry(const string_type&); - entry(const list_type&); - entry(const integer_type&); + entry(dictionary_type const&); + entry(string_type const&); + entry(list_type const&); + entry(integer_type const&); entry(); entry(data_type t); - entry(const entry& e); + entry(entry const& e); ~entry(); - void operator=(const entry& e); - void operator=(const dictionary_type&); - void operator=(const string_type&); - void operator=(const list_type&); - void operator=(const integer_type&); + void operator=(entry const& e); + void operator=(dictionary_type const&); + void operator=(string_type const&); + void operator=(list_type const&); + void operator=(integer_type const&); integer_type& integer(); integer_type const& integer() const; @@ -632,8 +673,8 @@ public: // is a dictionary, otherwise they will throw entry& operator[](char const* key); entry& operator[](std::string const& key); - const entry& operator[](char const* key) const; - const entry& operator[](std::string const& key) const; + entry const& operator[](char const* key) const; + entry const& operator[](std::string const& key) const; entry* find_key(char const* key); entry const* find_key(char const* key) const; @@ -669,7 +710,7 @@ can assign the value you want it to have.

entry torrent_file; // ... -const entry::dictionary_type& dict = torrent_file.dict(); +entry::dictionary_type const& dict = torrent_file.dict(); entry::dictionary_type::const_iterator i; i = dict.find("announce"); if (i != dict.end()) @@ -698,7 +739,7 @@ public: void set_comment(char const* str); void set_piece_size(int size); void set_creator(char const* str); - void set_hash(int index, const sha1_hash& h); + void set_hash(int index, sha1_hash const& h); void add_tracker(std::string const& url, int tier = 0); void add_file(boost::filesystem::path file, size_type size); @@ -718,9 +759,9 @@ public: size_type total_size() const; size_type piece_length() const; int num_pieces() const; - const sha1_hash& info_hash() const; - const std::stirng& name() const; - const std::string& comment() const; + sha1_hash const& info_hash() const; + std::stirng const& name() const; + std::string const& comment() const; boost::optional<boost::posix_time::ptime> creation_date() const; @@ -729,9 +770,79 @@ public: void print(std::ostream& os) const; size_type piece_size(unsigned int index) const; - const sha1_hash& hash_for_piece(unsigned int index) const; + sha1_hash const& hash_for_piece(unsigned int index) const; }; +
+

torrent_info()

+
+
+torrent_info();
+torrent_info(sha1_hash const& info_hash);
+torrent_info(entry const& torrent_file);
+
+
+

The default constructor of torrent_info is used when creating torrent files. It will +initialize the object to an empty torrent, containing no files. The info hash will be set +to 0 when this constructor is used. To use the empty torrent_info object, add files +and piece hashes, announce URLs and optionally a creator tag and comment. To do this you +use the members set_comment(), set_piece_size(), set_creator(), set_hash() +etc.

+

The contructor that takes an info-hash is identical to the default constructor with the +exception that it will initialize the info-hash to the given value. This is used internally +when downloading torrents without the metadata. The metadata will be created by libtorrent +as soon as it has been downloaded from the swarm.

+

The last constructor is the one that is used in most cases. It will create a torrent_info +object from the information found in the given torrent_file. The entry represents a tree +node in an bencoded file. To load an ordinary .torrent file into an entry, use bdecode(), +see bdecode() bencode().

+
+
+

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

+
+
+void set_comment(char const* str);
+void set_piece_size(int size);
+void set_creator(char const* str);
+void set_hash(int index, sha1_hash const& h);
+void add_tracker(std::string const& url, int tier = 0);
+void add_file(boost::filesystem::path file, size_type size);
+
+
+

These files are used when creating a torrent file. set_comment() will simply set +the comment that belongs to this torrent. The comment can be retrieved with the +comment() member.

+

set_piece_size() will set the size of each piece in this torrent. The piece size must +be an even multiple of 2. i.e. usually something like 256 kB, 512 kB, 1024 kB etc. The +size is given in number of bytes.

+

set_creator() is an optional attribute that can be used to identify your application +that was used to create the torrent file.

+

set_hash() writes the hash for the piece with the given piece-index. You have to call +this function for every piece in the torrent. Usually the hasher is used to calculate +the sha1-hash for a piece.

+

add_tracker() adds a tracker to the announce-list. The tier determines the order in +which the trackers are to be tried. For more iformation see trackers().

+

add_file() adds a file to the torrent. The order in which you add files will determine +the order in which they are placed in the torrent file. You have to add at least one file +to the torrent. The path you give has to be a relative path from the root directory +of the torrent. The size is given in bytes.

+

When you have added all the files and hashes to your torrent, you can generate an entry +which then can be encoded as a .torrent file. You do this by calling create_torrent().

+

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

+
+
+

create_torrent()

+
+
+entry create_torrent();
+
+
+

Returns an entry representing the bencoded tree of data that makes up a .torrent file. +You can save this data as a torrent file with bencode() (see bdecode() bencode()), for a +complete example, see make_torrent.

+

This function is not const because it will also set the info-hash of the torrent_info +object.

+

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

@@ -761,7 +872,7 @@ struct file_entry
 int num_files() const;
-const file_entry& file_at(int index) const;
+file_entry const& file_at(int index) const;
 

If you need index-access to files you can use the num_files() and file_at() @@ -781,7 +892,7 @@ the torrent file to the given outstream.

trackers()

-const std::vector<announce_entry>& trackers() const;
+std::vector<announce_entry> const& trackers() const;
 

The trackers() function will return a sorted vector of announce_entry. @@ -820,7 +931,7 @@ be smaller.

 size_type piece_size(unsigned int index) const;
-const sha1_hash& hash_for_piece(unsigned int index) const;
+sha1_hash const& hash_for_piece(unsigned int index) const;
 

hash_for_piece() takes a piece-index and returns the 20-bytes sha1-hash for that @@ -831,8 +942,8 @@ torrent file. For more information on the name() comment() creation_date()

-const std::stirng& name() const;
-const std::string& comment() const;
+std::string const& name() const;
+std::string const& comment() const;
 boost::optional<boost::posix_time::ptime> creation_date() const;
 
@@ -886,6 +997,8 @@ struct torrent_handle bool is_piece_filtered(int index) const; std::vector<bool> filtered_pieces() const; + void filter_files(std::vector<bool> const& files); + bool has_metadata() const; boost::filsystem::path save_path() const; @@ -893,17 +1006,16 @@ struct torrent_handle sha1_hash info_hash() const; - bool operator==(const torrent_handle&) const; - bool operator!=(const torrent_handle&) const; - bool operator<(const torrent_handle&) const; + bool operator==(torrent_handle const&) const; + bool operator!=(torrent_handle const&) const; + bool operator<(torrent_handle const&) const; };

The default constructor will initialize the handle to an invalid state. Which means you cannot perform any operation on it, unless you first assign it a valid handle. If you try to perform any operation on an uninitialized handle, it will throw invalid_handle.

TODO: document trackers() and replace_trackers()

-

TODO: document how to create a .torrent

-

TODO: document filter_piece(), filter_pieces(), is_piece_filtered() and filtered_pieces()

+

TODO: document filter_piece(), filter_pieces(), is_piece_filtered(), filtered_pieces() and filter_files()

save_path()

@@ -1047,8 +1159,8 @@ sha1_hash info_hash() const;

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

-
-

set_max_uploads() set_max_connections()

+
+

set_max_uploads() set_max_connections()

 void set_max_uploads(int max_uploads);
@@ -1096,8 +1208,8 @@ std::vector<char> const& metadata() const;
 .torrent file. This buffer will be valid as long as the torrent is still running. When hashed,
 it will produce the same hash as the info-hash.

-
-

status()

+
+

status()

 torrent_status status();
@@ -1518,6 +1630,64 @@ expand to 2 megs, it will be interrupted before the entire response has been
 uncompressed (given your limit is lower than 2 megs). Default limit is
 1 megabyte.

+
+

ip_filter

+

The ip_filter class is a set of rules that uniquely categorizes all +ip addresses as allowed or disallowed. The default constructor creates +a single rule that allowes all addresses (0.0.0.0 - 255.255.255.255).

+
+
+class ip_filter
+{
+public:
+        enum access_flags { blocked = 1 };
+
+        ip_filter();
+        void add_rule(address first, address last, int flags);
+        int access(address const& addr) const;
+};
+
+
+
+

ip_filter()

+
+
+ip_filter()
+
+
+

Creates a default filter that doesn't filter any address.

+

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

+
+
+

add_rule()

+
+
+void add_rule(address first, address last, int flags);
+
+
+

Adds a rule to the filter. first and last defines a range of +ip addresses that will be marked with the given flags. The flags +can currenly be 0, which means allowed, or ip_filter::blocked, which +means disallowed.

+

postcondition: +access(x) == flags for every x in the range [first, last]

+

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

+
+
+

access()

+
+
+int access(address const& addr) const;
+
+
+

Returns the access permissions for the given address (addr). The permission +can currently be 0 or ip_filter::blocked. The complexity of this operation +is O(log n), where n is the minimum number of non-overlapping ranges to describe +the current filter.

+
+

big_number

Both the peer_id and sha1_hash types are typedefs of the class @@ -2199,6 +2369,104 @@ int main(int argc, char* argv[]) }

+
+

make_torrent

+

Shows how to create a torrent from a directory tree:

+
+#include <iostream>
+#include <fstream>
+#include <iterator>
+#include <iomanip>
+
+#include "libtorrent/entry.hpp"
+#include "libtorrent/bencode.hpp"
+#include "libtorrent/torrent_info.hpp"
+#include "libtorrent/file.hpp"
+#include "libtorrent/storage.hpp"
+#include "libtorrent/hasher.hpp"
+
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/path.hpp>
+#include <boost/filesystem/fstream.hpp>
+
+using namespace boost::filesystem;
+using namespace libtorrent;
+
+void add_files(
+        torrent_info& t
+        , path const& p
+        , path const& l)
+{
+        path f(p / l);
+        if (is_directory(f))
+        {
+                for (directory_iterator i(f), end; i != end; ++i)
+                        add_files(t, p, l / i->leaf());
+        }
+        else
+        {
+                std::cerr << "adding \"" << l.string() << "\"\n";
+                file fi(f, file::in);
+                fi.seek(0, file::end);
+                libtorrent::size_type size = fi.tell();
+                t.add_file(l, size);
+        }
+}
+
+int main(int argc, char* argv[])
+{
+        using namespace libtorrent;
+        using namespace boost::filesystem;
+
+        if (argc != 4)
+        {
+                std::cerr << "usage: make_torrent <output torrent-file> <announce url> <file or directory to create torrent from>\n";
+                return 1;
+        }
+
+        boost::filesystem::path::default_name_check(native);
+
+        try
+        {
+                torrent_info t;
+                path full_path = initial_path() / path(argv[3]);
+                ofstream out(initial_path() / path(argv[1]), std::ios_base::binary);
+
+                int piece_size = 256 * 1024;
+                char const* creator_str = "libtorrent";
+
+                add_files(t, full_path.branch_path(), full_path.leaf());
+                t.set_piece_size(piece_size);
+
+                storage st(t, full_path.branch_path());
+                t.add_tracker(argv[2]);
+
+                // calculate the hash for all pieces
+                int num = t.num_pieces();
+                std::vector<char> buf(piece_size);
+                for (int i = 0; i < num; ++i)
+                {
+                        st.read(&buf[0], i, 0, t.piece_size(i));
+                        hasher h(&buf[0], t.piece_size(i));
+                        t.set_hash(i, h.final());
+                        std::cerr << (i+1) << "/" << num << "\r";
+                }
+
+                t.set_creator(creator_str);
+
+                // create the torrent and print it to out
+                entry e = t.create_torrent();
+                libtorrent::bencode(std::ostream_iterator<char>(out), e);
+        }
+        catch (std::exception& e)
+        {
+                std::cerr << e.what() << "\n";
+        }
+
+        return 0;
+}
+
+

fast resume

diff --git a/docs/manual.rst b/docs/manual.rst index 24714cb89..2432497a7 100755 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -159,8 +159,13 @@ debug and release variants respectively, but adds extra logging (``TORRENT_VERBO | | removed. This option takes precedence over | | | other debug settings. | +--------------------------------+-------------------------------------------------+ +| ``TORRENT_LOGGING`` | This macro will enable logging of the session | +| | events, such as tracker announces and incoming | +| | connections (as well as blocked connections). | ++--------------------------------+-------------------------------------------------+ | ``TORRENT_VERBOSE_LOGGING`` | If you define this macro, every peer connection | -| | will log its traffic to a log file. | +| | will log its traffic to a log file as well as | +| | the session log. | +--------------------------------+-------------------------------------------------+ | ``TORRENT_STORAGE_DEBUG`` | This will enable extra expensive invariant | | | checks in the storage, including logging of | @@ -171,6 +176,14 @@ debug and release variants respectively, but adds extra logging (``TORRENT_VERBO If you experience that libtorrent uses unreasonable amounts of cpu, it will definately help to define ``NDEBUG``, since it will remove the invariant checks within the library. +The ``Jamfile`` has the following build variants: + + * ``release`` - release version without any logging + * ``release_log`` - release version with standard logging + * ``release_vlog`` - release version with verbose logging (all peer connections are logged) + * ``debug`` - debug version without any logging + * ``debug_log`` - debug version with standard logging + * ``debug_vlog`` - debug version with verbose logging using ===== @@ -212,14 +225,14 @@ The ``session`` class has the following synopsis:: entry const& e , boost::filesystem::path const& save_path , entry const& resume_data = entry() - , bool compact_mode = true); + , bool compact_mode = true); torrent_handle add_torrent( char const* tracker_url , sha1_hash const& info_hash , boost::filesystem::path const& save_path , entry const& resume_data = entry() - , bool compact_mode = true); + , bool compact_mode = true); void remove_torrent(torrent_handle const& h); @@ -233,6 +246,8 @@ The ``session`` class has the following synopsis:: void set_max_uploads(int limit); void set_max_connections(int limit); + void set_ip_filter(ip_filter const& f); + session_status status() const; bool is_listening() const; @@ -254,11 +269,10 @@ session() :: - session(const fingerprint& print = libtorrent::fingerprint("LT", 0, 1, 0, 0)); - session( - const fingerprint& print + session(fingerprint const& print = libtorrent::fingerprint("LT", 0, 1, 0, 0)); + session(fingerprint const& print , std::pair listen_port_range - , const char* listen_interface = 0); + , char const* listen_interface = 0); If the fingerprint in the first overload is ommited, the client will get a default fingerprint stating the version of libtorrent. The fingerprint is a short string that will be @@ -391,6 +405,19 @@ connections limit, and open too many torrents, the limit will not be met. The number of uploads is at least one per torrent. +set_ip_filter() +--------------- + + :: + + void set_ip_filter(ip_filter const& filter); + +Sets a filter that will be used to reject and accept incoming as well as outgoing +connections based on their originating ip address. The default filter will allow +connections to any ip address. To build a set of rules for which addresses are +accepted and not, see ip_filter_. + + status() -------- @@ -509,21 +536,21 @@ or a string. This is its synopsis:: data_type type() const; - entry(const dictionary_type&); - entry(const string_type&); - entry(const list_type&); - entry(const integer_type&); + entry(dictionary_type const&); + entry(string_type const&); + entry(list_type const&); + entry(integer_type const&); entry(); entry(data_type t); - entry(const entry& e); + entry(entry const& e); ~entry(); - void operator=(const entry& e); - void operator=(const dictionary_type&); - void operator=(const string_type&); - void operator=(const list_type&); - void operator=(const integer_type&); + void operator=(entry const& e); + void operator=(dictionary_type const&); + void operator=(string_type const&); + void operator=(list_type const&); + void operator=(integer_type const&); integer_type& integer(); integer_type const& integer() const; @@ -538,8 +565,8 @@ or a string. This is its synopsis:: // is a dictionary, otherwise they will throw entry& operator[](char const* key); entry& operator[](std::string const& key); - const entry& operator[](char const* key) const; - const entry& operator[](std::string const& key) const; + entry const& operator[](char const* key) const; + entry const& operator[](std::string const& key) const; entry* find_key(char const* key); entry const* find_key(char const* key) const; @@ -579,7 +606,7 @@ The typical code to get info from a torrent file will then look like this:: entry torrent_file; // ... - const entry::dictionary_type& dict = torrent_file.dict(); + entry::dictionary_type const& dict = torrent_file.dict(); entry::dictionary_type::const_iterator i; i = dict.find("announce"); if (i != dict.end()) @@ -610,7 +637,7 @@ The ``torrent_info`` has the following synopsis:: void set_comment(char const* str); void set_piece_size(int size); void set_creator(char const* str); - void set_hash(int index, const sha1_hash& h); + void set_hash(int index, sha1_hash const& h); void add_tracker(std::string const& url, int tier = 0); void add_file(boost::filesystem::path file, size_type size); @@ -630,9 +657,9 @@ The ``torrent_info`` has the following synopsis:: size_type total_size() const; size_type piece_length() const; int num_pieces() const; - const sha1_hash& info_hash() const; - const std::stirng& name() const; - const std::string& comment() const; + sha1_hash const& info_hash() const; + std::stirng const& name() const; + std::string const& comment() const; boost::optional creation_date() const; @@ -641,9 +668,90 @@ The ``torrent_info`` has the following synopsis:: void print(std::ostream& os) const; size_type piece_size(unsigned int index) const; - const sha1_hash& hash_for_piece(unsigned int index) const; + sha1_hash const& hash_for_piece(unsigned int index) const; }; +torrent_info() +-------------- + + :: + + torrent_info(); + torrent_info(sha1_hash const& info_hash); + torrent_info(entry const& torrent_file); + +The default constructor of ``torrent_info`` is used when creating torrent files. It will +initialize the object to an empty torrent, containing no files. The info hash will be set +to 0 when this constructor is used. To use the empty ``torrent_info`` object, add files +and piece hashes, announce URLs and optionally a creator tag and comment. To do this you +use the members ``set_comment()``, ``set_piece_size()``, ``set_creator()``, ``set_hash()`` +etc. + +The contructor that takes an info-hash is identical to the default constructor with the +exception that it will initialize the info-hash to the given value. This is used internally +when downloading torrents without the metadata. The metadata will be created by libtorrent +as soon as it has been downloaded from the swarm. + +The last constructor is the one that is used in most cases. It will create a ``torrent_info`` +object from the information found in the given torrent_file. The ``entry`` represents a tree +node in an bencoded file. To load an ordinary .torrent file into an ``entry``, use bdecode(), +see `bdecode() bencode()`_. + +set_comment() set_piece_size() set_creator() set_hash() add_tracker() add_file() +-------------------------------------------------------------------------------- + + :: + + void set_comment(char const* str); + void set_piece_size(int size); + void set_creator(char const* str); + void set_hash(int index, sha1_hash const& h); + void add_tracker(std::string const& url, int tier = 0); + void add_file(boost::filesystem::path file, size_type size); + +These files are used when creating a torrent file. ``set_comment()`` will simply set +the comment that belongs to this torrent. The comment can be retrieved with the +``comment()`` member. + +``set_piece_size()`` will set the size of each piece in this torrent. The piece size must +be an even multiple of 2. i.e. usually something like 256 kB, 512 kB, 1024 kB etc. The +size is given in number of bytes. + +``set_creator()`` is an optional attribute that can be used to identify your application +that was used to create the torrent file. + +``set_hash()`` writes the hash for the piece with the given piece-index. You have to call +this function for every piece in the torrent. Usually the hasher_ is used to calculate +the sha1-hash for a piece. + +``add_tracker()`` adds a tracker to the announce-list. The ``tier`` determines the order in +which the trackers are to be tried. For more iformation see `trackers()`_. + +``add_file()`` adds a file to the torrent. The order in which you add files will determine +the order in which they are placed in the torrent file. You have to add at least one file +to the torrent. The ``path`` you give has to be a relative path from the root directory +of the torrent. The ``size`` is given in bytes. + +When you have added all the files and hashes to your torrent, you can generate an ``entry`` +which then can be encoded as a .torrent file. You do this by calling `create_torrent()`_. + +For a complete example of how to create a torrent from a file structure, see make_torrent_. + + +create_torrent() +---------------- + + :: + + entry create_torrent(); + +Returns an ``entry`` representing the bencoded tree of data that makes up a .torrent file. +You can save this data as a torrent file with bencode() (see `bdecode() bencode()`_), for a +complete example, see make_torrent_. + +This function is not const because it will also set the info-hash of the ``torrent_info`` +object. + begin_files() end_files() rbegin_files() rend_files() ----------------------------------------------------- @@ -678,7 +786,7 @@ num_files() file_at() :: int num_files() const; - const file_entry& file_at(int index) const; + file_entry const& file_at(int index) const; If you need index-access to files you can use the ``num_files()`` and ``file_at()`` to access files using indices. @@ -700,7 +808,7 @@ trackers() :: - const std::vector& trackers() const; + std::vector const& trackers() const; The ``trackers()`` function will return a sorted vector of ``announce_entry``. Each announce entry contains a string, which is the tracker url, and a tier index. The @@ -743,7 +851,7 @@ hash_for_piece() info_hash() :: size_type piece_size(unsigned int index) const; - const sha1_hash& hash_for_piece(unsigned int index) const; + sha1_hash const& hash_for_piece(unsigned int index) const; ``hash_for_piece()`` takes a piece-index and returns the 20-bytes sha1-hash for that piece and ``info_hash()`` returns the 20-bytes sha1-hash for the info-section of the @@ -755,8 +863,8 @@ name() comment() creation_date() :: - const std::stirng& name() const; - const std::string& comment() const; + std::string const& name() const; + std::string const& comment() const; boost::optional creation_date() const; ``name()`` returns the name of the torrent. @@ -815,6 +923,8 @@ Its declaration looks like this:: bool is_piece_filtered(int index) const; std::vector filtered_pieces() const; + void filter_files(std::vector const& files); + bool has_metadata() const; boost::filsystem::path save_path() const; @@ -822,9 +932,9 @@ Its declaration looks like this:: sha1_hash info_hash() const; - bool operator==(const torrent_handle&) const; - bool operator!=(const torrent_handle&) const; - bool operator<(const torrent_handle&) const; + bool operator==(torrent_handle const&) const; + bool operator!=(torrent_handle const&) const; + bool operator<(torrent_handle const&) const; }; The default constructor will initialize the handle to an invalid state. Which means you cannot @@ -833,9 +943,7 @@ any operation on an uninitialized handle, it will throw ``invalid_handle``. **TODO: document trackers() and replace_trackers()** -**TODO: document how to create a .torrent** - -**TODO: document filter_piece(), filter_pieces(), is_piece_filtered() and filtered_pieces()** +**TODO: document filter_piece(), filter_pieces(), is_piece_filtered(), filtered_pieces() and filter_files()** save_path() ----------- @@ -1500,6 +1608,70 @@ uncompressed (given your limit is lower than 2 megs). Default limit is 1 megabyte. +ip_filter +========= + +The ``ip_filter`` class is a set of rules that uniquely categorizes all +ip addresses as allowed or disallowed. The default constructor creates +a single rule that allowes all addresses (0.0.0.0 - 255.255.255.255). + + :: + + class ip_filter + { + public: + enum access_flags { blocked = 1 }; + + ip_filter(); + void add_rule(address first, address last, int flags); + int access(address const& addr) const; + }; + + +ip_filter() +----------- + + :: + + ip_filter() + +Creates a default filter that doesn't filter any address. + +postcondition: +``access(x) == 0`` for every ``x`` + + +add_rule() +---------- + + :: + + void add_rule(address first, address last, int flags); + +Adds a rule to the filter. ``first`` and ``last`` defines a range of +ip addresses that will be marked with the given flags. The ``flags`` +can currenly be 0, which means allowed, or ``ip_filter::blocked``, which +means disallowed. + +postcondition: +``access(x) == flags`` for every ``x`` in the range [``first``, ``last``] + +This means that in a case of overlapping ranges, the last one applied takes +precedence. + + +access() +-------- + + :: + + int access(address const& addr) const; + +Returns the access permissions for the given address (``addr``). The permission +can currently be 0 or ``ip_filter::blocked``. The complexity of this operation +is O(``log`` n), where n is the minimum number of non-overlapping ranges to describe +the current filter. + big_number ========== @@ -2258,6 +2430,104 @@ This is a simple client. It doesn't have much output to keep it simple:: return 0; } +make_torrent +------------ + +Shows how to create a torrent from a directory tree:: + + #include + #include + #include + #include + + #include "libtorrent/entry.hpp" + #include "libtorrent/bencode.hpp" + #include "libtorrent/torrent_info.hpp" + #include "libtorrent/file.hpp" + #include "libtorrent/storage.hpp" + #include "libtorrent/hasher.hpp" + + #include + #include + #include + + using namespace boost::filesystem; + using namespace libtorrent; + + void add_files( + torrent_info& t + , path const& p + , path const& l) + { + path f(p / l); + if (is_directory(f)) + { + for (directory_iterator i(f), end; i != end; ++i) + add_files(t, p, l / i->leaf()); + } + else + { + std::cerr << "adding \"" << l.string() << "\"\n"; + file fi(f, file::in); + fi.seek(0, file::end); + libtorrent::size_type size = fi.tell(); + t.add_file(l, size); + } + } + + int main(int argc, char* argv[]) + { + using namespace libtorrent; + using namespace boost::filesystem; + + if (argc != 4) + { + std::cerr << "usage: make_torrent \n"; + return 1; + } + + boost::filesystem::path::default_name_check(native); + + try + { + torrent_info t; + path full_path = initial_path() / path(argv[3]); + ofstream out(initial_path() / path(argv[1]), std::ios_base::binary); + + int piece_size = 256 * 1024; + char const* creator_str = "libtorrent"; + + add_files(t, full_path.branch_path(), full_path.leaf()); + t.set_piece_size(piece_size); + + storage st(t, full_path.branch_path()); + t.add_tracker(argv[2]); + + // calculate the hash for all pieces + int num = t.num_pieces(); + std::vector buf(piece_size); + for (int i = 0; i < num; ++i) + { + st.read(&buf[0], i, 0, t.piece_size(i)); + hasher h(&buf[0], t.piece_size(i)); + t.set_hash(i, h.final()); + std::cerr << (i+1) << "/" << num << "\r"; + } + + t.set_creator(creator_str); + + // create the torrent and print it to out + entry e = t.create_torrent(); + libtorrent::bencode(std::ostream_iterator(out), e); + } + catch (std::exception& e) + { + std::cerr << e.what() << "\n"; + } + + return 0; + } + fast resume =========== diff --git a/examples/client_test.cpp b/examples/client_test.cpp index 249ae25b1..fd686982b 100755 --- a/examples/client_test.cpp +++ b/examples/client_test.cpp @@ -290,6 +290,50 @@ int main(int argc, char* argv[]) ses.set_severity_level(alert::debug); // ses.set_severity_level(alert::info); + // look for ipfilter.dat + // poor man's parser + // reads emule ipfilter files. + // with the following format: + // + // - , , + // + // first-ip is an ip address that defines the first + // address of the range + // last-ip is the last ip address in the range + // access is a number specifying the access control + // for this ip-range. Right now values > 127 = allowed + // and numbers <= 127 = blocked + // the rest of the line is ignored + // + // In the original spec ranges may not overlap, but + // here ranges may overlap, and it is the last added + // rule that has precedence for addresses that may fall + // into more than one range. + std::ifstream in("ipfilter.dat"); + ip_filter filter; + while (in.good()) + { + char line[300]; + in.getline(line, 300); + int len = in.gcount(); + if (len <= 0) continue; + if (line[0] == '#') continue; + int a, b, c, d; + char dummy; + in >> a >> dummy >> b >> dummy >> c >> dummy >> d >> dummy; + address start(a, b, c, d, 0); + in >> a >> dummy >> b >> dummy >> c >> dummy >> d >> dummy; + address last(a, b, c, d, 0); + int flags; + in >> flags; + if (flags <= 127) flags = ip_filter::blocked; + else flags = 0; + if (in.fail()) break; + filter.add_rule(start, last, flags); + } + + ses.set_ip_filter(filter); + for (int i = 0; i < argc-1; ++i) { try @@ -367,6 +411,7 @@ int main(int argc, char* argv[]) torrent_handle h = *i; if (!h.get_torrent_info().is_valid()) continue; + h.pause(); entry data = h.write_resume_data(); std::stringstream s; s << h.get_torrent_info().name() << ".fastresume"; @@ -420,12 +465,12 @@ int main(int argc, char* argv[]) { // limit the bandwidth for all seeding torrents p->handle.set_max_connections(10); - p->handle.set_max_uploads(5); - p->handle.set_upload_limit(10000); + //p->handle.set_max_uploads(5); + //p->handle.set_upload_limit(10000); // all finished downloades are // moved into this directory - p->handle.move_storage("finished"); + //p->handle.move_storage("finished"); events.push_back( p->handle.get_torrent_info().name() + ": " + a->msg()); } diff --git a/examples/make_torrent.cpp b/examples/make_torrent.cpp index 566c49934..154a29ee5 100755 --- a/examples/make_torrent.cpp +++ b/examples/make_torrent.cpp @@ -118,7 +118,7 @@ int main(int argc, char* argv[]) } catch (std::exception& e) { - std::cerr << e.what() << "\n"; + std::cerr << e.what() << "\n"; } return 0; diff --git a/include/libtorrent/ip_filter.hpp b/include/libtorrent/ip_filter.hpp new file mode 100644 index 000000000..44837b859 --- /dev/null +++ b/include/libtorrent/ip_filter.hpp @@ -0,0 +1,77 @@ +/* + +Copyright (c) 2003, Arvid Norberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + * Neither the name of the author nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef IP_FILTER_HPP +#define IP_FILTER_HPP + +#include "libtorrent/socket.hpp" +#include + +namespace libtorrent +{ + +class ip_filter +{ +public: + + enum access_flags + { + blocked = 1 + }; + + ip_filter(); + void add_rule(address first, address last, int flags); + int access(address const& addr) const; + //void print() const; + +private: + struct range + { + range(address addr, int access = 0): start(addr), access(access) {} + bool operator<(range const& r) const + { return start < r.start; } + bool operator<(address const& a) const + { return start < a; } + address start; + // the end of the range is implicit + // and given by the next entry in the set + int access; + }; + + typedef std::set range_t; + range_t m_access_list; +}; + +} + +#endif + diff --git a/include/libtorrent/session.hpp b/include/libtorrent/session.hpp index 6b7d1c107..39da5f978 100755 --- a/include/libtorrent/session.hpp +++ b/include/libtorrent/session.hpp @@ -68,6 +68,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/debug.hpp" #include "libtorrent/peer_request.hpp" #include "libtorrent/piece_block_progress.hpp" +#include "libtorrent/ip_filter.hpp" #if !defined(NDEBUG) && defined(_MSC_VER) # include @@ -200,6 +201,9 @@ namespace libtorrent // in loops that iterate over them. std::vector m_disconnect_peer; + // filters incomming connections + ip_filter m_ip_filter; + // the peer id that is generated at the start of the session peer_id m_peer_id; @@ -266,7 +270,7 @@ namespace libtorrent #ifndef NDEBUG void check_invariant(const char *place = 0); #endif -#ifdef TORRENT_VERBOSE_LOGGING +#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) boost::shared_ptr create_log(std::string const& name); boost::shared_ptr m_logger; #endif @@ -327,6 +331,7 @@ namespace libtorrent void enable_extension(peer_connection::extension_index i); void disable_extensions(); + void set_ip_filter(ip_filter const& f); void set_peer_id(peer_id const& id); void set_key(int key); diff --git a/include/libtorrent/socket.hpp b/include/libtorrent/socket.hpp index 2f904fe9e..1b7bf9602 100755 --- a/include/libtorrent/socket.hpp +++ b/include/libtorrent/socket.hpp @@ -90,6 +90,8 @@ namespace libtorrent std::string as_string() const; unsigned int ip() const { return m_ip; } + bool operator<=(const address& a) const + { if (ip() == a.ip()) return port <= a.port; else return ip() <= a.ip(); } bool operator<(const address& a) const { if (ip() == a.ip()) return port < a.port; else return ip() < a.ip(); } bool operator!=(const address& a) const diff --git a/include/libtorrent/torrent_info.hpp b/include/libtorrent/torrent_info.hpp index 316d2f5f2..ca5382763 100755 --- a/include/libtorrent/torrent_info.hpp +++ b/include/libtorrent/torrent_info.hpp @@ -91,12 +91,12 @@ namespace libtorrent torrent_info(entry const& torrent_file); ~torrent_info(); - entry create_torrent() const; + entry create_torrent(); entry create_info_metadata() const; void set_comment(char const* str); void set_creator(char const* str); void set_piece_size(int size); - void set_hash(int index, const sha1_hash& h); + void set_hash(int index, sha1_hash const& h); void add_tracker(std::string const& url, int tier = 0); void add_file(boost::filesystem::path file, size_type size); diff --git a/src/session.cpp b/src/session.cpp index a35ad42d6..48414789e 100755 --- a/src/session.cpp +++ b/src/session.cpp @@ -68,6 +68,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/file.hpp" #include "libtorrent/allocate_resources.hpp" #include "libtorrent/peer_connection.hpp" +#include "libtorrent/ip_filter.hpp" #if defined(_MSC_VER) && _MSC_VER < 1300 namespace std @@ -232,7 +233,7 @@ namespace libtorrent { namespace detail , m_max_connections(-1) , m_incoming_connection(false) { -#ifdef TORRENT_VERBOSE_LOGGING +#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) m_logger = create_log("main_session"); #endif std::fill(m_extension_enabled, m_extension_enabled @@ -303,7 +304,7 @@ namespace libtorrent { namespace detail std::string msg = "cannot listen on the given interface '" + m_listen_interface.as_string() + "'"; m_alerts.post_alert(listen_failed_alert(msg)); } -#ifdef TORRENT_VERBOSE_LOGGING +#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) std::string msg = "cannot listen on the given interface '" + m_listen_interface.as_string() + "'"; (*m_logger) << msg << "\n"; #endif @@ -320,7 +321,7 @@ namespace libtorrent { namespace detail << ", " << m_listen_port_range.second << "] could be opened for listening"; m_alerts.post_alert(listen_failed_alert(msg.str())); -#ifdef TORRENT_VERBOSE_LOGGING +#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) (*m_logger) << msg.str() << "\n"; #endif m_listen_socket.reset(); @@ -334,7 +335,7 @@ namespace libtorrent { namespace detail m_alerts.post_alert(listen_failed_alert(e.what())); } -#ifdef TORRENT_VERBOSE_LOGGING +#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) if (m_listen_socket) { (*m_logger) << "listening on port: " << m_listen_interface.port << "\n"; @@ -513,7 +514,7 @@ namespace libtorrent { namespace detail } catch(std::exception& e) { -#ifdef TORRENT_VERBOSE_LOGGING +#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) (*m_logger) << "accept failed: " << e.what() << "\n"; #endif } @@ -522,10 +523,17 @@ namespace libtorrent { namespace detail s->set_blocking(false); // we got a connection request! m_incoming_connection = true; -#ifdef TORRENT_VERBOSE_LOGGING +#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) (*m_logger) << s->sender().as_string() << " <== INCOMING CONNECTION\n"; #endif - // TODO: filter ip:s + if (m_ip_filter.access(s->sender()) & ip_filter::blocked) + { +#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) + (*m_logger) << "filtered blocked ip\n"; +#endif + // TODO: issue an info-alert when an ip is blocked + continue; + } boost::shared_ptr c( new peer_connection(*this, m_selector, s)); @@ -622,7 +630,7 @@ namespace libtorrent { namespace detail std::string msg = "cannot listen on the given interface '" + m_listen_interface.as_string() + "'"; m_alerts.post_alert(listen_failed_alert(msg)); } -#ifdef TORRENT_VERBOSE_LOGGING +#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) std::string msg = "cannot listen on the given interface '" + m_listen_interface.as_string() + "'"; (*m_logger) << msg << "\n"; #endif @@ -811,7 +819,7 @@ namespace libtorrent { namespace detail return 0; } -#ifdef TORRENT_VERBOSE_LOGGING +#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) boost::shared_ptr session_impl::create_log(std::string const& name) { // current options are file_logger, cout_logger and null_logger @@ -897,6 +905,12 @@ namespace libtorrent + peer_connection::num_supported_extensions, false); } + void session::set_ip_filter(ip_filter const& f) + { + boost::mutex::scoped_lock l(m_impl.m_mutex); + m_impl.m_ip_filter = f; + } + void session::set_peer_id(peer_id const& id) { boost::mutex::scoped_lock l(m_impl.m_mutex); diff --git a/src/torrent.cpp b/src/torrent.cpp index 0a23b3d5e..a83d63d96 100755 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -321,15 +321,13 @@ namespace libtorrent // connect to random peers from the list std::random_shuffle(peer_list.begin(), peer_list.end()); - #ifdef TORRENT_VERBOSE_LOGGING std::stringstream s; s << "TRACKER RESPONSE:\n" "interval: " << m_duration << "\n" "peers:\n"; for (std::vector::const_iterator i = peer_list.begin(); - i != peer_list.end(); - ++i) + i != peer_list.end(); ++i) { s << " " << std::setfill(' ') << std::setw(16) << i->ip << " " << std::setw(5) << std::dec << i->port << " "; @@ -340,8 +338,7 @@ namespace libtorrent #endif // for each of the peers we got from the tracker for (std::vector::iterator i = peer_list.begin(); - i != peer_list.end(); - ++i) + i != peer_list.end(); ++i) { // don't make connections to ourself if (i->id == m_ses.get_peer_id()) @@ -349,6 +346,14 @@ namespace libtorrent address a(i->ip.c_str(), i->port); + if (m_ses.m_ip_filter.access(a) == ip_filter::blocked) + { +#ifdef TORRENT_VERBOSE_LOGGING + debug_log("blocked ip from tracker: " + i->ip); +#endif + continue; + } + m_policy->peer_from_tracker(a, i->id); } @@ -632,42 +637,35 @@ namespace libtorrent m_picker->filtered_pieces(bitmask); } - //suggest using this function on single file in a torrent file - //suggest using this function after filter_files() function - //or change selective download policy casually during downloading progress + //idea from Arvid and MooPolice + //todo refactoring and improving the function body void torrent::filter_file(int index, bool filter) { // this call is only valid on torrents with metadata if (!valid_metadata()) return; - assert(index >= 0); assert(index < m_torrent_file.num_files()); - - entry::integer_type position = 0; + assert(index >= 0); - if (m_torrent_file.num_pieces()) - { - int piece_length = m_torrent_file.piece_length(); - entry::integer_type start = position; + entry::integer_type start_position = 0; + int start_piece_index = 0; + int end_piece_index = 0; - for (int i = 0; i < index; ++i) - { - start = position; - position += m_torrent_file.file_at(i).size; - } - int start_piece = int(start / piece_length); - int last_piece = int(position / piece_length); - - for (int filter_index = start_piece ; filter_index < last_piece ; ++filter_index) - { - filter_piece(filter_index, filter); - } - } + // TODO: just skipping the first and last piece is not a good idea. + // they should only be skipped if there are files that are wanted + // that span those pieces. Maybe this function should be removed. + for (int i = 0; i < index; ++i) + start_position += m_torrent_file.file_at(i).size; + + start_position = start_position + 1; + + start_piece_index = start_position / m_torrent_file.piece_length(); + end_piece_index = start_piece_index + m_torrent_file.file_at(index).size/(m_torrent_file.piece_length()); + + for(int i = start_piece_index; i < end_piece_index; ++i) + filter_piece(i, filter); } - //suggest using this function on a torrent file. - //suggest using this function as a static globle selective download policy - //"before" downloading progress void torrent::filter_files(std::vector const& bitmask) { // this call is only valid on torrents with metadata @@ -685,7 +683,7 @@ namespace libtorrent // mark all pieces as filtered, then clear the bits for files // that should be downloaded std::vector piece_filter(m_torrent_file.num_pieces(), true); - for (int i = 0; i < bitmask.size(); ++i) + for (int i = 0; i < (int)bitmask.size(); ++i) { entry::integer_type start = position; position += m_torrent_file.file_at(i).size; diff --git a/src/torrent_info.cpp b/src/torrent_info.cpp index 72ea6d19d..5b194b6d2 100755 --- a/src/torrent_info.cpp +++ b/src/torrent_info.cpp @@ -123,6 +123,7 @@ namespace libtorrent // constructor used for creating new torrents // will not contain any hashes, comments, creation date // just the necessary to use it with piece manager + // used for torrents with no metadata torrent_info::torrent_info(sha1_hash const& info_hash) : m_piece_length(256 * 1024) , m_total_size(0) @@ -440,7 +441,7 @@ namespace libtorrent return info; } - entry torrent_info::create_torrent() const + entry torrent_info::create_torrent() { assert(m_piece_length > 0); @@ -490,9 +491,13 @@ namespace libtorrent dict["created by"] = m_created_by; dict["info"] = create_info_metadata(); - dict.sort(); + entry const& info_section = dict["info"]; + std::vector buf; + bencode(std::back_inserter(buf), info_section); + m_info_hash = hasher(&buf[0], buf.size()).final(); + return dict; }