on - build with support for tracker less
torrents and DHT support.
@@ -494,6 +494,17 @@ boost.date_time.
+
statistics
+
+
off - default. No logging of additional
+stats.
+
on - log session statistics in current
+working directory session_stats<pid>. The log
+is rotated every hour. It can be parsed by the
+parse_session_stats.py script (requires gnuplot)
+
+
+
The variant feature is implicit, which means you don't need to specify
diff --git a/docs/client_test.html b/docs/client_test.html
index debf477eb..e284688e7 100644
--- a/docs/client_test.html
+++ b/docs/client_test.html
@@ -3,7 +3,7 @@
dht_upload_rate_limit sets the rate limit on the DHT. This is specified in
bytes per second and defaults to 4000. For busy boxes with lots of torrents
that requires more DHT traffic, this should be raised.
-
unchoke_slots_limit is the max number of unchoked peers in the session.
-
The number of unchoke slots may be ignored depending on what
-choking_algorithm is set to.
+
unchoke_slots_limit is the max number of unchoked peers in the session. The
+number of unchoke slots may be ignored depending on what choking_algorithm
+is set to. A value of -1 means infinite.
half_open_limit sets the maximum number of half-open connections
libtorrent will have when connecting to peers. A half-open connection is one
where connect() has been called, but the connection still hasn't been established
diff --git a/docs/projects.html b/docs/projects.html
index fcad56a5f..cb30515f7 100644
--- a/docs/projects.html
+++ b/docs/projects.html
@@ -3,7 +3,7 @@
remove the read timeout concept. This should not be necessary
remove the read timeout concept. This should not be necessary
src/utp_stream.cpp:412
// these are the callbacks made into the utp_stream object
- // on read/write/connect events
- utp_stream::handler_t m_read_handler;
- utp_stream::handler_t m_write_handler;
- utp_stream::connect_handler_t m_connect_handler;
+
class TORRENT_EXPORT natpmp : public intrusive_ptr_base<natpmp>
+
{
+public:
+ natpmp(io_service& ios, address const& listen_interface
+ , portmap_callback_t const& cb
+ , log_callback_t const& lcb);
- // the address of the remote endpoint
- address m_remote_address;
+ void rebind(address const& listen_interface);
- // the local address
- address m_local_address;
+ // maps the ports, if a port is set to 0
+ // it will not be mapped
+ enum protocol_type { none = 0, udp = 1, tcp = 2 };
+ int add_mapping(protocol_type p, int external_port, int local_port);
+ void delete_mapping(int mapping_index);
+ bool get_mapping(int mapping_index, int& local_port, int& external_port, int& protocol) const;
- // the send and receive buffers
- // maps packet sequence numbers
- packet_buffer m_inbuf;
- packet_buffer m_outbuf;
+ void close();
- // timers when we should trigger the read and
- // write callbacks (unless the buffers fill up
- // before)
- ptime m_read_timeout;
-
-
ptime m_write_timeout;
-
- // the time when the last packet we sent times out. Including re-sends.
- // if we ever end up not having sent anything in one second (
- // or one mean rtt + 2 average deviations, whichever is greater)
- // we set our cwnd to 1 MSS. This condition can happen either because
- // a packet has timed out and needs to be resent or because our
- // cwnd is set to less than one MSS during congestion control.
- // it can also happen if the other end sends an advertized window
- // size less than one MSS.
- ptime m_timeout;
+private:
- // the last time we wanted to send more data, but couldn't because
- // it would bring the number of outstanding bytes above the cwnd.
- // this is used to restrict increasing the cwnd size when we're
- // not sending fast enough to need it bigger
- ptime m_last_cwnd_hit;
+ void update_mapping(int i, mutex::scoped_lock& l);
+ void send_map_request(int i, mutex::scoped_lock& l);
+ void send_get_ip_address_request(mutex::scoped_lock& l);
+ void resend_request(int i, error_code const& e);
+ void on_reply(error_code const& e
+ , std::size_t bytes_transferred);
+ void try_next_mapping(int i, mutex::scoped_lock& l);
+ void update_expiration_timer(mutex::scoped_lock& l);
+ void mapping_expired(error_code const& e, int i);
+ void close_impl(mutex::scoped_lock& l);
- // the last time we stepped the timestamp history
- ptime m_last_history_step;
+
#include "libtorrent/config.hpp"
+#include "libtorrent/assert.hpp"
- // the max number of bytes in-flight. This is a fixed point
- // value, to get the true number of bytes, shift right 16 bits
- // the value is always >= 0, but the calculations performed on
- // it in do_ledbat() are signed.
- boost::int64_t m_cwnd;
+#if TORRENT_USE_IOSTREAM
+#include "libtorrent/escape_string.hpp" // to_hex, from_hex
+#include <iostream>
+#include <iomanip>
+#endif
- timestamp_history m_delay_hist;
- timestamp_history m_their_delay_hist;
+#ifdef max
+#undef max
+#endif
- // the number of bytes we have buffered in m_inbuf
-
remove this dependency by having the dht observer have its own flags
remove this dependency by having the dht observer
-have its own flags
src/kademlia/rpc_manager.cpp:36
contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
+#ifdef min
+#undef min
+#endif
-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
+namespace libtorrent
+{
+
+
class port_filter;
+ class connection_queue;
+ class natpmp;
+ class upnp;
+ class alert;
+
+ TORRENT_EXPORT session_settings min_memory_usage();
+ TORRENT_EXPORT session_settings high_performance_seed();
+
+#ifndef TORRENT_CFG
+#error TORRENT_CFG is not defined!
+#endif
+
+ void TORRENT_EXPORT TORRENT_CFG();
+
+ namespace aux
+ {
+ // workaround for microsofts
+ // hardware exceptions that makes
+ // it hard to debug stuff
+
#ifdef _MSC_VER
+
struct TORRENT_EXPORT eh_initializer
+ {
+ eh_initializer();
+ static void straight_to_debugger(unsigned int, _EXCEPTION_POINTERS*)
+ { throw; }
+ };
+#else
+ struct eh_initializer {};
+#endif
+ struct session_impl;
+ }
+
+ class TORRENT_EXPORT session_proxy
+ {
+ friend class session;
+ public:
+ session_proxy() {}
+ private:
+ session_proxy(boost::shared_ptr<aux::session_impl> impl)
+ : m_impl(impl) {}
+ boost::shared_ptr<aux::session_impl> m_impl;
+ };
+
+#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
+#define TORRENT_LOGPATH_ARG_DEFAULT , std::string logpath = "."
+#else
+#define TORRENT_LOGPATH_ARG_DEFAULT
+#endif
+
+ // Once it's created, the session object will spawn the main thread that will do all the work.
+
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)
@@ -167,41 +239,195 @@ POSSIBILITY OF SUCH DAMAGE.
*/
-#include "libtorrent/pch.hpp"
-#include "libtorrent/socket.hpp"
+#ifndef TORRENT_TIME_HPP_INCLUDED
+#define TORRENT_TIME_HPP_INCLUDED
-
// if the user wanted to remove this while
+ // we were resolving it. In this case, we set
+ // the removed flag to true, to make the resolver
+ // callback remove it
+ bool removed;
+
+ tcp::endpoint endpoint;
+
+ // this is the peer_info field used for the
+ // connection, just to count hash failures
+ // it's also used to hold the peer_connection
+ // pointer, when the web seed is connected
+ policy::peer peer_info;
+ };
+
+#ifndef BOOST_NO_EXCEPTIONS
+ // for backwards compatibility with 0.14
+ typedef libtorrent_exception invalid_torrent_file;
#endif
-namespace libtorrent { namespace dht
-{
+
int TORRENT_EXPORT load_file(std::string const& filename
+
, std::vector<char>& v, error_code& ec, int limit = 8000000);
-namespace io = libtorrent::detail;
+ class TORRENT_EXPORT torrent_info : public intrusive_ptr_base<torrent_info>
+ {
+ public:
-#ifdef TORRENT_DHT_VERBOSE_LOGGING
-TORRENT_DEFINE_LOG(rpc)
-
m_downloads size will be > 0 just by having pad-files in the torrent. That should be taken into account here.
m_downloads size will be > 0 just by having pad-files
+in the torrent. That should be taken into account here.
../src/piece_picker.cpp:1489
// have an affinity to pick pieces in the same speed
// category.
// * ignore_whole_pieces
// ignores the prefer_whole_pieces parameter (as if
@@ -356,7 +582,7 @@ in the torrent. That should be taken into account here.
src/piece_picker
// ignored as long as possible. All blocks found in downloading
// pieces are regarded as backup blocks
-
if we still can't find the torrent, we should probably look for it by url here
if we still can't find the torrent, we should probably look for it by url here
../src/session_impl.cpp:5157
}
}
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
else
@@ -407,7 +633,7 @@ in the torrent. That should be taken into account here.
if (info_hash != m_torrent_file->info_hash())
{
if (alerts().should_post<metadata_failed_alert>())
@@ -458,7 +684,58 @@ in the torrent. That should be taken into account here.
src/piece_picker
{
std::set<peer_connection*>::iterator p = i++;
(*p)->disconnect_if_redundant();
-
UTP_STATE_ERROR_WAIT,
// there are no more references to this socket
// and we can delete it
@@ -498,6 +775,10 @@ in the torrent. That should be taken into account here.
src/piece_picker
// manager will send acks for all sockets on this list.
bool m_deferred_ack:1;
+ // this is true if this socket has subscribed to be notified
+ // when this receive round is done
+ bool m_subscribe_drained:1;
+
// if this socket tries to send a packet via the utp socket
// manager, and it fails with EWOULDBLOCK, the socket
// is stalled and this is set. It's also added to a list
@@ -505,19 +786,9 @@ in the torrent. That should be taken into account here.
src/piece_picker
// the socket being writable again
bool m_stalled:1;
};
-
-#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
-int socket_impl_size() { return sizeof(utp_socket_impl); }
-#endif
-
we might want to do something else here as well, to resend the packet immediately without it being an MTU probe
we might want to do something else here
as well, to resend the packet immediately without
-it being an MTU probe
src/utp_stream.cpp:1850
, boost::uint32_t(h->timestamp_difference_microseconds), int(p->mtu_probe)
- , h->extension);
-#endif
-
- error_code ec;
-#ifdef TORRENT_DEBUG
- // simulate 1% packet loss
+it being an MTU probe
../src/utp_stream.cpp:1862
// simulate 1% packet loss
// if ((rand() % 100) > 0)
#endif
m_sm->send_packet(udp::endpoint(m_remote_address, m_port)
@@ -528,11 +799,28 @@ it being an MTU probe
fix this stats logging. For instance, the stats counters could be factored out into its own class, and dht_tracker could take an optional reference to it ++m_replies_sent[e["r"]]; m_replies_bytes_sent[e["r"]] += int(m_send_buf.size());
fix this stats logging. For instance, the stats counters could be factored out into its own class, and dht_tracker could take an optional reference to it ++m_replies_sent[e["r"]]; m_replies_bytes_sent[e["r"]] += int(m_send_buf.size());
fix this stats logging. For instance,
the stats counters could be factored out into its own
class, and dht_tracker could take an optional reference to it
++m_replies_sent[e["r"]];
-m_replies_bytes_sent[e["r"]] += int(m_send_buf.size());
this should be a deque, since time critical pieces are expected to be popped in the same order as they are sorted. The expectation is that new items are pushed back and items are popped from the front
this should be a deque, since time critical
-pieces are expected to be popped in the same order
-as they are sorted. The expectation is that new items
-are pushed back and items are popped from the front
include/libtorrent/torrent.hpp:1044
- struct time_critical_piece
- {
- // when this piece was first requested
- ptime first_requested;
- // when this piece was last requested
- ptime last_requested;
- // by what time we want this piece
- ptime deadline;
- // 1 = send alert with piece data when available
- int flags;
- // how many peers it's been requested from
- int peers;
- // the piece index
- int piece;
- bool operator<(time_critical_piece const& rhs) const
- { return deadline < rhs.deadline; }
- };
-
- // this list is sorted by time_critical_piece::deadline
-
- std::string m_trackerid;
- std::string m_username;
- std::string m_password;
-
- // the network interfaces outgoing connections
- // are opened through. If there is more then one,
- // they are used in a round-robin fasion
- std::vector<union_endpoint> m_net_interfaces;
-
- std::string m_save_path;
-
- // if we don't have the metadata, this is a url to
- // the torrent file
- std::string m_url;
-
- // if this was added from an RSS feed, this is the unique
- // identifier in the feed.
- std::string m_uuid;
-
- // if this torrent was added by an RSS feed, this is the
- // URL to that feed
- std::string m_source_feed_url;
-
- // this is used as temporary storage while downloading
- // the .torrent file from m_url
- std::vector<char> m_torrent_file_buf;
-
- // each bit represents a piece. a set bit means
- // the piece has had its hash verified. This
-
these strings (m_comment, m_created_by, m_ssl_root_cert) could be lazy_entry* to save memory
these strings (m_comment, m_created_by, m_ssl_root_cert) could be lazy_entry* to save memory
../include/libtorrent/torrent_info.hpp:468
std::vector<announce_entry> m_urls;
std::vector<web_seed_entry> m_web_seeds;
nodes_t m_nodes;
@@ -762,8 +985,8 @@ are pushed back and items are popped from the front
include/libtorrent/t
// this is used when creating a torrent. If there's
// only one file there are cases where it's impossible
// to know if it should be written as a multifile torrent
-
in chunked encoding mode, this assert won't hold. the chunk headers should be subtracted from the receive_buffer_size
in chunked encoding mode, this assert won't hold.
+the chunk headers should be subtracted from the receive_buffer_size
../src/http_seed_connection.cpp:120
boost::optional<piece_block_progress>
http_seed_connection::downloading_piece_progress() const
{
if (m_requests.empty())
@@ -814,8 +1037,8 @@ the chunk headers should be subtracted from the receive_buffer_size
report the proper address of the router as the source IP of this understanding of our external address, instead of the empty address
report the proper address of the router as the source IP of
+this understanding of our external address, instead of the empty address
../src/session_impl.cpp:5517
void session_impl::on_port_mapping(int mapping, address const& ip, int port
, error_code const& ec, int map_transport)
{
TORRENT_ASSERT(is_network_thread());
@@ -918,7 +1141,7 @@ this understanding of our external address, instead of the empty address
we only need to do this if our global IPv4 address has changed since the DHT (currently) only supports IPv4. Since restarting the DHT is kind of expensive, it would be nice to not do it unnecessarily
we only need to do this if our global IPv4 address has changed
+
we only need to do this if our global IPv4 address has changed since the DHT (currently) only supports IPv4. Since restarting the DHT is kind of expensive, it would be nice to not do it unnecessarily
we only need to do this if our global IPv4 address has changed
since the DHT (currently) only supports IPv4. Since restarting the DHT
-is kind of expensive, it would be nice to not do it unnecessarily
src/session_impl.cpp:6138
void session_impl::set_external_address(address const& ip
+is kind of expensive, it would be nice to not do it unnecessarily
../src/session_impl.cpp:6196
void session_impl::set_external_address(address const& ip
, int source_type, address const& source)
{
#if defined TORRENT_VERBOSE_LOGGING
@@ -1022,11 +1245,11 @@ is kind of expensive, it would be nice to not do it unnecessarily
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 the filesystem doesn't support sparse files, only zero the priorities of the pieces that are at the tails of all files, leaving everything up to the highest written piece in each file
make this depend on the error and on the filesystem the
+
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 the filesystem doesn't support sparse files, only zero the priorities of the pieces that are at the tails of all files, leaving everything up to the highest written piece in each file
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 the filesystem doesn't support sparse files, only zero the priorities
of the pieces that are at the tails of all files, leaving everything
-up to the highest written piece in each file
src/torrent.cpp:1113
if (c) c->disconnect(errors::no_memory);
+up to the highest written piece in each file
../src/torrent.cpp:1167
if (c) c->disconnect(errors::no_memory);
return;
}
@@ -1077,8 +1300,8 @@ up to the highest written piece in each file
ideally, we would disconnect the oldest connection i.e. the one that has waited the longest to connect.
ideally, we would disconnect the oldest connection
+i.e. the one that has waited the longest to connect.
../src/torrent.cpp:6051
if (m_ses.is_aborted())
{
p->disconnect(errors::session_closing);
return false;
@@ -1181,10 +1404,10 @@ i.e. the one that has waited the longest to connect.
src/torrent.cpp:599
{
boost::shared_ptr<peer_plugin> pp((*i)->new_connection(p));
if (pp) p->add_extension(pp);
-
this logic should be a separate step done once the torrent is loaded, and the original filenames should be preserved!
this logic should be a separate step
+ // on windows, the max path is expressed in
+ // unicode characters, not bytes
+#if defined TORRENT_WINDOWS
+ std::wstring path_element;
+ utf8_wchar(element, path_element);
+ if (path_element.size() <= max_path_len) return;
+
+ // truncate filenames that are too long. But keep extensions!
+ std::wstring ext;
+ wchar_t const* ext1 = wcsrchr(path_element.c_str(), '.');
+ if (ext1 != NULL) ext = ext1;
+
+ if (ext.size() > 15)
+ {
+ path_element.resize(max_path_len);
+ }
+ else
+
once the filename renaming is removed from here this check can be removed as well
once the filename renaming is removed from here
+this check can be removed as well
../src/torrent_info.cpp:416
if (!extract_single_file(*list.list_at(i), e, root_dir
+ , &file_hash, &fee, &mtime))
+ return false;
// as long as this file already exists
// increase the counter
+ int cnt = 0;
while (!files.insert(e.path).second)
{
++cnt;
char suffix[50];
- snprintf(suffix, sizeof(suffix), ".%d%s", cnt, extension(e.path).c_str());
+ snprintf(suffix, sizeof(suffix), "%d%s", cnt, extension(e.path).c_str());
replace_extension(e.path, suffix);
}
target.add_file(e, file_hash ? file_hash->string_ptr() + info_ptr_diff : 0);
@@ -1377,7 +1610,7 @@ this check can be removed as well
instead, have one instance per possible subnet, global IPv4, global IPv6, loopback, 192.168.x.x, 10.x.x.x, etc.
instead, have one instance per possible subnet, global IPv4, global IPv6, loopback, 192.168.x.x, 10.x.x.x, etc.
include/libtorrent/ip_voter.hpp:100
bloom_filter<32> m_external_address_voters;
+
+ // is the announcer asking to ignore the explicit
+ // listen port and instead use the source port of the packet?
+ if (msg_keys[5] && msg_keys[5]->int_value() != 0)
+ port = m.addr.port();
+
instead, have one instance per possible subnet, global IPv4, global IPv6, loopback, 192.168.x.x, 10.x.x.x, etc.
instead, have one instance per possible subnet, global IPv4, global IPv6, loopback, 192.168.x.x, 10.x.x.x, etc.
../include/libtorrent/ip_voter.hpp:100
bloom_filter<32> m_external_address_voters;
std::vector<external_ip_t> m_external_addresses;
address m_external_address;
};
@@ -1455,7 +1688,7 @@ this check can be removed as well
implement blocking write. Low priority since it's not used (yet)
implement blocking write. Low priority since it's not used (yet)
../include/libtorrent/utp_stream.hpp:351
for (typename Mutable_Buffers::const_iterator i = buffers.begin()
, end(buffers.end()); i != end; ++i)
{
using asio::buffer_cast;
@@ -1506,9 +1739,9 @@ this check can be removed as well
if (m_encrypted && m_rc4_encrypted)
{
fun = encrypt;
userdata = m_enc_handler.get();
@@ -1608,8 +1841,7 @@ use allocate_disk_receive_buffer and release_disk_receive_buffer
int last_seen_complete = boost::uint8_t(root.dict_find_int_value("complete_ago", -1));
if (last_seen_complete >= 0) set_last_seen_complete(last_seen_complete);
@@ -1622,7 +1854,8 @@ use allocate_disk_receive_buffer and release_disk_receive_buffer
include
if (root.dict_find_int_value("upload_only", 0))
set_upload_only(true);
- if (root.dict_find_int_value("share_mode", 0))
+ if (m_ses.m_settings.support_share_mode
+ && root.dict_find_int_value("share_mode", 0))
set_share_mode(true);
std::string myip = root.dict_find_string_value("yourip");
@@ -1659,7 +1892,7 @@ use allocate_disk_receive_buffer and release_disk_receive_buffer
include
disconnect(errors::upload_upload_connection);
}
-
move the erasing into the loop above remove all payload ranges that has been sent
move the erasing into the loop above
+remove all payload ranges that has been sent
../src/bt_peer_connection.cpp:3317
for (std::vector<range>::iterator i = m_payloads.begin();
i != m_payloads.end(); ++i)
{
i->start -= bytes_transferred;
@@ -1746,7 +1979,7 @@ remove all payload ranges that has been sent
src/bt_peer_connection.cpp:
}
}
-#ifdef TORRENT_DEBUG
+#if defined TORRENT_DEBUG && !defined TORRENT_DISABLE_INVARIANT_CHECKS
void bt_peer_connection::check_invariant() const
{
boost::shared_ptr<torrent> t = associated_torrent().lock();
@@ -1762,7 +1995,7 @@ remove all payload ranges that has been sent
support authentication (i.e. user name and password) in the URL
support authentication (i.e. user name and password) in the URL
../src/http_tracker_connection.cpp:99
, aux::session_impl const& ses
, proxy_settings const& ps
, std::string const& auth
#if TORRENT_USE_I2P
@@ -1864,7 +2097,7 @@ remove all payload ranges that has been sent
while (new_size < size)
new_size <<= 1;
void** new_storage = (void**)malloc(sizeof(void*) * new_size);
@@ -1966,9 +2199,9 @@ remove all payload ranges that has been sent
// this piece index later
m_allowed_fast.push_back(index);
// if the peer has the piece and we want
@@ -2070,7 +2303,7 @@ we can construct a full bitfield
std::fill(m_recv_buffer.begin() + m_recv_pos, m_recv_buffer.end(), 0);
#endif
m_packet_size = packet_size;
@@ -2121,8 +2354,8 @@ we can construct a full bitfield
peers should really be corked/uncorked outside of all completed disk operations
peers should really be corked/uncorked outside of
+all completed disk operations
../src/peer_connection.cpp:4509
// this means we're in seed mode and we haven't yet
// verified this piece (r.piece)
t->filesystem().async_read_and_hash(r, boost::bind(&peer_connection::on_disk_read_complete
, self(), _1, _2, r), cache.second);
@@ -2173,8 +2406,8 @@ all completed disk operations
recalculate all connect candidates for all torrents
recalculate all connect candidates for all torrents
../src/session_impl.cpp:1898
m_upload_rate.close();
// #error closing the udp socket here means that
// the uTP connections cannot be closed gracefully
@@ -2327,7 +2560,58 @@ override at a time
have 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:3252
// --------------------------------------------------------------
+ if (!m_paused) m_auto_manage_time_scaler--;
+ if (m_auto_manage_time_scaler < 0)
+ {
+ m_auto_manage_time_scaler = settings().auto_manage_interval;
+ recalculate_auto_managed_torrents();
+ }
+
+ // --------------------------------------------------------------
+ // check for incoming connections that might have timed out
+ // --------------------------------------------------------------
+
+ for (connection_map::iterator i = m_connections.begin();
+ i != m_connections.end();)
+ {
+ peer_connection* p = (*i).get();
+ ++i;
+ // ignore connections that already have a torrent, since they
+ // are ticked through the torrents' second_tick
+ if (!p->associated_torrent().expired()) continue;
+
if (m_last_tick - p->connected_time() > seconds(m_settings.handshake_timeout))
+
p->disconnect(errors::timed_out);
+ }
+
+ // --------------------------------------------------------------
+ // second_tick every torrent
+ // --------------------------------------------------------------
+
+ int congested_torrents = 0;
+ int uncongested_torrents = 0;
+
+ // count the number of seeding torrents vs. downloading
+ // torrents we are running
+ int num_seeds = 0;
+ int num_downloads = 0;
+
+ // count the number of peers of downloading torrents
+ int num_downloads_peers = 0;
+
+ torrent_map::iterator least_recently_scraped = m_torrents.end();
+ int num_paused_auto_managed = 0;
+
+ int num_checking = 0;
+ int num_queued = 0;
+ for (torrent_map::iterator i = m_torrents.begin();
+ i != m_torrents.end();)
+ {
+ torrent& t = *i->second;
+ TORRENT_ASSERT(!t.is_aborted());
+ if (t.statistics().upload_rate() * 11 / 10 > t.upload_limit())
+ ++congested_torrents;
+
make this more generic to not just work if files have been renamed, but also if they have been merged into a single file for instance maybe use the same format as .torrent files and reuse some code from torrent_info
make this more generic to not just work if files have been
+
make this more generic to not just work if files have been renamed, but also if they have been merged into a single file for instance maybe use the same format as .torrent files and reuse some code from torrent_info
make this more generic to not just work if files have been
renamed, but also if they have been merged into a single file for instance
-maybe use the same format as .torrent files and reuse some code from torrent_info
src/storage.cpp:623
for (file_iter = files().begin();;)
+maybe use the same format as .torrent files and reuse some code from torrent_info
../src/storage.cpp:638
for (file_iter = files().begin();;)
{
if (file_offset < file_iter->size)
break;
@@ -2721,9 +3005,9 @@ maybe use the same format as .torrent files and reuse some code from torrent_inf
for (int i = 0; i < file_sizes_ent->list_size(); ++i)
{
-
what if file_base is used to merge several virtual files into a single physical file? We should probably disable this if file_base is used. This is not a widely used feature though
what if file_base is used to merge several virtual files
+
what if file_base is used to merge several virtual files into a single physical file? We should probably disable this if file_base is used. This is not a widely used feature though
what if file_base is used to merge several virtual files
into a single physical file? We should probably disable this
-if file_base is used. This is not a widely used feature though
src/storage.cpp:1192
int bytes_transferred = 0;
+if file_base is used. This is not a widely used feature though
../src/storage.cpp:1252
int bytes_transferred = 0;
// if the file is opened in no_buffer mode, and the
// read is unaligned, we need to fall back on a slow
// special read that reads aligned buffers and copies
@@ -2735,7 +3019,7 @@ if file_base is used. This is not a widely used feature though
src/stora
{
bytes_transferred = (int)(this->*op.unaligned_op)(file_handle, adjusted_offset
, tmp_bufs, num_tmp_bufs, ec);
- if (op.mode == file::read_write
+ if ((op.mode & file::rw_mask) == file::read_write
&& adjusted_offset + bytes_transferred >= file_iter->size
&& (file_handle->pos_alignment() > 0 || file_handle->size_alignment() > 0))
{
@@ -2756,7 +3040,7 @@ if file_base is used. This is not a widely used feature though
src/stora
if (ec)
{
- set_error(combine_path(m_save_path, files().file_path(*file_iter)), ec);
+ set_error(files().file_path(*file_iter, m_save_path), ec);
return -1;
}
@@ -2774,12 +3058,12 @@ if file_base is used. This is not a widely used feature though
src/stora
// makes unaligned requests (and the disk cache is disabled or fully utilized
// for write cache).
-
make this more generic to not just work if files have been renamed, but also if they have been merged into a single file for instance maybe use the same format as .torrent files and reuse some code from torrent_info The mapped_files needs to be read both in the network thread and in the disk thread, since they both have their own mapped files structures which are kept in sync
make this more generic to not just work if files have been
+
make this more generic to not just work if files have been renamed, but also if they have been merged into a single file for instance maybe use the same format as .torrent files and reuse some code from torrent_info The mapped_files needs to be read both in the network thread and in the disk thread, since they both have their own mapped files structures which are kept in sync
make this more generic to not just work if files have been
renamed, but also if they have been merged into a single file for instance
maybe use the same format as .torrent files and reuse some code from torrent_info
The mapped_files needs to be read both in the network thread
and in the disk thread, since they both have their own mapped files structures
-which are kept in sync
src/torrent.cpp:5094
if (m_seed_mode) m_verified.resize(m_torrent_file->num_pieces(), false);
+which are kept in sync
../src/torrent.cpp:5144
if (m_seed_mode) m_verified.resize(m_torrent_file->num_pieces(), false);
super_seeding(rd.dict_find_int_value("super_seeding", 0));
m_last_scrape = rd.dict_find_int_value("last_scrape", 0);
@@ -2830,12 +3114,12 @@ which are kept in sync
if this is a merkle torrent and we can't restore the tree, we need to wipe all the bits in the have array, but not necessarily we might want to do a full check to see if we have all the pieces. This is low priority since almost no one uses merkle torrents
if this is a merkle torrent and we can't restore the tree, we need to wipe all the bits in the have array, but not necessarily we might want to do a full check to see if we have all the pieces. This is low priority since almost no one uses merkle torrents
if this is a merkle torrent and we can't
restore the tree, we need to wipe all the
bits in the have array, but not necessarily
we might want to do a full check to see if we have
all the pieces. This is low priority since almost
-no one uses merkle torrents
src/torrent.cpp:5230
add_web_seed(url, web_seed_entry::http_seed);
+no one uses merkle torrents
../src/torrent.cpp:5280
add_web_seed(url, web_seed_entry::http_seed);
}
}
@@ -2886,9 +3170,9 @@ no one uses merkle torrents
make this more generic to not just work if files have been renamed, but also if they have been merged into a single file for instance. using file_base
make this more generic to not just work if files have been
renamed, but also if they have been merged into a single file for instance.
-using file_base
go through the pieces we have and count the total number of downloaders we have. Only count peers that are interested in us since some peers might not send have messages for pieces we have it num_interested == 0, we need to pick a new piece
go through the pieces we have and count the total number
+
go through the pieces we have and count the total number of downloaders we have. Only count peers that are interested in us since some peers might not send have messages for pieces we have it num_interested == 0, we need to pick a new piece
go through the pieces we have and count the total number
of downloaders we have. Only count peers that are interested in us
since some peers might not send have messages for pieces we have
-it num_interested == 0, we need to pick a new piece
src/torrent.cpp:7901
}
+it num_interested == 0, we need to pick a new piece
../src/torrent.cpp:7945
}
rarest_pieces.clear();
rarest_rarity = pp.peer_count;
@@ -2993,63 +3277,9 @@ it num_interested == 0, we need to pick a new piece
src/torrent.cpp:7901
{
// we don't keep track of availability, do it the expensive way
// do a linear search from the first piece
-
if there's been long enough since we requested something from this piece, request one of the backup blocks (the one with the least number of requests to it) and update the last request timestamp
if there's been long enough since we requested something
-from this piece, request one of the backup blocks (the one with
-the least number of requests to it) and update the last request
-timestamp
it would be more efficient to not use a string here. however, the problem is that some trackers will respond with actual strings. For example i2p trackers
it would be more efficient to not use a string here.
+
it would be more efficient to not use a string here. however, the problem is that some trackers will respond with actual strings. For example i2p trackers
it would be more efficient to not use a string here.
however, the problem is that some trackers will respond
-with actual strings. For example i2p trackers
src/udp_tracker_connection.cpp:548
}
+with actual strings. For example i2p trackers
../src/udp_tracker_connection.cpp:552
}
boost::shared_ptr<request_callback> cb = requester();
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
@@ -3100,7 +3330,7 @@ with actual strings. For example i2p trackers
src/udp_tracker_connection
{
restart_read_timeout();
int action = detail::read_int32(buf);
-
std::string path;
+ size_type offset; // the offset of this file inside the torrent
+ size_type size; // the size of this file
+ // the offset in the file where the storage starts.
+ // This is always 0 unless parts of the torrent is
+ // compressed into a single file, such as a so-called part file.
+ size_type file_base;
+ std::time_t mtime;
+ sha1_hash filehash;
+ bool pad_file:1;
+ bool hidden_attribute:1;
+ bool executable_attribute:1;
+ bool symlink_attribute:1;
+ std::string symlink_path;
+ };
+
+ // this is used internally to hold the file entry
+ // it's smaller and optimized for smaller memory
+ // footprint, as opposed to file_entry, which is
+ // optimized for convenience
+
For additional information and descritptions of
+the terminology used in this document, see
+the protocol specification
+
All values are sent in network byte order (big endian). The sizes
+are specified with ANSI-C standard types.
+
If no response to a request is received within 15 seconds, resend
+the request. If no reply has been received after 60 seconds, stop
+retrying.
+
+
+
connecting
+
Client sends packet:
+
+
+
+
+
+
+
+
size
+
name
+
description
+
+
+
+
int64_t
+
connection_id
+
Must be initialized to 0x41727101980
+in network byte order. This will
+identify the protocol.
+
+
int32_t
+
action
+
0 for a connection request
+
+
int32_t
+
transaction_id
+
Randomized by client.
+
+
+
+
Server replies with packet:
+
+
+
+
+
+
+
+
size
+
name
+
description
+
+
+
+
int32_t
+
action
+
Describes the type of packet, in this
+case it should be 0, for connect.
+If 3 (for error) see errors.
+
+
int32_t
+
transaction_id
+
Must match the transaction_id sent
+from the client.
+
+
int64_t
+
connection_id
+
A connection id, this is used when
+further information is exchanged with
+the tracker, to identify you.
+This connection id can be reused for
+multiple requests, but if it's cached
+for too long, it will not be valid
+anymore.
+
+
+
+
+
+
announcing
+
Client sends packet:
+
+
+
+
+
+
+
+
size
+
name
+
description
+
+
+
+
int64_t
+
connection_id
+
The connection id acquired from
+establishing the connection.
+
+
int32_t
+
action
+
Action. in this case, 1 for announce.
+See actions.
+
+
int32_t
+
transaction_id
+
Randomized by client.
+
+
int8_t[20]
+
info_hash
+
The info-hash of the torrent you want
+announce yourself in.
+
+
int8_t[20]
+
peer_id
+
Your peer id.
+
+
int64_t
+
downloaded
+
The number of byte you've downloaded
+in this session.
+
+
int64_t
+
left
+
The number of bytes you have left to
+download until you're finished.
+
+
int64_t
+
uploaded
+
The number of bytes you have uploaded
+in this session.
+
+
int32_t
+
event
+
The event, one of
+
+
+
none = 0
+
completed = 1
+
started = 2
+
stopped = 3
+
+
+
+
+
uint32_t
+
ip
+
Your ip address. Set to 0 if you want
+the tracker to use the sender of
+this udp packet.
+
+
uint32_t
+
key
+
A unique key that is randomized by the
+client.
+
+
int32_t
+
num_want
+
The maximum number of peers you want
+in the reply. Use -1 for default.
If multiple bits are present in the extension field, the extension
+bodies are appended to the packet in the order of least significant
+bit first. For instance, if both bit 1 and 2 are set, the extension
+represented by bit 1 comes first, followed by the extension represented
+by bit 2.
+
+
authentication
+
The packet will have an authentication part
+appended to it. It has the following format:
+
+
+
+
+
+
+
+
size
+
name
+
description
+
+
+
+
int8_t
+
username_length
+
The number of characters in the
+username.
+
+
int8_t[]
+
username
+
The username, the number of characters
+as specified in the previous field.
+
+
uint8_t[8]
+
passwd_hash
+
sha1(packet + sha1(password))
+The packet in this case means the
+entire packet except these 8 bytes
+that are the password hash. These are
+the 8 first bytes (most significant)
+from the 20 bytes hash calculated.
+
+
+
+
+
+
+
request string
+
The request string extension is meant to allow torrent creators pass along
+cookies back to the tracker. This can be useful for authenticating that a
+torrent is allowed to be tracked by a tracker for instance. It could also
+be used to authenticate users by generating torrents with unique tokens
+in the tracker URL for each user. The extension body has the following format:
+
+
+
+
+
+
+
+
size
+
name
+
description
+
+
+
+
int8_t
+
request length
+
The number of bytes in the request
+string.
+
+
int8_t[]
+
request string
+
The string that comes after the host-
+name and port in the udp tracker URL.
+Typically this starts with "/announce"
+The bittorrent client is not expected
+to append query string arguments for
+stats reporting, like "uploaded" and
+"downloaded" since this is already
+reported in the udp tracker protocol.
+However, the client is free to add
+arguments as extensions.
+
+
+
+
+
+
credits
+
Protocol designed by Olaf van der Spek and extended by Arvid Norberg