<tablewidth="100%"border="1"style="border-collapse: collapse;"><trstyle="background: #f44"><td>relevance 4</td><td><ahref="javascript:expand(0)">../src/session_impl.cpp:480</a></td><td>in order to support SSL over uTP, the utp_socket manager either needs to be able to receive packets on multiple ports, or we need to peek into the first few bytes the payload stream of a socket to determine whether or not it's an SSL connection. (The former is simpler but won't do as well with NATs)</td></tr><trid="0"style="display: none;"colspan="3"><tdcolspan="3"><h2>in order to support SSL over uTP, the utp_socket manager either
needs to be able to receive packets on multiple ports, or we need to
peek into the first few bytes the payload stream of a socket to determine
whether or not it's an SSL connection. (The former is simpler but won't
do as well with NATs)</h2><h4>../src/session_impl.cpp:480</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> , m_optimistic_unchoke_time_scaler(0)
</pre></td></tr><trstyle="background: #f44"><td>relevance 4</td><td><ahref="javascript:expand(1)">../src/kademlia/refresh.cpp:93</a></td><td>when bootstrapping against our own IP completes, continue to issue another bootstrap against the deepest, non-full bucket. when it completes, issue a bootstrap against one bucket above it, and so on until the bootstrap lookup against the top level bucket (bucket 0) completes. That's when the bootstrap is done</td></tr><trid="1"style="display: none;"colspan="3"><tdcolspan="3"><h2>when bootstrapping against our own IP completes,
continue to issue another bootstrap against the deepest,
non-full bucket. when it completes, issue a bootstrap against
one bucket above it, and so on until the bootstrap lookup
against the top level bucket (bucket 0) completes. That's
when the bootstrap is done</h2><h4>../src/kademlia/refresh.cpp:93</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> e["y"] = "q";
for (std::vector<observer_ptr>::iterator i = m_results.begin()
, end(m_results.end()); i != end; ++i)
{
if ((*i)->flags & observer::flag_queried) continue;
// this will send a ping
m_node.add_node((*i)->target_ep());
}
refresh::done();
}
} } // namespace libtorrent::dht
</pre></td></tr><trstyle="background: #fcc"><td>relevance 3</td><td><ahref="javascript:expand(2)">../src/disk_io_thread.cpp:242</a></td><td>it would be nice to have the number of threads be set dynamically</td></tr><trid="2"style="display: none;"colspan="3"><tdcolspan="3"><h2>it would be nice to have the number of threads be set dynamically</h2><h4>../src/disk_io_thread.cpp:242</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> std::pair<block_cache::iterator, block_cache::iterator> pieces
= m_disk_cache.all_pieces();
TORRENT_ASSERT(pieces.first == pieces.second);
#endif
#ifdef TORRENT_DISK_STATS
if (g_access_log)
{
FILE* f = g_access_log;
g_access_log = NULL;
fclose(f);
}
#endif
TORRENT_ASSERT(m_magic == 0x1337);
#if TORRENT_USE_ASSERTS
m_magic = 0xdead;
#endif
}
<divstyle="background: #ffff00"width="100%"> void disk_io_thread::set_num_threads(int i, bool wait)
</div> {
TORRENT_ASSERT(m_magic == 0x1337);
if (i == m_num_threads) return;
if (i > m_num_threads)
{
while (m_num_threads < i)
{
int thread_id = (++m_num_threads) - 1;
thread_type_t type = generic_thread;
// the magic number 3 is also used in add_job()
// every 4:th thread is a hasher thread
if ((thread_id & 0x3) == 3) type = hasher_thread;
</pre></td></tr><trstyle="background: #fcc"><td>relevance 3</td><td><ahref="javascript:expand(3)">../src/peer_connection.cpp:1719</a></td><td>we should probably use ses.m_allowed_upload_slots here instead to work with auto-unchoke logic</td></tr><trid="3"style="display: none;"colspan="3"><tdcolspan="3"><h2>we should probably use ses.m_allowed_upload_slots here instead
to work with auto-unchoke logic</h2><h4>../src/peer_connection.cpp:1719</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;">
</pre></td></tr><trstyle="background: #fcc"><td>relevance 3</td><td><ahref="javascript:expand(4)">../src/peer_connection.cpp:3049</a></td><td>since we throw away the queue entry once we issue the disk job, this may happen. Instead, we should keep the queue entry around, 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 to cancel disk jobs?</td></tr><trid="4"style="display: none;"colspan="3"><tdcolspan="3"><h2>since we throw away the queue entry once we issue
been cancelled. Maybe even be able to cancel disk jobs?</h2><h4>../src/peer_connection.cpp:3049</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;">
</pre></td></tr><trstyle="background: #fcc"><td>relevance 3</td><td><ahref="javascript:expand(5)">../src/peer_connection.cpp:4746</a></td><td>instead of using settings_pack::request_timeout, use m_rtt.mean() + m_rtt.avg_deviation() * 2 or something like that. the configuration option could hopefully be removed</td></tr><trid="5"style="display: none;"colspan="3"><tdcolspan="3"><h2>instead of using settings_pack::request_timeout, use
the configuration option could hopefully be removed</h2><h4>../src/peer_connection.cpp:4746</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> // don't bother disconnect peers we haven't been interested
if (as_stats && as_stats->second < m_download_rate_peak)
as_stats->second = m_download_rate_peak;
}
#endif
}
if (is_disconnecting()) return;
</pre></td></tr><trstyle="background: #fcc"><td>relevance 3</td><td><ahref="javascript:expand(6)">../src/piece_picker.cpp:3166</a></td><td>it would be nice if this could be folded into lock_piece() the main distinction is that this also maintains the m_num_passed counter and the passed_hash_check member</td></tr><trid="6"style="display: none;"colspan="3"><tdcolspan="3"><h2>it would be nice if this could be folded into lock_piece()
the main distinction is that this also maintains the m_num_passed
counter and the passed_hash_check member</h2><h4>../src/piece_picker.cpp:3166</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> int state = m_piece_map[piece].state;
if (state == piece_pos::piece_open) return;
std::vector<downloading_piece>::iterator i = find_dl_piece(state - 1, piece);
if (i == m_downloads[state - 1].end()) return;
TORRENT_ASSERT(i->passed_hash_check == false);
if (i->passed_hash_check)
{
// it's not clear why this would happen,
// but it seems reasonable to not break the
// accounting over it.
i->passed_hash_check = false;
TORRENT_ASSERT(m_num_passed > 0);
--m_num_passed;
}
// prevent this piece from being picked until it's restored
if (info.state == block_info::state_finished) return;
if (info.state == block_info::state_writing) --i->writing;
info.peer = 0;
</pre></td></tr><trstyle="background: #fcc"><td>relevance 3</td><td><ahref="javascript:expand(7)">../src/resolver.cpp:39</a></td><td>the first places to use this resolver is the http_connection/http_tracker_connection and udp_tracker_connection. make sure to prefer cache on shutdown</td></tr><trid="7"style="display: none;"colspan="3"><tdcolspan="3"><h2>the first places to use this resolver is the
http_connection/http_tracker_connection and udp_tracker_connection.
make sure to prefer cache on shutdown</h2><h4>../src/resolver.cpp:39</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;">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
</pre></td></tr><trstyle="background: #fcc"><td>relevance 3</td><td><ahref="javascript:expand(8)">../src/session_impl.cpp:5697</a></td><td>it would be really nice to update these counters as they are incremented. This depends on the session being ticked, which has a fairly coarse grained resolution</td></tr><trid="8"style="display: none;"colspan="3"><tdcolspan="3"><h2>it would be really nice to update these counters
being ticked, which has a fairly coarse grained resolution</h2><h4>../src/session_impl.cpp:5697</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> t->status(&alert->status.back(), ~torrent_handle::query_accurate_download_counters);
</pre></td></tr><trstyle="background: #fcc"><td>relevance 3</td><td><ahref="javascript:expand(9)">../src/session_impl.cpp:7156</a></td><td>If socket jobs could be higher level, to include RC4 encryption and decryption, we would offload the main thread even more</td></tr><trid="9"style="display: none;"colspan="3"><tdcolspan="3"><h2>If socket jobs could be higher level, to include RC4 encryption and decryption,
we would offload the main thread even more</h2><h4>../src/session_impl.cpp:7156</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> {
for (connection_map::iterator i = m_connections.begin()
, end(m_connections.end()); i != end; ++i)
{
int type = (*i)->type();
</pre></td></tr><trstyle="background: #fcc"><td>relevance 3</td><td><ahref="javascript:expand(10)">../src/torrent.cpp:1081</a></td><td>if any other peer has a busy request to this block, we need to cancel it too</td></tr><trid="10"style="display: none;"colspan="3"><tdcolspan="3"><h2>if any other peer has a busy request to this block, we need to cancel it too</h2><h4>../src/torrent.cpp:1081</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;">#endif
if (c) c->disconnect(errors::no_memory, peer_connection_interface::op_file);
</pre></td></tr><trstyle="background: #fcc"><td>relevance 3</td><td><ahref="javascript:expand(11)">../src/torrent.cpp:7600</a></td><td>if peer is a really good peer, maybe we shouldn't disconnect it</td></tr><trid="11"style="display: none;"colspan="3"><tdcolspan="3"><h2>if peer is a really good peer, maybe we shouldn't disconnect it</h2><h4>../src/torrent.cpp:7600</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;">#if defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
// we have to do this here because from the peer's point of
// it wasn't really attached to the torrent, but we do need
// to let policy know we're removing it
remove_peer(p);
return false;
}
}
#if TORRENT_USE_INVARIANT_CHECKS
if (m_policy) m_policy->check_invariant();
#endif
if (m_share_mode)
recalc_share_mode();
return true;
}
bool torrent::want_tick() const
{
if (m_abort) return false;
if (!m_connections.empty()) return true;
</pre></td></tr><trstyle="background: #fcc"><td>relevance 3</td><td><ahref="javascript:expand(12)">../src/web_peer_connection.cpp:586</a></td><td>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 following</td></tr><trid="12"style="display: none;"colspan="3"><tdcolspan="3"><h2>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 following</h2><h4>../src/web_peer_connection.cpp:586</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> {
</pre></td></tr><trstyle="background: #fcc"><td>relevance 3</td><td><ahref="javascript:expand(13)">../include/libtorrent/block_cache.hpp:212</a></td><td>could this be a scoped_array instead? does cached_piece_entry really need to be copyable? cached_piece_entry does need to be copyable since it's part of a container, but it's possible it could be a raw pointer or boost::unique_ptr perhaps</td></tr><trid="13"style="display: none;"colspan="3"><tdcolspan="3"><h2>could this be a scoped_array instead? does cached_piece_entry really need to be copyable?
cached_piece_entry does need to be copyable since it's part of a container, but it's possible
it could be a raw pointer or boost::unique_ptr perhaps</h2><h4>../include/libtorrent/block_cache.hpp:212</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> // on this piece to complete. These are executed at that point.
// the last time a block was written to this piece
// plus the minimum amount of time the block is guaranteed
// to stay in the cache
</pre></td></tr><trstyle="background: #fcc"><td>relevance 3</td><td><ahref="javascript:expand(14)">../include/libtorrent/disk_io_thread.hpp:537</a></td><td>turn these counters and gauges into session_stats counters (which also would need to be thread safe)</td></tr><trid="14"style="display: none;"colspan="3"><tdcolspan="3"><h2>turn these counters and gauges into session_stats
counters (which also would need to be thread safe)</h2><h4>../include/libtorrent/disk_io_thread.hpp:537</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> void* m_userdata;
// the last time we expired write blocks from the cache
// average read time for cache misses (in microseconds)
average_accumulator m_read_time;
// average write time (in microseconds)
average_accumulator m_write_time;
// average hash time (in microseconds)
average_accumulator m_hash_time;
// average time to serve a job (any job) in microseconds
average_accumulator m_job_time;
// the total number of outstanding jobs. This is used to
// limit the number of jobs issued in parallel. It also creates
// an opportunity to sort the jobs by physical offset before
// issued to the AIO subsystem
boost::atomic<int> m_outstanding_jobs;
// this is the main thread io_service. Callbacks are
// posted on this in order to have them execute in
// the main thread.
io_service& m_ios;
// the number of jobs that have been blocked by a fence. These
// jobs are queued up in their respective storage, waiting for
// the fence to be lowered. This counter is just used to know
// when it's OK to exit the main loop of the disk thread
boost::atomic<int> m_num_blocked_jobs;
</pre></td></tr><trstyle="background: #fcc"><td>relevance 3</td><td><ahref="javascript:expand(15)">../include/libtorrent/policy.hpp:104</a></td><td>this class should be renamed peer_list</td></tr><trid="15"style="display: none;"colspan="3"><tdcolspan="3"><h2>this class should be renamed peer_list</h2><h4>../include/libtorrent/policy.hpp:104</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> int min_reconnect_time;
// the number of iterations over the peer list for this operation
int loop_counter;
// these are used only by find_connect_candidates in order
bool update_peer_port(int port, torrent_peer* p, int src, torrent_state* state);
// called when an incoming connection is accepted
// false means the connection was refused or failed
</pre></td></tr><trstyle="background: #fcc"><td>relevance 3</td><td><ahref="javascript:expand(16)">../include/libtorrent/session.hpp:210</a></td><td>could the fingerprint be a setting as well? And should the settings_pack be optional?</td></tr><trid="16"style="display: none;"colspan="3"><tdcolspan="3"><h2>could the fingerprint be a setting as well? And should the
settings_pack be optional?</h2><h4>../include/libtorrent/session.hpp:210</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> //
// see apply_settings().
class TORRENT_EXPORT session: public boost::noncopyable
{
public:
// If the fingerprint in the first overload is omited, the client will
// get a default fingerprint stating the version of libtorrent. The
// fingerprint is a short string that will be used in the peer-id to
// identify the client and the client's version. For more details see the
// fingerprint class.
//
// The flags paramater can be used to start default features (upnp &
// nat-pmp) and default plugins (ut_metadata, ut_pex and smart_ban). The
// default is to start those features. If you do not want them to start,
// pass 0 as the flags parameter.
//
// The ``alert_mask`` is the same mask that you would send to
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
set_log_path(logpath);
#endif
start(flags, pack);
</pre></td></tr><trstyle="background: #cfc"><td>relevance 2</td><td><ahref="javascript:expand(17)">../src/disk_io_thread.cpp:844</a></td><td>should this be allocated on the stack?</td></tr><trid="17"style="display: none;"colspan="3"><tdcolspan="3"><h2>should this be allocated on the stack?</h2><h4>../src/disk_io_thread.cpp:844</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> // if we're also flushing the read cache, this piece
// should be removed as soon as all write jobs finishes
// otherwise it will turn into a read piece
}
// mark_for_deletion may erase the piece from the cache, that's
// why we don't have the 'i' iterator referencing it at this point
if (flags & (flush_read_cache | flush_delete_cache))
for (boost::unordered_set<cached_piece_entry*>::const_iterator i = storage_pieces.begin()
, end(storage_pieces.end()); i != end; ++i)
{
cached_piece_entry* pe = m_disk_cache.find_piece(storage, (*i)->piece);
TORRENT_PIECE_ASSERT(pe->num_dirty == 0, pe);
</pre></td></tr><trstyle="background: #cfc"><td>relevance 2</td><td><ahref="javascript:expand(18)">../src/disk_io_thread.cpp:885</a></td><td>we're not flushing the read cache at all?</td></tr><trid="18"style="display: none;"colspan="3"><tdcolspan="3"><h2>we're not flushing the read cache at all?</h2><h4>../src/disk_io_thread.cpp:885</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> // from disk_io_thread::do_delete, which is a fence job and should
// have any other jobs active, i.e. there should not be any references
// keeping pieces or blocks alive
if ((flags & flush_delete_cache) && (flags & flush_expect_clear))
</pre></td></tr><trstyle="background: #cfc"><td>relevance 2</td><td><ahref="javascript:expand(19)">../src/file.cpp:1491</a></td><td>use vm_copy here, if available, and if buffers are aligned</td></tr><trid="19"style="display: none;"colspan="3"><tdcolspan="3"><h2>use vm_copy here, if available, and if buffers are aligned</h2><h4>../src/file.cpp:1491</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> CloseHandle(native_handle());
m_path.clear();
#else
if (m_file_handle != INVALID_HANDLE_VALUE)
::close(m_file_handle);
#endif
m_file_handle = INVALID_HANDLE_VALUE;
m_open_mode = 0;
}
// defined in storage.cpp
int bufs_size(file::iovec_t const* bufs, int num_bufs);
void gather_copy(file::iovec_t const* bufs, int num_bufs, char* dst)
void scatter_copy(file::iovec_t const* bufs, int num_bufs, char const* src)
{
int offset = 0;
for (int i = 0; i < num_bufs; ++i)
{
</pre></td></tr><trstyle="background: #cfc"><td>relevance 2</td><td><ahref="javascript:expand(20)">../src/file.cpp:1502</a></td><td>use vm_copy here, if available, and if buffers are aligned</td></tr><trid="20"style="display: none;"colspan="3"><tdcolspan="3"><h2>use vm_copy here, if available, and if buffers are aligned</h2><h4>../src/file.cpp:1502</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> }
// defined in storage.cpp
int bufs_size(file::iovec_t const* bufs, int num_bufs);
void gather_copy(file::iovec_t const* bufs, int num_bufs, char* dst)
</pre></td></tr><trstyle="background: #cfc"><td>relevance 2</td><td><ahref="javascript:expand(22)">../src/session_impl.cpp:4596</a></td><td>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 want to announce</td></tr><trid="22"style="display: none;"colspan="3"><tdcolspan="3"><h2>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 want to announce</h2><h4>../src/session_impl.cpp:4596</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> if (!m_dht_torrents.empty())
</pre></td></tr><trstyle="background: #cfc"><td>relevance 2</td><td><ahref="javascript:expand(24)">../src/torrent.cpp:4646</a></td><td>abort lookups this torrent has made via the session host resolver interface</td></tr><trid="24"style="display: none;"colspan="3"><tdcolspan="3"><h2>abort lookups this torrent has made via the
session host resolver interface</h2><h4>../src/torrent.cpp:4646</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> // files belonging to the torrents
for (int i = 0; i < aux::session_interface::num_torrent_lists; ++i)
{
if (!m_links[i].in_list()) continue;
m_links[i].unlink(m_ses.torrent_list(i), i);
}
// don't re-add this torrent to the state-update list
m_state_subscription = false;
}
void torrent::super_seeding(bool on)
{
if (on == m_super_seeding) return;
m_super_seeding = on;
m_need_save_resume_data = true;
if (m_super_seeding) return;
// disable super seeding for all peers
for (peer_iterator i = begin(); i != end(); ++i)
{
(*i)->superseed_piece(-1, -1);
</pre></td></tr><trstyle="background: #cfc"><td>relevance 2</td><td><ahref="javascript:expand(25)">../src/udp_tracker_connection.cpp:64</a></td><td>it would be nice to not have a dependency on session_impl here</td></tr><trid="25"style="display: none;"colspan="3"><tdcolspan="3"><h2>it would be nice to not have a dependency on session_impl here</h2><h4>../src/udp_tracker_connection.cpp:64</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;">#pragma warning(pop)
#endif
#include "libtorrent/tracker_manager.hpp"
#include "libtorrent/parse_url.hpp"
#include "libtorrent/udp_tracker_connection.hpp"
#include "libtorrent/io.hpp"
#include "libtorrent/aux_/session_impl.hpp"
#include "libtorrent/escape_string.hpp"
#include "libtorrent/broadcast_socket.hpp" // for is_any
if (port == -1) port = protocol == "http" ? 80 : 443;
if (ec)
</pre></td></tr><trstyle="background: #cfc"><td>relevance 2</td><td><ahref="javascript:expand(26)">../src/web_peer_connection.cpp:645</a></td><td>create a mapping of file-index to redirection URLs. Use that to form URLs instead. Support to reconnect to a new server without destructing this peer_connection</td></tr><trid="26"style="display: none;"colspan="3"><tdcolspan="3"><h2>create a mapping of file-index to redirection URLs. Use that to form
URLs instead. Support to reconnect to a new server without destructing this
</pre></td></tr><trstyle="background: #cfc"><td>relevance 2</td><td><ahref="javascript:expand(27)">../src/kademlia/node.cpp:67</a></td><td>make this configurable in dht_settings</td></tr><trid="27"style="display: none;"colspan="3"><tdcolspan="3"><h2>make this configurable in dht_settings</h2><h4>../src/kademlia/node.cpp:67</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;">#include "libtorrent/kademlia/routing_table.hpp"
#include "libtorrent/kademlia/node.hpp"
#include "libtorrent/kademlia/dht_observer.hpp"
#include "libtorrent/kademlia/refresh.hpp"
#include "libtorrent/kademlia/get_peers.hpp"
#include "libtorrent/kademlia/get_item.hpp"
#include "libtorrent/performance_counters.hpp" // for counters
#ifdef TORRENT_USE_VALGRIND
#include <valgrind/memcheck.h>
#endif
namespace libtorrent { namespace dht
{
void incoming_error(entry& e, char const* msg, int error_code = 203);
</pre></td></tr><trstyle="background: #cfc"><td>relevance 2</td><td><ahref="javascript:expand(28)">../src/kademlia/node_id.cpp:133</a></td><td>this could be optimized if SSE 4.2 is available. It could also be optimized given that we have a fixed length</td></tr><trid="28"style="display: none;"colspan="3"><tdcolspan="3"><h2>this could be optimized if SSE 4.2 is
that we have a fixed length</h2><h4>../src/kademlia/node_id.cpp:133</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> b6 = ip_.to_v6().to_bytes();
// no need to verify local IPs, they would be incorrect anyway
if (is_local(source_ip)) return true;
node_id h = generate_id_impl(source_ip, nid[19]);
</pre></td></tr><trstyle="background: #cfc"><td>relevance 2</td><td><ahref="javascript:expand(29)">../include/libtorrent/enum_net.hpp:137</a></td><td>this could be done more efficiently by just looking up the interface with the given name, maybe even with if_nametoindex()</td></tr><trid="29"style="display: none;"colspan="3"><tdcolspan="3"><h2>this could be done more efficiently by just looking up
the interface with the given name, maybe even with if_nametoindex()</h2><h4>../include/libtorrent/enum_net.hpp:137</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;">
address ip = address::from_string(device_name, ec);
if (!ec)
{
bind_ep.address(ip);
// it appears to be an IP. Just bind to that address
sock.bind(bind_ep, ec);
return bind_ep.address();
}
ec.clear();
#ifdef SO_BINDTODEVICE
// try to use SO_BINDTODEVICE here, if that exists. If it fails,
</pre></td></tr><trstyle="background: #cfc"><td>relevance 2</td><td><ahref="javascript:expand(30)">../include/libtorrent/intrusive_ptr_base.hpp:44</a></td><td>remove this class and transition over to using shared_ptr and make_shared instead</td></tr><trid="30"style="display: none;"colspan="3"><tdcolspan="3"><h2>remove this class and transition over to using shared_ptr and
make_shared instead</h2><h4>../include/libtorrent/intrusive_ptr_base.hpp:44</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;">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
</pre></td></tr><trstyle="background: #cfc"><td>relevance 2</td><td><ahref="javascript:expand(31)">../include/libtorrent/settings_pack.hpp:70</a></td><td>add an API to query a settings_pack as well</td></tr><trid="31"style="display: none;"colspan="3"><tdcolspan="3"><h2>add an API to query a settings_pack as well</h2><h4>../include/libtorrent/settings_pack.hpp:70</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"></pre></td></tr><trstyle="background: #cfc"><td>relevance 2</td><td><ahref="javascript:expand(32)">../include/libtorrent/settings_pack.hpp:71</a></td><td>maybe convert all bool types into int-types as well</td></tr><trid="32"style="display: none;"colspan="3"><tdcolspan="3"><h2>maybe convert all bool types into int-types as well</h2><h4>../include/libtorrent/settings_pack.hpp:71</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;">{
namespace aux { struct session_impl; struct session_settings; }
// setting names (indices) are 16 bits. The two most significant
// bits indicate what type the setting has. (string, int, bool)
enum type_bases
{
string_type_base = 0x0000,
int_type_base = 0x4000,
</pre></td></tr><trstyle="background: #cfc"><td>relevance 2</td><td><ahref="javascript:expand(33)">../include/libtorrent/torrent.hpp:1184</a></td><td>replace all usage of this with m_ses.get_resolver()</td></tr><trid="33"style="display: none;"colspan="3"><tdcolspan="3"><h2>replace all usage of this with m_ses.get_resolver()</h2><h4>../include/libtorrent/torrent.hpp:1184</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;">
// this vector is allocated lazily. If no file priorities are
// ever changed, this remains empty. Any unallocated slot
// implicitly means the file has priority 1.
</pre></td></tr><trstyle="background: #cfc"><td>relevance 2</td><td><ahref="javascript:expand(34)">../include/libtorrent/torrent_info.hpp:303</a></td><td>there may be some opportunities to optimize the size if torrent_info. specifically to turn some std::string and std::vector into pointers</td></tr><trid="34"style="display: none;"colspan="3"><tdcolspan="3"><h2>there may be some opportunities to optimize the size if torrent_info.
specifically to turn some std::string and std::vector into pointers</h2><h4>../include/libtorrent/torrent_info.hpp:303</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> bool resolving;
// 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;
// if the web server doesn't support keepalive or a block request was
// interrupted, the block received so far is kept here for the next
<divstyle="background: #ffff00"width="100%"> class TORRENT_EXPORT torrent_info
</div> {
public:
// The constructor that takes an info-hash will initialize the info-hash to the given value,
// but leave all other fields empty. 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 constructor that takes a lazy_entry will create a torrent_info object from the
// information found in the given torrent_file. The lazy_entry represents a tree node in
// an bencoded file. To load an ordinary .torrent file
// into a lazy_entry, use lazy_bdecode().
//
// The version that takes a buffer pointer and a size will decode it as a .torrent file and
// initialize the torrent_info object for you.
//
// The version that takes a filename will simply load the torrent file and decode it inside
// the constructor, for convenience. This might not be the most suitable for applications that
// want to be able to report detailed errors on what might go wrong.
//
// The overloads that takes an ``error_code const&`` never throws if an error occur, they
// will simply set the error code to describe what went wrong and not fully initialize the
// torrent_info object. The overloads that do not take the extra error_code parameter will
// always throw if an error occurs. These overloads are not available when building without
// exception support.
//
// The ``flags`` argument is currently unused.
#ifndef BOOST_NO_EXCEPTIONS
torrent_info(lazy_entry const& torrent_file, int flags = 0);
torrent_info(char const* buffer, int size, int flags = 0);
</pre></td></tr><trstyle="background: #cfc"><td>relevance 2</td><td><ahref="javascript:expand(35)">../include/libtorrent/aux_/session_interface.hpp:108</a></td><td>the IP voting mechanism should be factored out to its own class, not part of the session</td></tr><trid="35"style="display: none;"colspan="3"><tdcolspan="3"><h2>the IP voting mechanism should be factored out
to its own class, not part of the session</h2><h4>../include/libtorrent/aux_/session_interface.hpp:108</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> class port_filter;
struct settings_pack;
struct torrent_peer_allocator_interface;
struct counters;
struct resolver_interface;
#ifndef TORRENT_DISABLE_DHT
namespace dht
{
struct dht_tracker;
}
#endif
}
namespace libtorrent { namespace aux
{
// TOOD: make this interface a lot smaller
struct session_interface
: buffer_allocator_interface
{
<divstyle="background: #ffff00"width="100%"> enum
</div> {
source_dht = 1,
source_peer = 2,
source_tracker = 4,
source_router = 8
};
virtual void set_external_address(address const& ip
, int source_type, address const& source) = 0;
virtual void remove_torrent_impl(boost::shared_ptr<torrent> tptr, int options) = 0;
// ip and port filter
</pre></td></tr><trstyle="background: #ccf"><td>relevance 1</td><td><ahref="javascript:expand(36)">../src/http_seed_connection.cpp:111</a></td><td>in chunked encoding mode, this assert won't hold. the chunk headers should be subtracted from the receive_buffer_size</td></tr><trid="36"style="display: none;"colspan="3"><tdcolspan="3"><h2>in chunked encoding mode, this assert won't hold.
the chunk headers should be subtracted from the receive_buffer_size</h2><h4>../src/http_seed_connection.cpp:111</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> boost::optional<piece_block_progress>
</pre></td></tr><trstyle="background: #ccf"><td>relevance 1</td><td><ahref="javascript:expand(37)">../src/session_impl.cpp:6508</a></td><td>report the proper address of the router as the source IP of this understanding of our external address, instead of the empty address</td></tr><trid="37"style="display: none;"colspan="3"><tdcolspan="3"><h2>report the proper address of the router as the source IP of
this understanding of our external address, instead of the empty address</h2><h4>../src/session_impl.cpp:6508</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> void session_impl::on_port_mapping(int mapping, address const& ip, int port
</pre></td></tr><trstyle="background: #ccf"><td>relevance 1</td><td><ahref="javascript:expand(38)">../src/session_impl.cpp:7668</a></td><td>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</td></tr><trid="38"style="display: none;"colspan="3"><tdcolspan="3"><h2>we only need to do this if our global IPv4 address has changed
is kind of expensive, it would be nice to not do it unnecessarily</h2><h4>../src/session_impl.cpp:7668</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;">#endif
</pre></td></tr><trstyle="background: #ccf"><td>relevance 1</td><td><ahref="javascript:expand(39)">../src/torrent.cpp:1140</a></td><td>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</td></tr><trid="39"style="display: none;"colspan="3"><tdcolspan="3"><h2>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</h2><h4>../src/torrent.cpp:1140</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> alerts().post_alert(file_error_alert(j->error.ec
</pre></td></tr><trstyle="background: #ccf"><td>relevance 1</td><td><ahref="javascript:expand(40)">../src/torrent.cpp:6780</a></td><td>save the send_stats state instead of throwing them away it may pose an issue when downgrading though</td></tr><trid="40"style="display: none;"colspan="3"><tdcolspan="3"><h2>save the send_stats state instead of throwing them away
it may pose an issue when downgrading though</h2><h4>../src/torrent.cpp:6780</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> for (int k = 0; k < bits; ++k)
v |= (i->info[j*8+k].state == piece_picker::block_info::state_finished)
</pre></td></tr><trstyle="background: #ccf"><td>relevance 1</td><td><ahref="javascript:expand(41)">../src/torrent.cpp:7846</a></td><td>should disconnect all peers that have the pieces we have not just seeds. It would be pretty expensive to check all pieces for all peers though</td></tr><trid="41"style="display: none;"colspan="3"><tdcolspan="3"><h2>should disconnect all peers that have the pieces we have
// this torrent just completed downloads, which means it will fall
</pre></td></tr><trstyle="background: #ccf"><td>relevance 1</td><td><ahref="javascript:expand(42)">../src/kademlia/node.cpp:827</a></td><td>find_node should write directly to the response entry</td></tr><trid="42"style="display: none;"colspan="3"><tdcolspan="3"><h2>find_node should write directly to the response entry</h2><h4>../src/kademlia/node.cpp:827</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> TORRENT_LOG(node) << " values: " << reply["values"].list().size();
}
#endif
}
else if (strcmp(query, "find_node") == 0)
{
key_desc_t msg_desc[] = {
{"target", lazy_entry::string_t, 20, 0},
};
lazy_entry const* msg_keys[1];
if (!verify_message(arg_ent, msg_desc, msg_keys, 1, error_string, sizeof(error_string)))
if (!verify_message(arg_ent, msg_desc, msg_keys, 6, error_string, sizeof(error_string)))
{
#ifdef TORRENT_DHT_VERBOSE_LOGGING
++g_failed_announces;
#endif
incoming_error(e, error_string);
return;
}
int port = int(msg_keys[1]->int_value());
// 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();
</pre></td></tr><trstyle="background: #ccf"><td>relevance 1</td><td><ahref="javascript:expand(43)">../include/libtorrent/ip_voter.hpp:122</a></td><td>instead, have one instance per possible subnet, global IPv4, global IPv6, loopback, 192.168.x.x, 10.x.x.x, etc.</td></tr><trid="43"style="display: none;"colspan="3"><tdcolspan="3"><h2>instead, have one instance per possible subnet, global IPv4, global IPv6, loopback, 192.168.x.x, 10.x.x.x, etc.</h2><h4>../include/libtorrent/ip_voter.hpp:122</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> // away all the votes and started from scratch, in case
// our IP has changed
ptime m_last_rotate;
};
// this keeps track of multiple external IPs (for now, just IPv6 and IPv4, but
// it could be extended to deal with loopback and local network addresses as well)
struct TORRENT_EXTRA_EXPORT external_ip
{
// returns true if a different IP is the top vote now
// i.e. we changed our idea of what our external IP is
bool cast_vote(address const& ip, int source_type, address const& source);
// the external IP as it would be observed from `ip`
</pre></td></tr><trstyle="background: #ccf"><td>relevance 1</td><td><ahref="javascript:expand(44)">../include/libtorrent/web_peer_connection.hpp:121</a></td><td>if we make this be a disk_buffer_holder instead we would save a copy sometimes use allocate_disk_receive_buffer and release_disk_receive_buffer</td></tr><trid="44"style="display: none;"colspan="3"><tdcolspan="3"><h2>if we make this be a disk_buffer_holder instead
we would save a copy sometimes
use allocate_disk_receive_buffer and release_disk_receive_buffer</h2><h4>../include/libtorrent/web_peer_connection.hpp:121</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;">
// the number of bytes received in the current HTTP
// response. used to know where in the buffer the
// next response starts
size_type m_received_body;
// position in the current range response
size_type m_range_pos;
// 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
size_type m_chunk_pos;
// the position in the current block
int m_block_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;
};
}
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(45)">../src/block_cache.cpp:884</a></td><td>it's somewhat expensive to iterate over this linked list. Presumably because of the random access of memory. It would be nice if pieces with no evictable blocks weren't in this list</td></tr><trid="45"style="display: none;"colspan="3"><tdcolspan="3"><h2>it's somewhat expensive
to iterate over this linked list. Presumably because of the random
access of memory. It would be nice if pieces with no evictable blocks
weren't in this list</h2><h4>../src/block_cache.cpp:884</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> }
else if (m_last_cache_op == ghost_hit_lru1)
{
// when we insert new items or move things from L1 to L2
if (pe->num_blocks <= pe->pinned) continue;
// go through the blocks and evict the ones that are not dirty and not
// referenced
for (int j = 0; j < pe->blocks_in_piece && num > 0; ++j)
{
cached_block_entry& b = pe->blocks[j];
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(46)">../src/block_cache.cpp:948</a></td><td>this should probably only be done every n:th time</td></tr><trid="46"style="display: none;"colspan="3"><tdcolspan="3"><h2>this should probably only be done every n:th time</h2><h4>../src/block_cache.cpp:948</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> }
if (pe->ok_to_evict())
{
#ifdef TORRENT_DEBUG
for (int j = 0; j < pe->blocks_in_piece; ++j)
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(47)">../src/block_cache.cpp:1714</a></td><td>create a holder for refcounts that automatically decrement</td></tr><trid="47"style="display: none;"colspan="3"><tdcolspan="3"><h2>create a holder for refcounts that automatically decrement</h2><h4>../src/block_cache.cpp:1714</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;">
boost::shared_ptr<piece_manager> s = pe->storage;
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(48)">../src/bt_peer_connection.cpp:646</a></td><td>this could be optimized using knuth morris pratt</td></tr><trid="48"style="display: none;"colspan="3"><tdcolspan="3"><h2>this could be optimized using knuth morris pratt</h2><h4>../src/bt_peer_connection.cpp:646</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> {
disconnect(errors::no_memory, op_encryption);
return;
}
#ifdef TORRENT_VERBOSE_LOGGING
peer_log(" computed RC4 keys");
#endif
}
int bt_peer_connection::get_syncoffset(char const* src, int src_size,
char const* target, int target_size) const
{
TORRENT_ASSERT(target_size >= src_size);
TORRENT_ASSERT(src_size > 0);
TORRENT_ASSERT(src);
TORRENT_ASSERT(target);
int traverse_limit = target_size - src_size;
<divstyle="background: #ffff00"width="100%"> for (int i = 0; i < traverse_limit; ++i)
</div> {
char const* target_ptr = target + i;
if (std::equal(src, src+src_size, target_ptr))
return i;
}
// // Partial sync
// for (int i = 0; i < target_size; ++i)
// {
// // first is iterator in src[] at which mismatch occurs
// // second is iterator in target[] at which mismatch occurs
// std::pair<const char*, const char*> ret;
// int src_sync_size;
// if (i > traverse_limit) // partial sync test
// {
// ret = std::mismatch(src, src + src_size - (i - traverse_limit), &target[i]);
// src_sync_size = ret.first - src;
// if (src_sync_size == (src_size - (i - traverse_limit)))
// return i;
// }
// else // complete sync test
// {
// ret = std::mismatch(src, src + src_size, &target[i]);
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(50)">../src/disk_io_thread.cpp:921</a></td><td>instead of doing a lookup each time through the loop, save cached_piece_entry pointers with piece_refcount incremented to pin them</td></tr><trid="50"style="display: none;"colspan="3"><tdcolspan="3"><h2>instead of doing a lookup each time through the loop, save
cached_piece_entry pointers with piece_refcount incremented to pin them</h2><h4>../src/disk_io_thread.cpp:921</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> // this is why we pass in 1 as cont_block to the flushing functions
num -= try_flush_hashed(pe, 1, completed_jobs, l);
--pe->piece_refcount;
}
// when the write cache is under high pressure, it is likely
// counter productive to actually do this, since a piece may
// not have had its flush_hashed job run on it
// so only do it if no other thread is currently flushing
if (num == 0 || m_stats_counters[counters::num_writing_threads] > 0) return;
// if we still need to flush blocks, start over and flush
// everything in LRU order (degrade to lru cache eviction)
for (std::vector<std::pair<piece_manager*, int>>::iterator i = pieces.begin()
, end(pieces.end()); i != end; ++i)
{
cached_piece_entry* pe = m_disk_cache.find_piece(i->first, i->second);
if (pe == NULL) continue;
if (pe->num_dirty == 0) continue;
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(51)">../src/disk_io_thread.cpp:1132</a></td><td>instead of doing this. pass in the settings to each storage_interface call. Each disk thread could hold its most recent understanding of the settings in a shared_ptr, and update it every time it wakes up from a job. That way each access to the settings won't require a mutex to be held.</td></tr><trid="51"style="display: none;"colspan="3"><tdcolspan="3"><h2>instead of doing this. pass in the settings to each storage_interface
call. Each disk thread could hold its most recent understanding of the settings
in a shared_ptr, and update it every time it wakes up from a job. That way
each access to the settings won't require a mutex to be held.</h2><h4>../src/disk_io_thread.cpp:1132</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> {
INVARIANT_CHECK;
TORRENT_ASSERT(j->next == 0);
TORRENT_ASSERT((j->flags & disk_io_job::in_progress) || !j->storage);
int ret = (this->*(job_functions[j->action]))(j, completed_jobs);
--m_outstanding_jobs;
if (ret == retry_job)
{
mutex::scoped_lock l(m_job_mutex);
// to avoid busy looping here, give up
// our quanta in case there aren't any other
// jobs to run in between
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(52)">../src/disk_io_thread.cpp:1157</a></td><td>a potentially more efficient solution would be to have a special queue for retry jobs, that's only ever run when a job completes, in any thread. It would only work if m_outstanding_jobs > 0</td></tr><trid="52"style="display: none;"colspan="3"><tdcolspan="3"><h2>a potentially more efficient solution would be to have a special
queue for retry jobs, that's only ever run when a job completes, in
any thread. It would only work if m_outstanding_jobs > 0</h2><h4>../src/disk_io_thread.cpp:1157</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> storage->get_storage_impl()->m_settings = &m_settings;
int ret = (this->*(job_functions[j->action]))(j, completed_jobs);
--m_outstanding_jobs;
if (ret == retry_job)
{
mutex::scoped_lock l(m_job_mutex);
// to avoid busy looping here, give up
// our quanta in case there aren't any other
// jobs to run in between
<divstyle="background: #ffff00"width="100%">
</div> TORRENT_ASSERT((j->flags & disk_io_job::in_progress) || !j->storage);
bool need_sleep = m_queued_jobs.empty();
m_queued_jobs.push_back(j);
l.unlock();
if (need_sleep) sleep(0);
return;
}
#if TORRENT_USE_ASSERT
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(53)">../src/disk_io_thread.cpp:1171</a></td><td>it should clear the hash state even when there's an error, right?</td></tr><trid="53"style="display: none;"colspan="3"><tdcolspan="3"><h2>it should clear the hash state even when there's an error, right?</h2><h4>../src/disk_io_thread.cpp:1171</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> --m_outstanding_jobs;
if (ret == retry_job)
{
mutex::scoped_lock l(m_job_mutex);
// to avoid busy looping here, give up
// our quanta in case there aren't any other
// jobs to run in between
TORRENT_ASSERT((j->flags & disk_io_job::in_progress) || !j->storage);
bool need_sleep = m_queued_jobs.empty();
m_queued_jobs.push_back(j);
l.unlock();
if (need_sleep) sleep(0);
return;
}
#if TORRENT_USE_ASSERT
<divstyle="background: #ffff00"width="100%"> if (j->action == disk_io_job::hash && !j->error.ec)
</div> {
// a hash job should never return without clearing pe->hash
l.lock();
cached_piece_entry* pe = m_disk_cache.find_piece(j);
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(54)">../src/disk_io_thread.cpp:1866</a></td><td>maybe the tailqueue_iterator should contain a pointer-pointer instead and have an unlink function</td></tr><trid="54"style="display: none;"colspan="3"><tdcolspan="3"><h2>maybe the tailqueue_iterator should contain a pointer-pointer
instead and have an unlink function</h2><h4>../src/disk_io_thread.cpp:1866</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> j->callback = handler;
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(55)">../src/disk_io_thread.cpp:2121</a></td><td>this is potentially very expensive. One way to solve it would be to have a fence for just this one piece.</td></tr><trid="55"style="display: none;"colspan="3"><tdcolspan="3"><h2>this is potentially very expensive. One way to solve
it would be to have a fence for just this one piece.</h2><h4>../src/disk_io_thread.cpp:2121</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> }
void disk_io_thread::async_clear_piece(piece_manager* storage, int index
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(56)">../src/disk_io_thread.cpp:2382</a></td><td>we should probably just hang the job on the piece and make sure the hasher gets kicked</td></tr><trid="56"style="display: none;"colspan="3"><tdcolspan="3"><h2>we should probably just hang the job on the piece and make sure the hasher gets kicked</h2><h4>../src/disk_io_thread.cpp:2382</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> if (pe == NULL)
{
int cache_state = (j->flags & disk_io_job::volatile_read)
// blocks up front, and then hash them without holding the lock
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(57)">../src/disk_io_thread.cpp:2452</a></td><td>introduce a holder class that automatically increments and decrements the piece_refcount</td></tr><trid="57"style="display: none;"colspan="3"><tdcolspan="3"><h2>introduce a holder class that automatically increments
and decrements the piece_refcount</h2><h4>../src/disk_io_thread.cpp:2452</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> for (int i = ph->offset / block_size; i < blocks_in_piece; ++i)
TORRENT_PIECE_ASSERT(ph->offset == i * block_size, pe);
ret = j->storage->get_storage_impl()->readv(&iov, 1, j->piece
, ph->offset, file_flags, j->error);
if (ret < 0)
{
m_disk_cache.free_buffer((char*)iov.iov_base);
l.lock();
break;
}
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(58)">../src/disk_io_thread.cpp:2692</a></td><td>it would be nice to not have to lock the mutex every turn through this loop</td></tr><trid="58"style="display: none;"colspan="3"><tdcolspan="3"><h2>it would be nice to not have to lock the mutex every
turn through this loop</h2><h4>../src/disk_io_thread.cpp:2692</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> {
ret = j->storage->get_storage_impl()->readv(&iov, 1, j->piece
, offset, file_flags, j->error);
if (ret < 0)
{
l.lock();
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(59)">../src/http_tracker_connection.cpp:96</a></td><td>support authentication (i.e. user name and password) in the URL</td></tr><trid="59"style="display: none;"colspan="3"><tdcolspan="3"><h2>support authentication (i.e. user name and password) in the URL</h2><h4>../src/http_tracker_connection.cpp:96</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> , tracker_request const& req
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(60)">../src/metadata_transfer.cpp:359</a></td><td>this is not safe. The torrent could be unloaded while we're still sending the metadata</td></tr><trid="60"style="display: none;"colspan="3"><tdcolspan="3"><h2>this is not safe. The torrent could be unloaded while
we're still sending the metadata</h2><h4>../src/metadata_transfer.cpp:359</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> std::pair<int, int> offset
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(61)">../src/packet_buffer.cpp:176</a></td><td>use compare_less_wrap for this comparison as well</td></tr><trid="61"style="display: none;"colspan="3"><tdcolspan="3"><h2>use compare_less_wrap for this comparison as well</h2><h4>../src/packet_buffer.cpp:176</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> while (new_size < size)
for (index_type i = m_first; i < (m_first + m_capacity); ++i)
new_storage[i & (new_size - 1)] = m_storage[i & (m_capacity - 1)];
free(m_storage);
m_storage = new_storage;
m_capacity = new_size;
}
void* packet_buffer::remove(index_type idx)
{
INVARIANT_CHECK;
<divstyle="background: #ffff00"width="100%"> if (idx >= m_first + m_capacity)
</div> return 0;
if (compare_less_wrap(idx, m_first, 0xffff))
return 0;
const int mask = (m_capacity - 1);
void* old_value = m_storage[idx & mask];
m_storage[idx & mask] = 0;
if (old_value)
{
--m_size;
if (m_size == 0) m_last = m_first;
}
if (idx == m_first && m_size != 0)
{
++m_first;
for (boost::uint32_t i = 0; i < m_capacity; ++i, ++m_first)
if (m_storage[m_first & mask]) break;
m_first &= 0xffff;
}
if (((idx + 1) & 0xffff) == m_last && m_size != 0)
{
--m_last;
for (boost::uint32_t i = 0; i < m_capacity; ++i, --m_last)
if (m_storage[m_last & mask]) break;
++m_last;
m_last &= 0xffff;
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(62)">../src/part_file.cpp:252</a></td><td>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</td></tr><trid="62"style="display: none;"colspan="3"><tdcolspan="3"><h2>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</h2><h4>../src/part_file.cpp:252</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> if (((mode & file::rw_mask) != file::read_only)
if (ec == boost::system::errc::no_such_file_or_directory)
ec.clear();
if (ec)
{
copy_file(old_path, new_path, ec);
if (ec) return;
remove(old_path, ec);
}
}
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(63)">../src/part_file.cpp:344</a></td><td>instead of rebuilding the whole file header and flushing it, update the slot entries as we go</td></tr><trid="63"style="display: none;"colspan="3"><tdcolspan="3"><h2>instead of rebuilding the whole file header
and flushing it, update the slot entries as we go</h2><h4>../src/part_file.cpp:344</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> if (block_to_copy == m_piece_size)
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(64)">../src/peer_connection.cpp:1115</a></td><td>this should be the global download rate</td></tr><trid="64"style="display: none;"colspan="3"><tdcolspan="3"><h2>this should be the global download rate</h2><h4>../src/peer_connection.cpp:1115</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;">
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(65)">../src/peer_connection.cpp:3284</a></td><td>sort the allowed fast set in priority order</td></tr><trid="65"style="display: none;"colspan="3"><tdcolspan="3"><h2>sort the allowed fast set in priority order</h2><h4>../src/peer_connection.cpp:3284</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> m_allowed_fast.push_back(index);
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(66)">../src/piece_picker.cpp:2407</a></td><td>when expanding pieces for cache stripe reasons, the !downloading condition doesn't make much sense</td></tr><trid="66"style="display: none;"colspan="3"><tdcolspan="3"><h2>when expanding pieces for cache stripe reasons,
the !downloading condition doesn't make much sense</h2><h4>../src/piece_picker.cpp:2407</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> TORRENT_ASSERT(index < (int)m_piece_map.size() || m_piece_map.empty());
for (std::vector<block_info>::iterator i = m_block_info.begin()
, end(m_block_info.end()); i != end; ++i)
{
if (i->peer == peer) i->peer = 0;
}
}
namespace
{
// 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.
boost::tuple<bool, bool> requested_from(piece_picker::downloading_piece const& p
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(67)">../src/session_impl.cpp:678</a></td><td>there's no rule here to make uTP connections not have the global or local rate limits apply to it. This used to be the default.</td></tr><trid="67"style="display: none;"colspan="3"><tdcolspan="3"><h2>there's no rule here to make uTP connections not have the global or
local rate limits apply to it. This used to be the default.</h2><h4>../src/session_impl.cpp:678</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> m_global_class = m_classes.new_peer_class("global");
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(68)">../src/session_impl.cpp:2384</a></td><td>instead of having a special case for this, just make the default listen interfaces be "0.0.0.0:6881,[::1]:6881" and use the generic path. That would even allow for not listening at all.</td></tr><trid="68"style="display: none;"colspan="3"><tdcolspan="3"><h2>instead of having a special case for this, just make the
default listen interfaces be "0.0.0.0:6881,[::1]:6881" and use
the generic path. That would even allow for not listening at all.</h2><h4>../src/session_impl.cpp:2384</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;">
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(69)">../src/session_impl.cpp:3225</a></td><td>should this function take a shared_ptr instead?</td></tr><trid="69"style="display: none;"colspan="3"><tdcolspan="3"><h2>should this function take a shared_ptr instead?</h2><h4>../src/session_impl.cpp:3225</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> {
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(70)">../src/session_impl.cpp:3600</a></td><td>have a separate list for these connections, instead of having to loop through all of them</td></tr><trid="70"style="display: none;"colspan="3"><tdcolspan="3"><h2>have a separate list for these connections, instead of having to loop through all of them</h2><h4>../src/session_impl.cpp:3600</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> if (m_auto_manage_time_scaler < 0)
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(71)">../src/session_impl.cpp:3641</a></td><td>this should apply to all bandwidth channels</td></tr><trid="71"style="display: none;"colspan="3"><tdcolspan="3"><h2>this should apply to all bandwidth channels</h2><h4>../src/session_impl.cpp:3641</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> t.second_tick(tick_interval_ms, m_tick_residual / 1000);
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(72)">../src/session_impl.cpp:4704</a></td><td>these vectors could be copied from m_torrent_lists, if we would maintain them. That way the first pass over all torrents could be avoided. It would be especially efficient if most torrents are not auto-managed whenever we receive a scrape response (or anything that may change the rank of a torrent) that one torrent could re-sort itself in a list that's kept sorted at all times. That way, this pass over all torrents could be avoided alltogether.</td></tr><trid="72"style="display: none;"colspan="3"><tdcolspan="3"><h2>these vectors could be copied from m_torrent_lists,
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(73)">../src/session_impl.cpp:4779</a></td><td>allow extensions to sort torrents for queuing</td></tr><trid="73"style="display: none;"colspan="3"><tdcolspan="3"><h2>allow extensions to sort torrents for queuing</h2><h4>../src/session_impl.cpp:4779</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> if (t->is_finished())
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(74)">../src/session_impl.cpp:4957</a></td><td>use a lower limit than m_settings.connections_limit to allocate the to 10% or so of connection slots for incoming connections</td></tr><trid="74"style="display: none;"colspan="3"><tdcolspan="3"><h2>use a lower limit than m_settings.connections_limit
connections</h2><h4>../src/session_impl.cpp:4957</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> // if we don't have any free slots, return
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(75)">../src/session_impl.cpp:5119</a></td><td>post a message to have this happen immediately instead of waiting for the next tick</td></tr><trid="75"style="display: none;"colspan="3"><tdcolspan="3"><h2>post a message to have this happen
immediately instead of waiting for the next tick</h2><h4>../src/session_impl.cpp:5119</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> {
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(78)">../src/session_impl.cpp:5246</a></td><td>this should be called for all peers!</td></tr><trid="78"style="display: none;"colspan="3"><tdcolspan="3"><h2>this should be called for all peers!</h2><h4>../src/session_impl.cpp:5246</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> // measurement of the peak, use that + 10kB/s, otherwise
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(79)">../src/session_impl.cpp:5663</a></td><td>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</td></tr><trid="79"style="display: none;"colspan="3"><tdcolspan="3"><h2>it might be a nice feature here to limit the number of torrents
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(80)">../src/storage.cpp:710</a></td><td>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</td></tr><trid="80"style="display: none;"colspan="3"><tdcolspan="3"><h2>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</h2><h4>../src/storage.cpp:710</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> for (;;)
{
if (file_offset < files().file_size(file_index))
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(81)">../src/storage.cpp:1006</a></td><td>if everything moves OK, except for the partfile we currently won't update the save path, which breaks things. it would probably make more sense to give up on the partfile</td></tr><trid="81"style="display: none;"colspan="3"><tdcolspan="3"><h2>if everything moves OK, except for the partfile
we currently won't update the save path, which breaks things.
it would probably make more sense to give up on the partfile</h2><h4>../src/storage.cpp:1006</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> if (ec)
int default_storage::writev(file::iovec_t const* bufs, int num_bufs
, int slot, int offset, int flags, storage_error& ec)
{
fileop op = { &file::writev
, file::read_write | flags };
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(82)">../src/torrent.cpp:489</a></td><td>if the existing torrent doesn't have metadata, insert the metadata we just downloaded into it.</td></tr><trid="82"style="display: none;"colspan="3"><tdcolspan="3"><h2>if the existing torrent doesn't have metadata, insert
the metadata we just downloaded into it.</h2><h4>../src/torrent.cpp:489</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;">
m_torrent_file = tf;
// now, we might already have this torrent in the session.
boost::shared_ptr<torrent> t = m_ses.find_torrent(m_torrent_file->info_hash()).lock();
if (t)
{
if (!m_uuid.empty() && t->uuid().empty())
t->set_uuid(m_uuid);
if (!m_url.empty() && t->url().empty())
t->set_url(m_url);
if (!m_source_feed_url.empty() && t->source_feed_url().empty())
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(83)">../src/torrent.cpp:639</a></td><td>if the existing torrent doesn't have metadata, insert the metadata we just downloaded into it.</td></tr><trid="83"style="display: none;"colspan="3"><tdcolspan="3"><h2>if the existing torrent doesn't have metadata, insert
the metadata we just downloaded into it.</h2><h4>../src/torrent.cpp:639</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;">
m_torrent_file = tf;
// now, we might already have this torrent in the session.
boost::shared_ptr<torrent> t = m_ses.find_torrent(m_torrent_file->info_hash()).lock();
if (t)
{
if (!m_uuid.empty() && t->uuid().empty())
t->set_uuid(m_uuid);
if (!m_url.empty() && t->url().empty())
t->set_url(m_url);
if (!m_source_feed_url.empty() && t->source_feed_url().empty())
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(84)">../src/torrent.cpp:1444</a></td><td>is verify_peer_cert called once per certificate in the chain, and this function just tells us which depth we're at right now? If so, the comment makes sense. any certificate that isn't the leaf (i.e. the one presented by the peer) should be accepted automatically, given preverified is true. The leaf certificate need to be verified to make sure its DN matches the info-hash</td></tr><trid="84"style="display: none;"colspan="3"><tdcolspan="3"><h2>is verify_peer_cert called once per certificate in the chain, and
this function just tells us which depth we're at right now? If so, the comment
makes sense.
any certificate that isn't the leaf (i.e. the one presented by the peer)
should be accepted automatically, given preverified is true. The leaf certificate
need to be verified to make sure its DN matches the info-hash</h2><h4>../src/torrent.cpp:1444</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> if (pp) p->add_extension(pp);
}
// if files are checked for this torrent, call the extension
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(85)">../src/torrent.cpp:1836</a></td><td>instead of creating the picker up front here, maybe this whole section should move to need_picker()</td></tr><trid="85"style="display: none;"colspan="3"><tdcolspan="3"><h2>instead of creating the picker up front here,
maybe this whole section should move to need_picker()</h2><h4>../src/torrent.cpp:1836</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> else
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(86)">../src/torrent.cpp:2032</a></td><td>there may be peer extensions relying on the torrent extension still being alive. Only do this if there are no peers. And when the last peer is disconnected, if the torrent is unloaded, clear the extensions m_extensions.clear();</td></tr><trid="86"style="display: none;"colspan="3"><tdcolspan="3"><h2>there may be peer extensions relying on the torrent extension
still being alive. Only do this if there are no peers. And when the last peer
is disconnected, if the torrent is unloaded, clear the extensions
m_extensions.clear();</h2><h4>../src/torrent.cpp:2032</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> // pinned torrents are not allowed to be swapped out
TORRENT_ASSERT(!m_pinned);
m_should_be_loaded = false;
// make sure it's not unloaded in the middle of some operation that uses it
if (m_refcount > 0) return;
// call on_unload() on extensions
#ifndef TORRENT_DISABLE_EXTENSIONS
for (extension_list_t::iterator i = m_extensions.begin()
, end(m_extensions.end()); i != end; ++i)
{
TORRENT_TRY {
(*i)->on_unload();
} TORRENT_CATCH (std::exception&) {}
}
// also remove extensions and re-instantiate them when the torrent is loaded again
// they end up using a significant amount of memory
if (was_introduced_by(pp, ep)) return (bt_peer_connection*)p;
}
#endif
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(87)">../src/torrent.cpp:2705</a></td><td>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</td></tr><trid="87"style="display: none;"colspan="3"><tdcolspan="3"><h2>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</h2><h4>../src/torrent.cpp:2705</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> // if the files haven't been checked yet, we're
// 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 defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
debug_log("DHT: no dht initialized");
#endif
return;
}
if (!should_announce_dht())
{
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
if (!m_ses.announce_dht())
debug_log("DHT: no listen sockets");
if (m_torrent_file->is_valid() && !m_files_checked)
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(88)">../src/torrent.cpp:3236</a></td><td>instead, borrow host resolvers from a pool in session_impl. That would make the torrent object smaller</td></tr><trid="88"style="display: none;"colspan="3"><tdcolspan="3"><h2>instead, borrow host resolvers from a pool in session_impl. That
would make the torrent object smaller</h2><h4>../src/torrent.cpp:3236</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> , boost::bind(&torrent::on_i2p_resolve
, shared_from_this(), _1));
*/
// it seems like you're not supposed to do a name lookup
// on the peers returned from the tracker, but just strip
// the .i2p and use it as a destination
i->ip.resize(i->ip.size() - 4);
torrent_state st = get_policy_state();
need_policy();
if (m_policy->add_i2p_peer(i->ip.c_str(), peer_info::tracker, 0, &st))
// it would be nice if we would keep track of piece
// availability even when we're a seed, for
// the suggest piece feature
if (!has_picker()) return;
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(90)">../src/torrent.cpp:4570</a></td><td>really, we should just keep the picker around in this case to maintain the availability counters</td></tr><trid="90"style="display: none;"colspan="3"><tdcolspan="3"><h2>really, we should just keep the picker around
in this case to maintain the availability counters</h2><h4>../src/torrent.cpp:4570</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> pieces.reserve(cs.pieces.size());
// sort in ascending order, to get most recently used first
</div> for (const_peer_iterator i = m_connections.begin()
, end(m_connections.end()); i != end; ++i)
{
peer_connection* peer = *i;
if (peer->has_piece(p.piece_index)) ++p.num_peers;
}
}
pieces.push_back(p);
}
// sort by rarity (stable, to maintain sort
// by last use)
std::stable_sort(pieces.begin(), pieces.end());
// only suggest half of the pieces
pieces.resize(pieces.size() / 2);
// send new suggests to peers
// the peers will filter out pieces we've
// already suggested to them
for (std::vector<suggest_piece_t>::iterator i = pieces.begin()
, end(pieces.end()); i != end; ++i)
{
for (peer_iterator p = m_connections.begin();
p != m_connections.end(); ++p)
(*p)->send_suggest(i->piece_index);
}
}
void torrent::abort()
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(91)">../src/torrent.cpp:6480</a></td><td>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</td></tr><trid="91"style="display: none;"colspan="3"><tdcolspan="3"><h2>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</h2><h4>../src/torrent.cpp:6480</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> m_last_upload = rd.dict_find_int_value("last_upload", 0);
if (!m_use_resume_save_path)
{
std::string p = rd.dict_find_string_value("save_path");
// unallocated slots are assumed to be priority 1, so cut off any
// trailing ones
int end_range = num_files - 1;
for (; end_range >= 0; --end_range) if (m_file_priority[end_range] != 1) break;
m_file_priority.resize(end_range + 1);
// initialize pad files to priority 0
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(92)">../src/torrent.cpp:6643</a></td><td>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</td></tr><trid="92"style="display: none;"colspan="3"><tdcolspan="3"><h2>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</h2><h4>../src/torrent.cpp:6643</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> add_web_seed(url, web_seed_entry::http_seed);
using namespace libtorrent::detail; // for write_*_endpoint()
ret["file-format"] = "libtorrent resume file";
ret["file-version"] = 1;
ret["libtorrent-version"] = LIBTORRENT_VERSION;
ret["total_uploaded"] = m_total_uploaded;
ret["total_downloaded"] = m_total_downloaded;
ret["active_time"] = m_active_time;
ret["finished_time"] = m_finished_time;
ret["seeding_time"] = m_seeding_time;
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(93)">../src/torrent.cpp:6837</a></td><td>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</td></tr><trid="93"style="display: none;"colspan="3"><tdcolspan="3"><h2>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</h2><h4>../src/torrent.cpp:6837</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> pieces.resize(m_torrent_file->num_pieces());
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(94)">../src/torrent.cpp:8765</a></td><td>add a flag to ignore stats, and only care about resume data for content. For unchanged files, don't trigger a load of the metadata just to save an empty resume data file</td></tr><trid="94"style="display: none;"colspan="3"><tdcolspan="3"><h2>add a flag to ignore stats, and only care about resume data for
just to save an empty resume data file</h2><h4>../src/torrent.cpp:8765</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> if (m_complete != 0xffffff) seeds = m_complete;
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(95)">../src/torrent.cpp:9708</a></td><td>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</td></tr><trid="95"style="display: none;"colspan="3"><tdcolspan="3"><h2>go through the pieces we have and count the total number
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(96)">../src/torrent.cpp:10354</a></td><td>instead of resorting the whole list, insert the peers directly into the right place</td></tr><trid="96"style="display: none;"colspan="3"><tdcolspan="3"><h2>instead of resorting the whole list, insert the peers
directly into the right place</h2><h4>../src/torrent.cpp:10354</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> printf("timed out [average-piece-time: %d ms ]\n"
for (std::list<web_seed_entry>::const_iterator i = m_web_seeds.begin()
, end(m_web_seeds.end()); i != end; ++i)
{
if (i->peer_info.banned) continue;
if (i->type != type) continue;
ret.insert(i->url);
}
return ret;
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(97)">../src/torrent_peer.cpp:179</a></td><td>how do we deal with our external address changing?</td></tr><trid="97"style="display: none;"colspan="3"><tdcolspan="3"><h2>how do we deal with our external address changing?</h2><h4>../src/torrent_peer.cpp:179</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> , is_v6_addr(false)
#endif
#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)
#if TORRENT_USE_ASSERTS
, in_use(false)
#endif
{
TORRENT_ASSERT((src & 0xff) == src);
}
boost::uint32_t torrent_peer::rank(external_ip const& external, int external_port) const
{
<divstyle="background: #ffff00"width="100%"> if (peer_rank == 0)
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(98)">../src/udp_socket.cpp:290</a></td><td>it would be nice to detect this on posix systems also</td></tr><trid="98"style="display: none;"colspan="3"><tdcolspan="3"><h2>it would be nice to detect this on posix systems also</h2><h4>../src/udp_socket.cpp:290</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> --m_v6_outstanding;
for (std::vector<udp_socket_observer*>::iterator i = m_observers.begin();
i != m_observers.end();)
{
bool ret = false;
TORRENT_TRY {
ret = (*i)->incoming_packet(ec, ep, buf, size);
} TORRENT_CATCH (std::exception&) {}
if (*i == NULL) i = m_observers.erase(i);
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(99)">../src/udp_tracker_connection.cpp:554</a></td><td>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</td></tr><trid="99"style="display: none;"colspan="3"><tdcolspan="3"><h2>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</h2><h4>../src/udp_tracker_connection.cpp:554</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> }
bool udp_tracker_connection::on_scrape_response(char const* buf, int size)
{
restart_read_timeout();
int action = detail::read_int32(buf);
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(100)">../src/upnp.cpp:72</a></td><td>listen_interface is not used. It's meant to bind the broadcast socket</td></tr><trid="100"style="display: none;"colspan="3"><tdcolspan="3"><h2>listen_interface is not used. It's meant to bind the broadcast socket</h2><h4>../src/upnp.cpp:72</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;">#include <asio/ip/multicast.hpp>
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(101)">../src/ut_metadata.cpp:320</a></td><td>we really need to increment the refcounter on the torrent while this buffer is still in the peer's send buffer</td></tr><trid="101"style="display: none;"colspan="3"><tdcolspan="3"><h2>we really need to increment the refcounter on the torrent
while this buffer is still in the peer's send buffer</h2><h4>../src/ut_metadata.cpp:320</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> if (!m_tp.need_loaded()) return;
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(102)">../src/utp_stream.cpp:1627</a></td><td>this loop may not be very efficient</td></tr><trid="102"style="display: none;"colspan="3"><tdcolspan="3"><h2>this loop may not be very efficient</h2><h4>../src/utp_stream.cpp:1627</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;">
// sends a packet, pulls data from the write buffer (if there's any)
// if ack is true, we need to send a packet regardless of if there's
// any data. Returns true if we could send more data (i.e. call
// send_pkt() again)
// returns true if there is more space for payload in our
// congestion window, false if there is no more space.
bool utp_socket_impl::send_pkt(int flags)
{
INVARIANT_CHECK;
bool force = (flags & pkt_ack) || (flags & pkt_fin);
// TORRENT_ASSERT(m_state != UTP_STATE_FIN_SENT || (flags & pkt_ack));
// first see if we need to resend any packets
<divstyle="background: #ffff00"width="100%"> for (int i = (m_acked_seq_nr + 1) & ACK_MASK; i != m_seq_nr; i = (i + 1) & ACK_MASK)
</div> {
packet* p = (packet*)m_outbuf.at(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 (m_state == UTP_STATE_ERROR_WAIT || m_state == UTP_STATE_DELETE) 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;
}
int sack = 0;
if (m_inbuf.size())
{
// the SACK bitfield should ideally fit all
// the pieces we have successfully received
sack = (m_inbuf.span() + 7) / 8;
if (sack > 32) sack = 32;
}
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(103)">../src/web_connection_base.cpp:71</a></td><td>introduce a web-seed default class which has a low download priority</td></tr><trid="103"style="display: none;"colspan="3"><tdcolspan="3"><h2>introduce a web-seed default class which has a low download priority</h2><h4>../src/web_connection_base.cpp:71</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;">
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(104)">../src/kademlia/dht_tracker.cpp:428</a></td><td>ideally this function would be called when the put completes</td></tr><trid="104"style="display: none;"colspan="3"><tdcolspan="3"><h2>ideally this function would be called when the
put completes</h2><h4>../src/kademlia/dht_tracker.cpp:428</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> // since it controls whether we re-put the content
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(105)">../src/kademlia/routing_table.cpp:308</a></td><td>instad of refreshing a bucket by using find_nodes, ping each node periodically</td></tr><trid="105"style="display: none;"colspan="3"><tdcolspan="3"><h2>instad of refreshing a bucket by using find_nodes,
ping each node periodically</h2><h4>../src/kademlia/routing_table.cpp:308</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> os << "]\n";
// count the number of bits in the bitfield that are set to 1.
int count() const
{
int ret = 0;
const int words = num_words();
#if TORRENT_HAS_SSE
unsigned int cpui[4];
cpuid(cpui, 1);
if (cpui[2] & (1 << 23))
{
for (int i = 0; i < words; ++i)
{
#ifdef __GNUC__
ret += __builtin_popcount(m_buf[i]);
#else
ret += _mm_popcnt_u32(m_buf[i]);
#endif
}
return ret;
}
#endif // TORRENT_HAS_SSE
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(107)">../include/libtorrent/block_cache.hpp:220</a></td><td>make this 32 bits and to count seconds since the block cache was created</td></tr><trid="107"style="display: none;"colspan="3"><tdcolspan="3"><h2>make this 32 bits and to count seconds since the block cache was created</h2><h4>../include/libtorrent/block_cache.hpp:220</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;">
// the number of blocks in the cache for this piece
boost::uint64_t num_blocks:14;
// the total number of blocks in this piece (and the number
// of elements in the blocks array)
boost::uint64_t blocks_in_piece:14;
// ---- 64 bit boundary ----
// while we have an outstanding async hash operation
// working on this piece, 'hashing' is set to 1
// When the operation returns, this is set to 0.
boost::uint32_t hashing:1;
// if we've completed at least one hash job on this
// piece, and returned it. This is set to one
boost::uint32_t hashing_done:1;
// if this is true, whenever refcount hits 0,
// this piece should be deleted
boost::uint32_t marked_for_deletion:1;
// this is set to true once we flush blocks past
// the hash cursor. Once this happens, there's
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(108)">../include/libtorrent/config.hpp:339</a></td><td>Make this count Unicode characters instead of bytes on windows</td></tr><trid="108"style="display: none;"colspan="3"><tdcolspan="3"><h2>Make this count Unicode characters instead of bytes on windows</h2><h4>../include/libtorrent/config.hpp:339</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;">#define TORRENT_USE_WRITEV 0
#define TORRENT_USE_READV 0
#else
#warning unknown OS, assuming BSD
#define TORRENT_BSD
#endif
#if defined __GNUC__ && !(defined TORRENT_USE_OSATOMIC \
|| defined TORRENT_USE_INTERLOCKED_ATOMIC \
|| defined TORRENT_USE_BEOS_ATOMIC \
|| defined TORRENT_USE_SOLARIS_ATOMIC)
// atomic operations in GCC were introduced in 4.1.1
// on windows, NAME_MAX refers to Unicode characters
// on linux it refers to bytes (utf-8 encoded)
<divstyle="background: #ffff00"width="100%">
</div>// windows
#if defined FILENAME_MAX
#define TORRENT_MAX_PATH FILENAME_MAX
// beos
#elif defined B_PATH_NAME_LENGTH
#define TORRENT_MAX_PATH B_PATH_NAME_LENGTH
// solaris
#elif defined MAXPATH
#define TORRENT_MAX_PATH MAXPATH
// posix
#elif defined NAME_MAX
#define TORRENT_MAX_PATH NAME_MAX
// none of the above
#else
// this is the maximum number of characters in a
// path element / filename on windows
#define TORRENT_MAX_PATH 255
#warning unknown platform, assuming the longest path is 255
#endif
#if defined TORRENT_WINDOWS && !defined TORRENT_MINGW
#include <stdarg.h>
// internal
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(109)">../include/libtorrent/debug.hpp:212</a></td><td>rewrite this class to use FILE* instead and have a printf-like interface</td></tr><trid="109"style="display: none;"colspan="3"><tdcolspan="3"><h2>rewrite this class to use FILE* instead and
have a printf-like interface</h2><h4>../include/libtorrent/debug.hpp:212</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;">#endif
}
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(110)">../include/libtorrent/disk_buffer_pool.hpp:133</a></td><td>try to remove the observers, only using the async_allocate handlers</td></tr><trid="110"style="display: none;"colspan="3"><tdcolspan="3"><h2>try to remove the observers, only using the async_allocate handlers</h2><h4>../include/libtorrent/disk_buffer_pool.hpp:133</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;">
// number of bytes per block. The BitTorrent
// protocol defines the block size to 16 KiB.
const int m_block_size;
// number of disk buffers currently allocated
int m_in_use;
// cache size limit
int m_max_use;
// if we have exceeded the limit, we won't start
// allowing allocations again until we drop below
// this low watermark
int m_low_watermark;
// if we exceed the max number of buffers, we start
// adding up callbacks to this queue. Once the number
// of buffers in use drops below the low watermark,
// the pointer to the block of virtual address space
// making up the mmapped cache space
char* m_cache_pool;
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(111)">../include/libtorrent/peer_connection.hpp:217</a></td><td>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</td></tr><trid="111"style="display: none;"colspan="3"><tdcolspan="3"><h2>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</h2><h4>../include/libtorrent/peer_connection.hpp:217</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> , m_snubbed(false)
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(112)">../include/libtorrent/peer_connection.hpp:1141</a></td><td>factor this out into its own class with a virtual interface torrent and session should implement this interface</td></tr><trid="112"style="display: none;"colspan="3"><tdcolspan="3"><h2>factor this out into its own class with a virtual interface
torrent and session should implement this interface</h2><h4>../include/libtorrent/peer_connection.hpp:1141</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;">
<divstyle="background: #ffff00"width="100%"> stat m_statistics;
</div> protected:
// if the timeout is extended for the outstanding
// requests, this is the number of seconds it was
// extended.
int m_timeout_extend;
// the number of outstanding bytes expected
// to be received by extensions
int m_extension_outstanding_bytes;
// the number of time critical requests
// queued up in the m_request_queue that
// soon will be committed to the download
// queue. This is included in download_queue_time()
// so that it can be used while adding more
// requests and take the previous requests
// into account without submitting it all
// immediately
int m_queued_time_critical;
// the number of valid, received bytes in m_recv_buffer
int m_recv_end:24;
//#error 1 byte
// recv_buf.begin (start of actual receive buffer)
// |
// | m_recv_start (logical start of current
// | | receive buffer, as perceived by upper layers)
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(113)">../include/libtorrent/peer_connection_interface.hpp:45</a></td><td>make this interface smaller!</td></tr><trid="113"style="display: none;"colspan="3"><tdcolspan="3"><h2>make this interface smaller!</h2><h4>../include/libtorrent/peer_connection_interface.hpp:45</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;">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
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(114)">../include/libtorrent/performance_counters.hpp:132</a></td><td>should keepalives be in here too? how about dont-have, share-mode, upload-only</td></tr><trid="114"style="display: none;"colspan="3"><tdcolspan="3"><h2>should keepalives be in here too?
how about dont-have, share-mode, upload-only</h2><h4>../include/libtorrent/performance_counters.hpp:132</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> // a connect candidate
connection_attempt_loops,
// successful incoming connections (not rejected for any reason)
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(115)">../include/libtorrent/performance_counters.hpp:404</a></td><td>some space could be saved here by making gauges 32 bits</td></tr><trid="115"style="display: none;"colspan="3"><tdcolspan="3"><h2>some space could be saved here by making gauges 32 bits</h2><h4>../include/libtorrent/performance_counters.hpp:404</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> limiter_down_bytes,
// if the atomic type is't lock-free, use a single lock instead, for
// the whole array
mutex m_mutex;
boost::int64_t m_stats_counter[num_counters];
#endif
};
}
#endif
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(116)">../include/libtorrent/piece_picker.hpp:669</a></td><td>should this be allocated lazily?</td></tr><trid="116"style="display: none;"colspan="3"><tdcolspan="3"><h2>should this be allocated lazily?</h2><h4>../include/libtorrent/piece_picker.hpp:669</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> std::vector<downloading_piece>::const_iterator find_dl_piece(int queue, int index) const;
std::vector<downloading_piece>::iterator find_dl_piece(int queue, int index);
// returns an iterator to the downloading piece, whichever
// has an entry in this list with block allocations.
// i.e. it says wich parts of the piece that
// is being downloaded. This list is ordered
// by piece index to make lookups efficient
// there are 3 buckets of downloading pieces, each
// is individually sorted by piece index.
// 0: downloading pieces with unrequested blocks
// 1: downloading pieces where every block is busy
// and some are still in the requested state
// 2: downloading pieces where every block is
// finished or writing
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(117)">../include/libtorrent/proxy_base.hpp:166</a></td><td>it would be nice to remember the bind port and bind once we know where the proxy is m_sock.bind(endpoint, ec);</td></tr><trid="117"style="display: none;"colspan="3"><tdcolspan="3"><h2>it would be nice to remember the bind port and bind once we know where the proxy is
// Creates a new peer class (see peer-classes_) with the given name. The
// returned integer is the new peer class' identifier. Peer classes may
// have the same name, so each invocation of this function creates a new
// class and returns a unique identifier.
//
// Identifiers are assigned from low numbers to higher. So if you plan on
// using certain peer classes in a call to `set_peer_class_filter()`_,
// make sure to create those early on, to get low identifiers.
//
// For more information on peer classes, see peer-classes_.
int create_peer_class(char const* name);
// This call dereferences the reference count of the specified peer
// class. When creating a peer class it's automatically referenced by 1.
// If you want to recycle a peer class, you may call this function. You
// may only call this function **once** per peer class you create.
// Calling it more than once for the same class will lead to memory
// corruption.
//
// Since peer classes are reference counted, this function will not
// remove the peer class if it's still assigned to torrents or peers. It
// will however remove it once the last peer and torrent drops their
// references to it.
//
// There is no need to call this function for custom peer classes. All
// peer classes will be properly destructed when the session object
// destructs.
//
// For more information on peer classes, see peer-classes_.
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(119)">../include/libtorrent/settings_pack.hpp:1074</a></td><td>deprecate this ``max_rejects`` is the number of piece requests we will reject in a row while a peer is choked before the peer is considered abusive and is disconnected.</td></tr><trid="119"style="display: none;"colspan="3"><tdcolspan="3"><h2>deprecate this
``max_rejects`` is the number of piece requests we will reject in a row
while a peer is choked before the peer is considered abusive and is
// ``recv_socket_buffer_size`` and ``send_socket_buffer_size`` specifies
// the buffer sizes set on peer sockets. 0 (which is the default) means
// the OS default (i.e. don't change the buffer sizes). The socket buffer
// sizes are changed using setsockopt() with SOL_SOCKET/SO_RCVBUF and
// SO_SNDBUFFER.
recv_socket_buffer_size,
send_socket_buffer_size,
// ``file_checks_delay_per_block`` is the number of milliseconds to sleep
// in between disk read operations when checking torrents. This defaults
// to 0, but can be set to higher numbers to slow down the rate at which
// data is read from the disk while checking. This may be useful for
// background tasks that doesn't matter if they take a bit longer, as long
// as they leave disk I/O time for other processes.
file_checks_delay_per_block,
// ``read_cache_line_size`` is the number of blocks to read into the read
// cache when a read cache miss occurs. Setting this to 0 is essentially
// the same thing as disabling read cache. The number of blocks read
// into the read cache is always capped by the piece boundry.
//
// When a piece in the write cache has ``write_cache_line_size`` contiguous
// blocks in it, they will be flushed. Setting this to 1 effectively
// disables the write cache.
read_cache_line_size,
write_cache_line_size,
// ``optimistic_disk_retry`` is the number of seconds from a disk write
// errors occur on a torrent until libtorrent will take it out of the
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(120)">../include/libtorrent/size_type.hpp:48</a></td><td>remove these and just use boost's types directly</td></tr><trid="120"style="display: none;"colspan="3"><tdcolspan="3"><h2>remove these and just use boost's types directly</h2><h4>../include/libtorrent/size_type.hpp:48</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;">ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// 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.
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(122)">../include/libtorrent/torrent.hpp:1249</a></td><td>These two bitfields should probably be coalesced into one</td></tr><trid="122"style="display: none;"colspan="3"><tdcolspan="3"><h2>These two bitfields should probably be coalesced into one</h2><h4>../include/libtorrent/torrent.hpp:1249</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> // the .torrent file from m_url
// std::vector<char> m_torrent_file_buf;
// this is a list of all pieces that we have announced
// as having, without actually having yet. If we receive
// a request for a piece in this list, we need to hold off
// on responding until we have completed the piece and
// verified its hash. If the hash fails, send reject to
// peers with outstanding requests, and dont_have to other
// peers. This vector is ordered, to make lookups fast.
// if the torrent is started without metadata, it may
// still be given a name until the metadata is received
// once the metadata is received this field will no
// longer be used and will be reset
boost::scoped_ptr<std::string> m_name;
storage_constructor_type m_storage_constructor;
// the posix time this torrent was added and when
// it was completed. If the torrent isn't yet
// completed, m_completed_time is 0
time_t m_added_time;
time_t m_completed_time;
// this was the last time _we_ saw a seed in this swarm
time_t m_last_seen_complete;
// this is the time last any of our peers saw a seed
// in this swarm
time_t m_swarm_last_seen_complete;
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(123)">../include/libtorrent/torrent.hpp:1591</a></td><td>there's space for 1 bits here</td></tr><trid="123"style="display: none;"colspan="3"><tdcolspan="3"><h2>there's space for 1 bits here</h2><h4>../include/libtorrent/torrent.hpp:1591</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;">
// if this is true, libtorrent may pause and resume
// this torrent depending on queuing rules. Torrents
// started with auto_managed flag set may be added in
// a paused state in case there are no available
// slots.
bool m_auto_managed:1;
enum { no_gauge_state = 0xf };
// the current stats gauge this torrent counts against
boost::uint32_t m_current_gauge_state:4;
// set to true while moving the storage
bool m_moving_storage:1;
// this is true if this torrent is considered inactive from the
// queuing mechanism's point of view. If a torrent doesn't transfer
// at high enough rates, it's inactive.
bool m_inactive:1;
<divstyle="background: #ffff00"width="100%">
</div>// ----
// the scrape data from the tracker response, this
// is optional and may be 0xffffff
unsigned int m_downloaded:24;
// the number of seconds since the last scrape request to
// one of the trackers in this torrent
boost::uint64_t m_last_scrape:16;
// ----
// progress parts per million (the number of
// millionths of completeness)
unsigned int m_progress_ppm:20;
// the number of seconds this torrent has been under the inactive
// threshold in terms of sending and receiving data. When this counter
// reaches the settings.inactive_torrent_timeout it will be considered
// inactive and possibly open up another queue slot, to start another,
// queued, torrent. Every second it's above the threshold
boost::int16_t m_inactive_counter;
// if this is set, accept the save path saved in the resume data, if
// present
bool m_use_resume_save_path:1;
#if TORRENT_USE_ASSERTS
public:
// set to false until we've loaded resume data
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(124)">../include/libtorrent/torrent_info.hpp:124</a></td><td>include the number of peers received from this tracker, at last announce</td></tr><trid="124"style="display: none;"colspan="3"><tdcolspan="3"><h2>include the number of peers received from this tracker, at last announce</h2><h4>../include/libtorrent/torrent_info.hpp:124</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;">
// if this tracker failed the last time it was contacted
// this error code specifies what error occurred
error_code last_error;
// returns the number of seconds to the next announce on
// this tracker. ``min_announce_in()`` returns the number of seconds until we are
// allowed to force another tracker update with this tracker.
//
// If the last time this tracker was contacted failed, ``last_error`` is the error
// code describing what error occurred.
int next_announce_in() const;
int min_announce_in() const;
// the time of next tracker announce
ptime next_announce;
// no announces before this time
ptime min_announce;
<divstyle="background: #ffff00"width="100%">
</div> // 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).
// if this tracker has returned scrape data, these fields are filled
// in with valid numbers. Otherwise they are set to -1.
// the number of current downloaders
int scrape_incomplete;
int scrape_complete;
int scrape_downloaded;
// the tier this tracker belongs to
boost::uint8_t tier;
// the max number of failures to announce to this tracker in
// a row, before this tracker is not used anymore. 0 means unlimited
boost::uint8_t fail_limit;
// the number of times in a row we have failed to announce to this
// tracker.
boost::uint8_t fails:7;
// true while we're waiting for a response from the tracker.
bool updating:1;
// flags for the source bitmask, each indicating where
// we heard about this tracker
enum tracker_source
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(125)">../include/libtorrent/upnp.hpp:113</a></td><td>support using the windows API for UPnP operations as well</td></tr><trid="125"style="display: none;"colspan="3"><tdcolspan="3"><h2>support using the windows API for UPnP operations as well</h2><h4>../include/libtorrent/upnp.hpp:113</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> // specific port
// Attempts to add a port mapping for the specified protocol. Valid protocols are
// ``upnp::tcp`` and ``upnp::udp`` for the UPnP class and ``natpmp::tcp`` and
// ``natpmp::udp`` for the NAT-PMP class.
//
// ``external_port`` is the port on the external address that will be mapped. This
// is a hint, you are not guaranteed that this port will be available, and it may
// end up being something else. In the portmap_alert_ notification, the actual
// external port is reported.
//
// ``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
// mappings that fail with a -1 return value.
int add_mapping(protocol_type p, int external_port, int local_port);
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(126)">../include/libtorrent/utp_stream.hpp:391</a></td><td>implement blocking write. Low priority since it's not used (yet)</td></tr><trid="126"style="display: none;"colspan="3"><tdcolspan="3"><h2>implement blocking write. Low priority since it's not used (yet)</h2><h4>../include/libtorrent/utp_stream.hpp:391</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> for (typename Mutable_Buffers::const_iterator i = buffers.begin()
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(127)">../include/libtorrent/kademlia/item.hpp:61</a></td><td>since this is a public function, it should probably be moved out of this header and into one with other public functions.</td></tr><trid="127"style="display: none;"colspan="3"><tdcolspan="3"><h2>since this is a public function, it should probably be moved
out of this header and into one with other public functions.</h2><h4>../include/libtorrent/kademlia/item.hpp:61</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;">#include <boost/array.hpp>
namespace libtorrent { namespace dht
{
// calculate the target hash for an immutable item.
sha1_hash TORRENT_EXTRA_EXPORT item_target_id(
std::pair<char const*, int> v);
// calculate the target hash for a mutable item.
sha1_hash TORRENT_EXTRA_EXPORT item_target_id(std::pair<char const*, int> salt
, char const* pk);
bool TORRENT_EXTRA_EXPORT verify_mutable_item(
std::pair<char const*, int> v
, std::pair<char const*, int> salt
, boost::uint64_t seq
, char const* pk
, char const* sig);
<divstyle="background: #ffff00"width="100%">
</div>// 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.
void TORRENT_EXPORT sign_mutable_item(
std::pair<char const*, int> v
, std::pair<char const*, int> salt
, boost::uint64_t seq
, char const* pk
, char const* sk
, char* sig);
sha1_hash TORRENT_EXTRA_EXPORT mutable_item_cas(
std::pair<char const*, int> v
, std::pair<char const*, int> salt
, boost::uint64_t seq);
enum
{
item_pk_len = 32,
item_sk_len = 64,
item_sig_len = 64
};
class TORRENT_EXTRA_EXPORT item
{
public:
item() : m_seq(0), m_mutable(false) {}
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(128)">../include/libtorrent/aux_/session_impl.hpp:412</a></td><td>move the login info into the tracker_request object</td></tr><trid="128"style="display: none;"colspan="3"><tdcolspan="3"><h2>move the login info into the tracker_request object</h2><h4>../include/libtorrent/aux_/session_impl.hpp:412</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;">
void on_lsd_announce(error_code const& e);
// called when a port mapping is successful, or a router returns
// a failure to map a port
void on_port_mapping(int mapping, address const& ip, int port
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(129)">../include/libtorrent/aux_/session_impl.hpp:900</a></td><td>should this be renamed m_outgoing_interfaces?</td></tr><trid="129"style="display: none;"colspan="3"><tdcolspan="3"><h2>should this be renamed m_outgoing_interfaces?</h2><h4>../include/libtorrent/aux_/session_impl.hpp:900</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> // listen socket. For each retry the port number
// is incremented by one
int m_listen_port_retries;
// the addresses or device names of the interfaces we are supposed to
// listen on. if empty, it means that we should let the os decide
</pre></td></tr><trstyle="background: #ccc"><td>relevance 0</td><td><ahref="javascript:expand(130)">../include/libtorrent/aux_/session_interface.hpp:200</a></td><td>it would be nice to not have this be part of session_interface</td></tr><trid="130"style="display: none;"colspan="3"><tdcolspan="3"><h2>it would be nice to not have this be part of session_interface</h2><h4>../include/libtorrent/aux_/session_interface.hpp:200</h4><prestyle="background: #f6f6f6; border: solid 1px #ddd;"> virtual boost::uint16_t listen_port() const = 0;