merge RC_1_1 into master
This commit is contained in:
commit
6d85c7c5f0
|
@ -7,6 +7,7 @@
|
|||
|
||||
1.1.0 release
|
||||
|
||||
* support filtering which parts of session state are loaded by load_state()
|
||||
* deprecate support for adding torrents by HTTP URL
|
||||
* allow specifying which tracker to scrape in scrape_tracker
|
||||
* tracker response alerts from user initiated announces/scrapes are now
|
||||
|
@ -91,6 +92,8 @@
|
|||
* almost completely changed the storage interface (for custom storage)
|
||||
* added support for hashing pieces in multiple threads
|
||||
|
||||
* fix division by zero in super-seeding logic
|
||||
|
||||
1.0.9 release
|
||||
|
||||
* fix issue in checking outgoing interfaces (when that option is enabled)
|
||||
|
|
|
@ -510,18 +510,18 @@ namespace
|
|||
}
|
||||
#endif
|
||||
|
||||
void load_state(lt::session& ses, entry const& st)
|
||||
{
|
||||
allow_threading_guard guard;
|
||||
void load_state(lt::session& ses, entry const& st, boost::uint32_t flags)
|
||||
{
|
||||
allow_threading_guard guard;
|
||||
|
||||
std::vector<char> buf;
|
||||
bencode(std::back_inserter(buf), st);
|
||||
bdecode_node e;
|
||||
error_code ec;
|
||||
bdecode(&buf[0], &buf[0] + buf.size(), e, ec);
|
||||
TORRENT_ASSERT(!ec);
|
||||
ses.load_state(e);
|
||||
}
|
||||
std::vector<char> buf;
|
||||
bencode(std::back_inserter(buf), st);
|
||||
bdecode_node e;
|
||||
error_code ec;
|
||||
bdecode(&buf[0], &buf[0] + buf.size(), e, ec);
|
||||
TORRENT_ASSERT(!ec);
|
||||
ses.load_state(e, flags);
|
||||
}
|
||||
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
void dht_get_mutable_item(lt::session& ses, std::string key, std::string salt)
|
||||
|
@ -796,7 +796,7 @@ void bind_session()
|
|||
.def("get_pe_settings", allow_threads(<::session::get_pe_settings))
|
||||
#endif
|
||||
#endif
|
||||
.def("load_state", &load_state)
|
||||
.def("load_state", &load_state, (arg("entry"), arg("flags") = 0xffffffff))
|
||||
.def("save_state", &save_state, (arg("entry"), arg("flags") = 0xffffffff))
|
||||
.def("pop_alerts", &pop_alerts)
|
||||
.def("wait_for_alert", &wait_for_alert
|
||||
|
@ -885,8 +885,8 @@ void bind_session()
|
|||
.value("save_dht_settings", lt::session::save_dht_settings)
|
||||
.value("save_dht_state", lt::session::save_dht_state)
|
||||
.value("save_encryption_settings", lt::session:: save_encryption_settings)
|
||||
.value("save_as_map", lt::session::save_as_map)
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
.value("save_as_map", lt::session::save_as_map)
|
||||
.value("save_i2p_proxy", lt::session::save_i2p_proxy)
|
||||
.value("save_proxy", lt::session::save_proxy)
|
||||
.value("save_dht_proxy", lt::session::save_dht_proxy)
|
||||
|
|
|
@ -31,7 +31,8 @@ class test_alerts(unittest.TestCase):
|
|||
ses = lt.session({'alert_mask': lt.alert.category_t.all_categories})
|
||||
shutil.copy(os.path.join('..', '..', 'test', 'test_torrents', 'base.torrent'), '.')
|
||||
ti = lt.torrent_info('base.torrent');
|
||||
h = ses.add_torrent({'ti': ti, 'save_path': '.'})
|
||||
h = ses.add_torrent({'ti': ti, 'save_path': os.getcwd()})
|
||||
st = h.status()
|
||||
time.sleep(1)
|
||||
ses.remove_torrent(h)
|
||||
ses.wait_for_alert(1000) # milliseconds
|
||||
|
@ -39,9 +40,8 @@ class test_alerts(unittest.TestCase):
|
|||
for a in alerts:
|
||||
print(a.message())
|
||||
|
||||
st = h.status()
|
||||
print(st.next_announce)
|
||||
print(st.name)
|
||||
self.assertEqual(st.name, 'temp')
|
||||
print(st.errc.message())
|
||||
print(st.pieces)
|
||||
print(st.last_seen_complete)
|
||||
|
@ -51,6 +51,7 @@ class test_alerts(unittest.TestCase):
|
|||
print(st.distributed_copies)
|
||||
print(st.paused)
|
||||
print(st.info_hash)
|
||||
self.assertEqual(st.save_path, os.getcwd())
|
||||
|
||||
class test_bencoder(unittest.TestCase):
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
* tutorial_
|
||||
* examples_
|
||||
* overview_
|
||||
* `reference documentation`_
|
||||
* documentation_
|
||||
* contributing_
|
||||
* building_
|
||||
* troubleshooting_
|
||||
|
@ -41,8 +41,10 @@ Extensions
|
|||
|
||||
Bindings
|
||||
|
||||
* `ruby bindings`_
|
||||
* `python bindings`_
|
||||
* python_
|
||||
* java_
|
||||
* go_
|
||||
* node_
|
||||
|
||||
--------
|
||||
|
||||
|
@ -64,7 +66,7 @@ libtorrent
|
|||
.. _building: building.html
|
||||
.. _examples: examples.html
|
||||
.. _overview: manual-ref.html
|
||||
.. _`reference documentation`: reference.html
|
||||
.. _documentation: reference.html
|
||||
.. _troubleshooting: troubleshooting.html
|
||||
.. _`tuning`: tuning.html
|
||||
.. _screenshot: client_test.png
|
||||
|
@ -85,8 +87,10 @@ libtorrent
|
|||
.. _`github page`: https://github.com/arvidn/libtorrent
|
||||
.. _blog: http://blog.libtorrent.org
|
||||
|
||||
.. _`ruby bindings`: http://libtorrent-ruby.rubyforge.org/
|
||||
.. _`python bindings`: python_binding.html
|
||||
.. _java: https://github.com/frostwire/frostwire-jlibtorrent/
|
||||
.. _python: python_binding.html
|
||||
.. _go: https://github.com/steeve/libtorrent-go
|
||||
.. _node: https://github.com/fanatid/node-libtorrent
|
||||
|
||||
.. _`Introduction, slides`: bittorrent.pdf
|
||||
|
||||
|
@ -104,22 +108,46 @@ The main goals of libtorrent are:
|
|||
* to be memory efficient
|
||||
* to be very easy to use
|
||||
|
||||
Donate
|
||||
======
|
||||
Getting started
|
||||
===============
|
||||
|
||||
Support the development of libtorrent
|
||||
The tutorial_ is an introduction to using libtorrent (C++). Also see the
|
||||
`reference documentation`_.
|
||||
|
||||
.. _`reference documentation`: reference.html
|
||||
|
||||
Contribute
|
||||
==========
|
||||
|
||||
If your organization use libtorrent, please consider supporting its development.
|
||||
See the contribute_ page for other ways to help out.
|
||||
|
||||
.. raw:: html
|
||||
|
||||
|
||||
<span style="display:inline-block">
|
||||
<a class="FlattrButton" style="display:none;" href="http://libtorrent.org"></a>
|
||||
<noscript><a href="https://flattr.com/thing/95662/libtorrent" target="_blank">
|
||||
<img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" /></a></noscript>
|
||||
</span>
|
||||
|
||||
<span style="display:inline-block">
|
||||
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top">
|
||||
<input type="hidden" name="cmd" value="_donations">
|
||||
<input type="hidden" name="business" value="ZNR45WU2PP5W2">
|
||||
<input type="hidden" name="lc" value="US">
|
||||
<input type="hidden" name="item_name" value="libtorrent">
|
||||
<input type="hidden" name="currency_code" value="USD">
|
||||
<input type="hidden" name="bn" value="PP-DonationsBF:btn_donate_LG.gif:NonHosted">
|
||||
<input type="image" src="https://www.paypalobjects.com/webstatic/en_US/i/buttons/pp-acceptance-medium.png" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!">
|
||||
<img alt="" border="0" src="https://www.paypalobjects.com/en_US/i/scr/pixel.gif" width="1" height="1">
|
||||
</form>
|
||||
</span>
|
||||
|
||||
|
||||
Feedback
|
||||
========
|
||||
Support
|
||||
=======
|
||||
|
||||
There's a `mailing list`__, general libtorrent discussion.
|
||||
Please direct questions to the `mailing list`__, general libtorrent discussion.
|
||||
|
||||
__ http://lists.sourceforge.net/lists/listinfo/libtorrent-discuss
|
||||
|
||||
|
|
|
@ -223,13 +223,13 @@ div.contents {
|
|||
|
||||
#librarySidebar {
|
||||
float: left;
|
||||
width: 150px;
|
||||
width: 170px;
|
||||
}
|
||||
|
||||
#libraryBody {
|
||||
border-left: solid 1px #eee;
|
||||
padding-left: 10px;
|
||||
margin-left: 158px;
|
||||
margin-left: 178px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
|
|
|
@ -52,10 +52,10 @@ First, let's extend the example to print out messages from the bittorrent engine
|
|||
about progress and events happening under the hood. libtorrent has a mechanism
|
||||
referred to as *alerts* to communicate back information to the client application.
|
||||
|
||||
Clients can poll libtorrents for new alerts via the `pop_alerts()`_ call on the
|
||||
session object. This call fills in a vector of alert pointers with all new
|
||||
alerts since the last call to this function. The pointers are owned by the
|
||||
session object at will become invalidated by the next call to `pop_alerts()`_.
|
||||
Clients can poll a session for new alerts via the `pop_alerts()`_ call. This
|
||||
function fills in a vector of alert pointers with all new alerts since the last
|
||||
call to this function. The pointers are owned by the session object at will
|
||||
become invalidated by the next call to `pop_alerts()`_.
|
||||
|
||||
The alerts form a class hierarchy with alert_ as the root class. Each specific
|
||||
kind of alert may include additional state, specific to the kind of message. All
|
||||
|
@ -183,10 +183,10 @@ resuming torrents
|
|||
|
||||
Since bittorrent downloads pieces of files in random order, it's not trivial to
|
||||
resume a partial download. When resuming a download, the bittorrent engine must
|
||||
restore the state of the downloading torrent, specifically, which parts of the
|
||||
restore the state of the downloading torrent, specifically which parts of the
|
||||
file(s) are downloaded. There are two approaches to doing this:
|
||||
|
||||
1. read every piece of the downloaded files from disk and compare it against the
|
||||
1. read every piece of the downloaded files from disk and compare it against its
|
||||
expected hash.
|
||||
2. save to disk the state of which pieces (and partial pieces) are downloaded,
|
||||
and load it back in again when resuming.
|
||||
|
@ -197,8 +197,14 @@ employ (1) by default.
|
|||
To save resume data, call `save_resume_data()`_ on the torrent_handle_ object.
|
||||
This will ask libtorrent to generate the resume data and post it back in
|
||||
a save_resume_data_alert_. If generating the resume data fails for any reason,
|
||||
a save_resume_data_failed_alert_ is posted instead. Exactly one of those alerts
|
||||
will be posted for every call to `save_resume_data()`_.
|
||||
a save_resume_data_failed_alert_ is posted instead.
|
||||
|
||||
Exactly one of those alerts will be posted for every call to
|
||||
`save_resume_data()`_. This is an important property when shutting down a
|
||||
session with multiple torrents, every resume alert must be handled before
|
||||
resuming with shut down. Any torrent may fail to save resume data, so the client
|
||||
would need to keep a count of the outstanding resume files, decremented on
|
||||
either save_resume_data_alert_ or save_resume_data_failed_alert_.
|
||||
|
||||
The save_resume_data_alert_ looks something like this:
|
||||
|
||||
|
@ -212,10 +218,13 @@ The save_resume_data_alert_ looks something like this:
|
|||
boost::shared_ptr<entry> resume_data;
|
||||
};
|
||||
|
||||
``resume_data`` points to an entry_ object. This represents a node or a tree
|
||||
of nodes in a bencoded_ structure, which is the native encoding scheme in
|
||||
``resume_data`` points to an entry_ object. This represents a node or a tree of
|
||||
nodes in a bencoded_ structure, which is the native encoding scheme in
|
||||
bittorrent. It can be encoded into a byte buffer or file using `bencode()`_.
|
||||
|
||||
When adding a torrent with resume data, set the `add_torrent_params::resume_data`_
|
||||
to contain the bencoded buffer of the resume data.
|
||||
|
||||
example
|
||||
-------
|
||||
|
||||
|
@ -230,6 +239,41 @@ Here's an updated version of the above example with the following updates:
|
|||
:tab-width: 2
|
||||
:start-after: */
|
||||
|
||||
torrent files
|
||||
-------------
|
||||
|
||||
To add torrent files to a session (as opposed to a magnet link), it must first
|
||||
be loaded into a torrent_info_ object.
|
||||
|
||||
The torrent_info_ object can be created either by filename a buffer or a
|
||||
bencoded structure. When adding by filename, there's a sanity check limit on the
|
||||
size of the file, for adding arbitrarily large torrents, load the file outside
|
||||
of the constructor.
|
||||
|
||||
The torrent_info_ object provides an opportunity to query information about the
|
||||
.torrent file as well as mutating it before adding it to the session.
|
||||
|
||||
bencoding
|
||||
---------
|
||||
|
||||
bencoded_ structures is the default data storage format used by bittorrent, such
|
||||
as .torrent files, tracker announce and scrape responses and some wire protocol
|
||||
extensions. libtorrent provides an efficient framework for decoding bencoded
|
||||
data through `bdecode()`_ function.
|
||||
|
||||
There are two separate mechanisms for *encoding* and *decoding*. When decoding,
|
||||
use the `bdecode()`_ function that returns a bdecode_node_. When encoding, use
|
||||
`bencode()`_ taking an entry_ object.
|
||||
|
||||
The key property of `bdecode()`_ is that it does not copy any data out of the
|
||||
buffer that was parsed. It builds the tree structures of references pointing
|
||||
into the buffer. The buffer must stay alive and valid for as long as the
|
||||
bdecode_node_ is in use.
|
||||
|
||||
For performance details on `bdecode()`_, see the `blog post about it`__.
|
||||
|
||||
__ http://blog.libtorrent.org/2015/03/bdecode-parsers/
|
||||
|
||||
.. _session: reference-Core.html#session
|
||||
.. _session_handle: reference-Core.html#session_handle
|
||||
.. _add_torrent_params: reference-Core.html#add_torrent_params
|
||||
|
@ -258,4 +302,9 @@ Here's an updated version of the above example with the following updates:
|
|||
.. _bencoded: https://en.wikipedia.org/wiki/Bencode
|
||||
.. _entry: reference-Bencoding.html#entry
|
||||
.. _`bencode()`: reference-Bencoding.html#bencode()
|
||||
.. _torrent_info: reference-Core.html#torrent_info
|
||||
.. _`add_torrent_params::resume_data`: reference-Core.html#resume_data
|
||||
.. _`bdecode()`: reference-Bdecoding.html#bdecode()
|
||||
.. _bdecode_node: reference-Bdecoding.html#bdecode-node
|
||||
|
||||
|
||||
|
|
|
@ -43,12 +43,12 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <libtorrent/torrent_status.hpp>
|
||||
|
||||
namespace lt = libtorrent;
|
||||
using clock_t = std::chrono::monotonic_clock;
|
||||
|
||||
// return the name of a torrent status enum
|
||||
char const* state(lt::torrent_status::state_t s)
|
||||
{
|
||||
switch(s)
|
||||
{
|
||||
switch(s) {
|
||||
case lt::torrent_status::checking_files: return "checking";
|
||||
case lt::torrent_status::downloading_metadata: return "dl metadata";
|
||||
case lt::torrent_status::downloading: return "downloading";
|
||||
|
@ -74,8 +74,8 @@ int main(int argc, char const* argv[])
|
|||
| lt::alert::status_notification);
|
||||
|
||||
lt::session ses(pack);
|
||||
|
||||
lt::add_torrent_params atp;
|
||||
std::chrono::time_point last_save_resume = clock_t::now();
|
||||
|
||||
// load resume data from disk and pass it in as we add the magnet link
|
||||
std::ifstream ifs(".resume_file", std::ios_base::binary);
|
||||
|
@ -134,9 +134,15 @@ int main(int argc, char const* argv[])
|
|||
// state output for the torrent
|
||||
ses.post_torrent_updates();
|
||||
|
||||
// TODO: 3 call save_resume_data() once every 30 seconds or so
|
||||
// save resume data once every 30 seconds
|
||||
if (clock_t::now() - last_save_resume > seconds(30)) {
|
||||
h.save_resume_data();
|
||||
}
|
||||
}
|
||||
done:
|
||||
|
||||
// TODO: ideally we should save resume data here
|
||||
|
||||
done:
|
||||
std::cout << "\ndone, shutting down" << std::endl;
|
||||
}
|
||||
|
||||
|
|
|
@ -377,9 +377,13 @@ FILE* g_log_file = 0;
|
|||
|
||||
std::string const& piece_bar(libtorrent::bitfield const& p, int width)
|
||||
{
|
||||
const int table_size = 18;
|
||||
#ifdef _WIN32
|
||||
int const table_size = 2;
|
||||
#else
|
||||
int const table_size = 18;
|
||||
#endif
|
||||
|
||||
double piece_per_char = p.size() / double(width);
|
||||
double const piece_per_char = p.size() / double(width);
|
||||
static std::string bar;
|
||||
bar.clear();
|
||||
bar.reserve(width * 6);
|
||||
|
@ -401,9 +405,13 @@ std::string const& piece_bar(libtorrent::bitfield const& p, int width)
|
|||
for (int k = int(piece); k < end; ++k, ++num_pieces)
|
||||
if (p[k]) ++num_have;
|
||||
int color = int(std::ceil(num_have / float((std::max)(num_pieces, 1)) * (table_size - 1)));
|
||||
char buf[10];
|
||||
snprintf(buf, 10, "48;5;%d", 232 + color);
|
||||
bar += esc(buf);
|
||||
char buf[40];
|
||||
#ifdef _WIN32
|
||||
snprintf(buf, sizeof(buf), "\x1b[4%dm", color ? 7 : 0);
|
||||
#else
|
||||
snprintf(buf, sizeof(buf), "\x1b[48;5;%dm", 232 + color);
|
||||
#endif
|
||||
bar += buf;
|
||||
bar += " ";
|
||||
}
|
||||
bar += esc("0");
|
||||
|
@ -597,6 +605,7 @@ std::string monitor_dir;
|
|||
int poll_interval = 5;
|
||||
int max_connections_per_torrent = 50;
|
||||
bool seed_mode = false;
|
||||
int cache_size = 1024;
|
||||
|
||||
bool share_mode = false;
|
||||
bool disable_storage = false;
|
||||
|
@ -1295,6 +1304,7 @@ int main(int argc, char* argv[])
|
|||
namespace lt = libtorrent;
|
||||
|
||||
settings_pack settings;
|
||||
settings.set_int(settings_pack::cache_size, cache_size);
|
||||
settings.set_int(settings_pack::active_loaded_limit, 20);
|
||||
settings.set_int(settings_pack::choking_algorithm, settings_pack::rate_based_choker);
|
||||
|
||||
|
@ -1446,9 +1456,9 @@ int main(int argc, char* argv[])
|
|||
}
|
||||
#endif // TORRENT_USE_I2P
|
||||
case 'C':
|
||||
settings.set_int(settings_pack::cache_size, atoi(arg));
|
||||
settings.set_bool(settings_pack::use_read_cache, atoi(arg) > 0);
|
||||
settings.set_int(settings_pack::cache_buffer_chunk_size, atoi(arg) / 100);
|
||||
cache_size = atoi(arg);
|
||||
settings.set_int(settings_pack::cache_size, cache_size);
|
||||
settings.set_int(settings_pack::cache_buffer_chunk_size, 0);
|
||||
break;
|
||||
case 'A': settings.set_int(settings_pack::allowed_fast_set_size, atoi(arg)); break;
|
||||
case 'R': settings.set_int(settings_pack::read_cache_line_size, atoi(arg)); break;
|
||||
|
@ -1564,6 +1574,9 @@ int main(int argc, char* argv[])
|
|||
}
|
||||
|
||||
ses.set_ip_filter(loaded_ip_filter);
|
||||
ses.set_load_function(&load_torrent);
|
||||
|
||||
error_code ec;
|
||||
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
dht_settings dht;
|
||||
|
@ -1581,18 +1594,15 @@ int main(int argc, char* argv[])
|
|||
ses.add_dht_router(std::make_pair(
|
||||
std::string("router.bitcomet.com"), 6881));
|
||||
}
|
||||
#endif
|
||||
|
||||
ses.set_load_function(&load_torrent);
|
||||
|
||||
std::vector<char> in;
|
||||
error_code ec;
|
||||
if (load_file(".ses_state", in, ec) == 0)
|
||||
{
|
||||
bdecode_node e;
|
||||
if (bdecode(&in[0], &in[0] + in.size(), e, ec) == 0)
|
||||
ses.load_state(e);
|
||||
ses.load_state(e, session::save_dht_state);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (std::vector<add_torrent_params>::iterator i = magnet_links.begin()
|
||||
, end(magnet_links.end()); i != end; ++i)
|
||||
|
@ -1926,6 +1936,13 @@ int main(int argc, char* argv[])
|
|||
if (c == '5') print_peer_rate = !print_peer_rate;
|
||||
if (c == '6') print_fails = !print_fails;
|
||||
if (c == '7') print_send_bufs = !print_send_bufs;
|
||||
if (c == 'C')
|
||||
{
|
||||
cache_size = (cache_size == 0) ? -1 : 0;
|
||||
settings_pack p;
|
||||
p.set_int(settings_pack::cache_size, cache_size);
|
||||
ses.apply_settings(p);
|
||||
}
|
||||
if (c == 'h')
|
||||
{
|
||||
clear_screen();
|
||||
|
@ -1936,7 +1953,7 @@ int main(int argc, char* argv[])
|
|||
"[q] quit client [m] add magnet link\n"
|
||||
"\n"
|
||||
"TORRENT ACTIONS\n"
|
||||
"[p] pause/unpause selected torrent\n"
|
||||
"[p] pause/unpause selected torrent [C] toggle disk cache\n"
|
||||
"[s] toggle sequential download [j] force recheck\n"
|
||||
"[space] toggle session pause [c] clear error\n"
|
||||
"[v] scrape [D] delete torrent and data\n"
|
||||
|
@ -2290,11 +2307,6 @@ int main(int argc, char* argv[])
|
|||
}
|
||||
}
|
||||
|
||||
// keep track of the number of resume data
|
||||
// alerts to wait for
|
||||
int num_paused = 0;
|
||||
int num_failed = 0;
|
||||
|
||||
ses.pause();
|
||||
printf("saving resume data\n");
|
||||
std::vector<torrent_status> temp;
|
||||
|
@ -2337,51 +2349,29 @@ int main(int argc, char* argv[])
|
|||
for (std::vector<alert*>::iterator i = alerts.begin()
|
||||
, end(alerts.end()); i != end; ++i)
|
||||
{
|
||||
torrent_paused_alert* tp = alert_cast<torrent_paused_alert>(*i);
|
||||
if (tp)
|
||||
if (!::handle_alert(ses, *i, files, non_files))
|
||||
{
|
||||
++num_paused;
|
||||
printf("\rleft: %d failed: %d pause: %d "
|
||||
, num_outstanding_resume_data, num_failed, num_paused);
|
||||
continue;
|
||||
// if we didn't handle the alert, print it to the log
|
||||
std::string event_string;
|
||||
print_alert(*i, event_string);
|
||||
}
|
||||
|
||||
if (alert_cast<save_resume_data_failed_alert>(*i))
|
||||
{
|
||||
++num_failed;
|
||||
--num_outstanding_resume_data;
|
||||
printf("\rleft: %d failed: %d pause: %d "
|
||||
, num_outstanding_resume_data, num_failed, num_paused);
|
||||
continue;
|
||||
}
|
||||
|
||||
save_resume_data_alert* rd = alert_cast<save_resume_data_alert>(*i);
|
||||
if (!rd) continue;
|
||||
--num_outstanding_resume_data;
|
||||
printf("\rleft: %d failed: %d pause: %d "
|
||||
, num_outstanding_resume_data, num_failed, num_paused);
|
||||
|
||||
if (!rd->resume_data) continue;
|
||||
|
||||
torrent_handle h = rd->handle;
|
||||
torrent_status st = h.status(torrent_handle::query_save_path);
|
||||
std::vector<char> out;
|
||||
bencode(std::back_inserter(out), *rd->resume_data);
|
||||
save_file(path_append(st.save_path, path_append(".resume"
|
||||
, leaf_path(hash_to_filename[st.info_hash]) + ".resume")), out);
|
||||
}
|
||||
}
|
||||
|
||||
if (g_log_file) fclose(g_log_file);
|
||||
|
||||
// we're just saving the DHT state
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
printf("\nsaving session state\n");
|
||||
{
|
||||
entry session_state;
|
||||
ses.save_state(session_state);
|
||||
ses.save_state(session_state, session::save_dht_state);
|
||||
|
||||
std::vector<char> out;
|
||||
bencode(std::back_inserter(out), session_state);
|
||||
save_file(".ses_state", out);
|
||||
}
|
||||
#endif
|
||||
|
||||
printf("closing session");
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ std::string const& progress_bar(int progress, int width, color_code c
|
|||
bar.clear();
|
||||
bar.reserve(size_t(width + 10));
|
||||
|
||||
int progress_chars = (progress * width + 500) / 1000;
|
||||
int const progress_chars = (progress * width + 500) / 1000;
|
||||
|
||||
if (caption.empty())
|
||||
{
|
||||
|
@ -108,14 +108,21 @@ std::string const& progress_bar(int progress, int width, color_code c
|
|||
|
||||
caption.resize(size_t(width), ' ');
|
||||
|
||||
#ifdef _WIN32
|
||||
char const* background = "40";
|
||||
#else
|
||||
char const* background = "48;5;238";
|
||||
#endif
|
||||
|
||||
char str[256];
|
||||
if (flags & progress_invert)
|
||||
snprintf(str, sizeof(str), "\x1b[48;5;238m\x1b[37m%s\x1b[4%d;3%dm%s\x1b[49;39m"
|
||||
, caption.substr(0, progress_chars).c_str(), c, tc
|
||||
snprintf(str, sizeof(str), "\x1b[%sm\x1b[37m%s\x1b[4%d;3%dm%s\x1b[49;39m"
|
||||
, background, caption.substr(0, progress_chars).c_str(), c, tc
|
||||
, caption.substr(progress_chars).c_str());
|
||||
else
|
||||
snprintf(str, sizeof(str), "\x1b[4%d;3%dm%s\x1b[48;5;238m\x1b[37m%s\x1b[49;39m"
|
||||
, c, tc, caption.substr(0, progress_chars).c_str(), caption.substr(progress_chars).c_str());
|
||||
snprintf(str, sizeof(str), "\x1b[4%d;3%dm%s\x1b[%sm\x1b[37m%s\x1b[49;39m"
|
||||
, c, tc, caption.substr(0, progress_chars).c_str(), background
|
||||
, caption.substr(progress_chars).c_str());
|
||||
bar = str;
|
||||
}
|
||||
return bar;
|
||||
|
@ -208,7 +215,7 @@ void terminal_size(int* terminal_width, int* terminal_height)
|
|||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
void apply_ansi_code(int* attributes, bool* reverse, int code)
|
||||
void apply_ansi_code(int* attributes, bool* reverse, bool* support_chaining, int code)
|
||||
{
|
||||
static const int color_table[8] =
|
||||
{
|
||||
|
@ -224,8 +231,8 @@ void apply_ansi_code(int* attributes, bool* reverse, int code)
|
|||
|
||||
enum
|
||||
{
|
||||
foreground_mask = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
|
||||
background_mask = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE
|
||||
foreground_mask = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
|
||||
background_mask = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY
|
||||
};
|
||||
|
||||
static const int fg_mask[2] = {foreground_mask, background_mask};
|
||||
|
@ -233,14 +240,29 @@ void apply_ansi_code(int* attributes, bool* reverse, int code)
|
|||
static const int fg_shift[2] = { 0, 4};
|
||||
static const int bg_shift[2] = { 4, 0};
|
||||
|
||||
// default foreground
|
||||
if (code == 39) code = 37;
|
||||
|
||||
// default background
|
||||
if (code == 49) code = 40;
|
||||
|
||||
if (code == 0)
|
||||
{
|
||||
// reset
|
||||
*attributes = color_table[7];
|
||||
*reverse = false;
|
||||
*support_chaining = true;
|
||||
}
|
||||
else if (code == 1)
|
||||
{
|
||||
// intensity
|
||||
*attributes |= *reverse ? BACKGROUND_INTENSITY : FOREGROUND_INTENSITY;
|
||||
*support_chaining = true;
|
||||
}
|
||||
else if (code == 7)
|
||||
{
|
||||
// reverse video
|
||||
*support_chaining = true;
|
||||
if (*reverse) return;
|
||||
*reverse = true;
|
||||
int fg_col = *attributes & foreground_mask;
|
||||
|
@ -254,12 +276,14 @@ void apply_ansi_code(int* attributes, bool* reverse, int code)
|
|||
// foreground color
|
||||
*attributes &= ~fg_mask[*reverse];
|
||||
*attributes |= color_table[code - 30] << fg_shift[*reverse];
|
||||
*support_chaining = true;
|
||||
}
|
||||
else if (code >= 40 && code <= 47)
|
||||
{
|
||||
// foreground color
|
||||
// background color
|
||||
*attributes &= ~bg_mask[*reverse];
|
||||
*attributes |= color_table[code - 40] << bg_shift[*reverse];
|
||||
*support_chaining = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -288,14 +312,15 @@ void print(char const* buf)
|
|||
CONSOLE_SCREEN_BUFFER_INFO sbi;
|
||||
if (GetConsoleScreenBufferInfo(out, &sbi))
|
||||
{
|
||||
COORD pos = sbi.dwCursorPosition;
|
||||
int width = sbi.dwSize.X;
|
||||
int run = width - pos.X;
|
||||
COORD const pos = sbi.dwCursorPosition;
|
||||
int const width = sbi.dwSize.X;
|
||||
int const run = width - pos.X;
|
||||
DWORD n;
|
||||
FillConsoleOutputAttribute(out, 0x7, run, pos, &n);
|
||||
FillConsoleOutputCharacter(out, ' ', run, pos, &n);
|
||||
}
|
||||
++buf;
|
||||
start = buf;
|
||||
continue;
|
||||
}
|
||||
else if (*start == 'J')
|
||||
|
@ -312,18 +337,30 @@ void print(char const* buf)
|
|||
FillConsoleOutputCharacter(out, ' ', run, pos, &n);
|
||||
}
|
||||
++buf;
|
||||
start = buf;
|
||||
continue;
|
||||
}
|
||||
one_more:
|
||||
one_more:
|
||||
while (*buf != 'm' && *buf != ';' && *buf != 0) ++buf;
|
||||
|
||||
// this is where we handle reset, color and reverse codes
|
||||
if (*buf == 0) break;
|
||||
int code = atoi(start);
|
||||
apply_ansi_code(¤t_attributes, &reverse, code);
|
||||
if (*buf == ';')
|
||||
bool support_chaining = false;
|
||||
apply_ansi_code(¤t_attributes, &reverse, &support_chaining, code);
|
||||
if (support_chaining)
|
||||
{
|
||||
++buf;
|
||||
start = buf;
|
||||
goto one_more;
|
||||
if (*buf == ';')
|
||||
{
|
||||
++buf;
|
||||
start = buf;
|
||||
goto one_more;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// ignore codes with multiple fields for now
|
||||
while (*buf != 'm' && *buf != 0) ++buf;
|
||||
}
|
||||
SetConsoleTextAttribute(out, current_attributes);
|
||||
++buf; // skip 'm'
|
||||
|
|
|
@ -96,7 +96,11 @@ void session_view::render()
|
|||
snprintf(str, sizeof(str), "%s%swaste: %s up: %s (%s) "
|
||||
"disk queue: %s | %s cache w: %3d%% r: %3d%% "
|
||||
"size: w: %s r: %s total: %s %s\x1b[K"
|
||||
#ifdef _WIN32
|
||||
, esc("40")
|
||||
#else
|
||||
, esc("48;5;238")
|
||||
#endif
|
||||
, esc("1")
|
||||
, add_suffix(m_cnt[0][m_wasted_bytes_idx]).c_str()
|
||||
, color(add_suffix(upload_rate, "/s"), col_red).c_str()
|
||||
|
|
|
@ -77,25 +77,12 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/time.hpp"
|
||||
#include "libtorrent/config.hpp"
|
||||
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
#ifndef BOOST_NO_TYPEID
|
||||
#include <typeinfo>
|
||||
#endif
|
||||
#endif // TORRENT_NO_DEPRECATE
|
||||
|
||||
#ifndef TORRENT_MAX_ALERT_TYPES
|
||||
#define TORRENT_MAX_ALERT_TYPES 15
|
||||
#endif
|
||||
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
#ifndef BOOST_NO_TYPEID
|
||||
#include <typeinfo>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace libtorrent {
|
||||
|
||||
// The ``alert`` class is the base class that specific messages are derived from.
|
||||
// alert types are not copyable, and cannot be constructed by the client. The
|
||||
// pointers returned by libtorrent are short lived (the details are described
|
||||
// under session_handle::pop_alerts())
|
||||
class TORRENT_EXPORT alert
|
||||
{
|
||||
public:
|
||||
|
@ -216,9 +203,6 @@ namespace libtorrent {
|
|||
alert();
|
||||
// hidden
|
||||
virtual ~alert();
|
||||
#if __cplusplus >= 201103L
|
||||
alert(alert const&) = default;
|
||||
#endif
|
||||
|
||||
// a timestamp is automatically created in the constructor
|
||||
time_point timestamp() const;
|
||||
|
@ -301,8 +285,15 @@ namespace libtorrent {
|
|||
|
||||
#endif // TORRENT_NO_DEPRECATE
|
||||
|
||||
protected:
|
||||
// the alert is not copyable (but for backwards compatibility reasons it
|
||||
// retains the ability to clone itself, for now).
|
||||
#if __cplusplus >= 201103L
|
||||
alert(alert const& rhs) = default;
|
||||
#endif
|
||||
|
||||
private:
|
||||
// explicitly disallow assignment, to silence msvc warning
|
||||
// explicitly disallow assignment and copyconstruction
|
||||
alert& operator=(alert const&);
|
||||
|
||||
time_point m_timestamp;
|
||||
|
|
|
@ -163,7 +163,25 @@ namespace libtorrent
|
|||
#define TORRENT_CLONE(name)
|
||||
#endif
|
||||
|
||||
// we can only use = default in C++11
|
||||
// the purpose of this is just to make all alert types non-copyable from user
|
||||
// code. The heterogeneous queue does not yet have an emplace_back(), so it
|
||||
// still needs to copy alerts, but the important part is that it's not
|
||||
// copyable for clients.
|
||||
// TODO: Once the backwards compatibility of clone() is removed, and once
|
||||
// C++11 is required, this can be simplified to just say = delete
|
||||
#if __cplusplus >= 201103L
|
||||
#define TORRENT_PROTECTED_CCTOR(name) \
|
||||
protected: \
|
||||
template <class T> friend struct heterogeneous_queue; \
|
||||
name(name const&) = default; \
|
||||
public:
|
||||
#else
|
||||
#define TORRENT_PROTECTED_CCTOR(name)
|
||||
#endif
|
||||
|
||||
#define TORRENT_DEFINE_ALERT_IMPL(name, seq, prio) \
|
||||
TORRENT_PROTECTED_CCTOR(name) \
|
||||
static const int priority = prio; \
|
||||
static const int alert_type = seq; \
|
||||
virtual int type() const TORRENT_OVERRIDE { return alert_type; } \
|
||||
|
|
|
@ -345,6 +345,7 @@ namespace libtorrent
|
|||
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
entry dht_state() const;
|
||||
void start_dht_deprecated(entry const& startup_state);
|
||||
#endif
|
||||
void on_dht_announce(error_code const& e);
|
||||
void on_dht_name_lookup(error_code const& e
|
||||
|
@ -512,7 +513,7 @@ namespace libtorrent
|
|||
void announce_lsd(sha1_hash const& ih, int port, bool broadcast = false) TORRENT_OVERRIDE;
|
||||
|
||||
void save_state(entry* e, boost::uint32_t flags) const;
|
||||
void load_state(bdecode_node const* e);
|
||||
void load_state(bdecode_node const* e, boost::uint32_t flags);
|
||||
|
||||
bool has_connection(peer_connection* p) const TORRENT_OVERRIDE;
|
||||
void insert_peer(boost::shared_ptr<peer_connection> const& c) TORRENT_OVERRIDE;
|
||||
|
|
|
@ -136,7 +136,11 @@ namespace libtorrent
|
|||
in_progress = 0x20,
|
||||
|
||||
// turns into file::coalesce_buffers in the file operation
|
||||
coalesce_buffers = 0x40
|
||||
coalesce_buffers = 0x40,
|
||||
|
||||
// the disk cache was enabled when this job was issued, it should use
|
||||
// the disk cache once it's handled by a disk thread
|
||||
use_disk_cache = 0x80
|
||||
};
|
||||
|
||||
// for write jobs, returns true if its block
|
||||
|
|
|
@ -229,7 +229,7 @@ namespace libtorrent
|
|||
// The const version of ``operator[]`` will only return a reference to an
|
||||
// existing element at the given key. If the key is not found, it will
|
||||
// throw ``libtorrent::type_error``.
|
||||
entry& operator[](char const* key);
|
||||
entry& operator[](char const* key);
|
||||
entry& operator[](std::string const& key);
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
const entry& operator[](char const* key) const;
|
||||
|
@ -290,7 +290,7 @@ namespace libtorrent
|
|||
|
||||
public:
|
||||
// in debug mode this is set to false by bdecode to indicate that the
|
||||
// program has not yet queried the type of this entry, and sould not
|
||||
// program has not yet queried the type of this entry, and should not
|
||||
// assume that it has a certain type. This is asserted in the accessor
|
||||
// functions. This does not apply if exceptions are used.
|
||||
mutable boost::uint8_t m_type_queried:1;
|
||||
|
|
|
@ -90,7 +90,7 @@ struct key_desc_t
|
|||
// generate an error response message
|
||||
void TORRENT_EXPORT incoming_error(entry& e, char const* msg, int error_code = 203);
|
||||
|
||||
// given a redundent name to avoid clashing with libtorrent::detail
|
||||
// given a redundant name to avoid clashing with libtorrent::detail
|
||||
namespace dht_detail {
|
||||
|
||||
bool TORRENT_EXPORT verify_message(bdecode_node const& msg, key_desc_t const desc[]
|
||||
|
|
|
@ -89,7 +89,7 @@ namespace libtorrent
|
|||
// a call related to bittorrent protocol encryption failed
|
||||
op_encryption,
|
||||
|
||||
// an attempt to connect a socket failed
|
||||
// an attempt to connect a socket failed
|
||||
op_connect,
|
||||
|
||||
// establishing an SSL connection failed
|
||||
|
|
|
@ -589,7 +589,7 @@ namespace libtorrent
|
|||
|
||||
bool can_disconnect(error_code const& ec) const;
|
||||
void incoming_dht_port(int listen_port);
|
||||
|
||||
|
||||
void incoming_reject_request(peer_request const& r);
|
||||
void incoming_have_all();
|
||||
void incoming_have_none();
|
||||
|
|
|
@ -40,7 +40,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
namespace libtorrent {
|
||||
|
||||
struct receive_buffer
|
||||
struct TORRENT_EXTRA_EXPORT receive_buffer
|
||||
{
|
||||
friend struct crypto_receive_buffer;
|
||||
|
||||
|
@ -58,6 +58,7 @@ struct receive_buffer
|
|||
int packet_bytes_remaining() const
|
||||
{
|
||||
TORRENT_ASSERT(m_recv_start == 0);
|
||||
TORRENT_ASSERT(m_packet_size > 0);
|
||||
return m_packet_size - m_recv_pos;
|
||||
}
|
||||
|
||||
|
@ -67,13 +68,19 @@ struct receive_buffer
|
|||
int pos() const { return m_recv_pos; }
|
||||
int capacity() const { return m_recv_buffer.capacity() + m_disk_recv_buffer_size; }
|
||||
|
||||
int regular_buffer_size() const { return m_packet_size - m_disk_recv_buffer_size; }
|
||||
int regular_buffer_size() const
|
||||
{
|
||||
TORRENT_ASSERT(m_packet_size > 0);
|
||||
return m_packet_size - m_disk_recv_buffer_size;
|
||||
}
|
||||
|
||||
// regular buffer only
|
||||
boost::asio::mutable_buffer reserve(int size);
|
||||
// with possible disk buffer usage
|
||||
int reserve(boost::array<boost::asio::mutable_buffer, 2>& vec, int size);
|
||||
|
||||
// tell the buffer we just receved more bytes at the end of it. This will
|
||||
// advance the end cursor
|
||||
void received(int bytes_transferred)
|
||||
{
|
||||
TORRENT_ASSERT(m_packet_size > 0);
|
||||
|
@ -82,9 +89,14 @@ struct receive_buffer
|
|||
+ m_disk_recv_buffer_size));
|
||||
}
|
||||
|
||||
// tell the buffer we consumed some bytes of it. This will advance the read
|
||||
// cursor
|
||||
int advance_pos(int bytes);
|
||||
|
||||
// has the read cursor reached the end cursor?
|
||||
bool pos_at_end() { return m_recv_pos == m_recv_end; }
|
||||
|
||||
// make the buffer size dividible by 8 bytes (RC4 block size)
|
||||
void clamp_size();
|
||||
|
||||
void set_soft_packet_size(int size) { m_soft_packet_size = size; }
|
||||
|
@ -94,6 +106,8 @@ struct receive_buffer
|
|||
// offset = the offset into the receive buffer where to remove `size` bytes
|
||||
void cut(int size, int packet_size, int offset = 0);
|
||||
|
||||
// return the interval between the start of the buffer to the read cursor.
|
||||
// This is the "current" packet.
|
||||
buffer::const_interval get() const;
|
||||
|
||||
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||
|
|
|
@ -92,13 +92,11 @@ namespace libtorrent
|
|||
save_dht_state = 0x004,
|
||||
|
||||
// save pe_settings
|
||||
save_encryption_settings = 0x020,
|
||||
|
||||
// internal
|
||||
save_as_map = 0x040
|
||||
save_encryption_settings = 0x020
|
||||
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
,
|
||||
save_as_map = 0x040,
|
||||
// saves RSS feeds
|
||||
save_feeds = 0x080,
|
||||
save_proxy = 0x008,
|
||||
|
@ -118,11 +116,11 @@ namespace libtorrent
|
|||
// ``load_state`` expects a bdecode_node which can be built from a bencoded
|
||||
// buffer with bdecode().
|
||||
//
|
||||
// The ``flags`` arguments passed in to ``save_state`` can be used to
|
||||
// filter which parts of the session state to save. By default, all state
|
||||
// is saved (except for the individual torrents). see save_state_flags_t
|
||||
// The ``flags`` argument is used to filter which parts of the session
|
||||
// state to save or load. By default, all state is saved/restored (except
|
||||
// for the individual torrents). see save_state_flags_t
|
||||
void save_state(entry& e, boost::uint32_t flags = 0xffffffff) const;
|
||||
void load_state(bdecode_node const& e);
|
||||
void load_state(bdecode_node const& e, boost::uint32_t flags = 0xffffffff);
|
||||
|
||||
// .. note::
|
||||
// these calls are potentially expensive and won't scale well with
|
||||
|
@ -547,12 +545,14 @@ namespace libtorrent
|
|||
// deprecated in 0.15
|
||||
// use load_state and save_state instead
|
||||
TORRENT_DEPRECATED
|
||||
void load_state(entry const& ses_state);
|
||||
void load_state(entry const& ses_state
|
||||
, boost::uint32_t flags = 0xffffffff);
|
||||
TORRENT_DEPRECATED
|
||||
entry state() const;
|
||||
// deprecated in 1.1
|
||||
TORRENT_DEPRECATED
|
||||
void load_state(lazy_entry const& ses_state);
|
||||
void load_state(lazy_entry const& ses_state
|
||||
, boost::uint32_t flags = 0xffffffff);
|
||||
#endif // TORRENT_NO_DEPRECATE
|
||||
|
||||
// Sets a filter that will be used to reject and accept incoming as well
|
||||
|
|
|
@ -453,7 +453,13 @@ namespace libtorrent
|
|||
void flush_cache();
|
||||
void pause(bool graceful = false);
|
||||
void resume();
|
||||
void set_allow_peers(bool b, bool graceful_pause = false);
|
||||
|
||||
enum pause_flags_t
|
||||
{
|
||||
flag_graceful_pause = 1,
|
||||
flag_clear_disk_cache = 2
|
||||
};
|
||||
void set_allow_peers(bool b, int flags = flag_clear_disk_cache);
|
||||
void set_announce_to_dht(bool b) { m_announce_to_dht = b; }
|
||||
void set_announce_to_trackers(bool b) { m_announce_to_trackers = b; }
|
||||
void set_announce_to_lsd(bool b) { m_announce_to_lsd = b; }
|
||||
|
@ -462,7 +468,7 @@ namespace libtorrent
|
|||
|
||||
int started() const { return m_started; }
|
||||
void step_session_time(int seconds);
|
||||
void do_pause();
|
||||
void do_pause(bool clear_disk_cache = true);
|
||||
void do_resume();
|
||||
|
||||
int finished_time() const;
|
||||
|
|
|
@ -98,6 +98,7 @@ namespace libtorrent
|
|||
// int: port-mapping index
|
||||
// address: external address as queried from router
|
||||
// int: external port
|
||||
// int: protocol (UDP, TCP)
|
||||
// std::string: error message
|
||||
// an empty string as error means success
|
||||
typedef boost::function<void(int, address, int, int, error_code const&)> portmap_callback_t;
|
||||
|
|
|
@ -15,6 +15,7 @@ project
|
|||
<source>setup_swarm.cpp
|
||||
<source>setup_dht.cpp
|
||||
<source>create_torrent.cpp
|
||||
<source>utils.cpp
|
||||
: default-build
|
||||
<threading>multi
|
||||
<invariant-checks>full
|
||||
|
@ -23,6 +24,7 @@ project
|
|||
;
|
||||
|
||||
alias libtorrent-sims :
|
||||
[ run test_checking.cpp ]
|
||||
[ run test_optimistic_unchoke.cpp ]
|
||||
[ run test_transfer.cpp ]
|
||||
[ run test_http_connection.cpp ]
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2016, Arvid Norberg
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the author nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "libtorrent/session.hpp"
|
||||
#include "libtorrent/deadline_timer.hpp"
|
||||
#include "libtorrent/address.hpp"
|
||||
#include "libtorrent/torrent_status.hpp"
|
||||
#include "simulator/simulator.hpp"
|
||||
|
||||
#include "test.hpp"
|
||||
#include "settings.hpp"
|
||||
#include "create_torrent.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
template <typename Setup, typename Test>
|
||||
void run_test(Setup const& setup, Test const& test)
|
||||
{
|
||||
// this is a seeding torrent
|
||||
lt::add_torrent_params atp = create_torrent(0, true);
|
||||
|
||||
sim::default_config network_cfg;
|
||||
sim::simulation sim{network_cfg};
|
||||
auto ios = std::unique_ptr<sim::asio::io_service>(new sim::asio::io_service(
|
||||
sim, lt::address_v4::from_string("50.0.0.1")));
|
||||
lt::session_proxy zombie;
|
||||
|
||||
// setup settings pack to use for the session (customization point)
|
||||
lt::settings_pack pack = settings();
|
||||
setup(atp, pack);
|
||||
|
||||
auto ses = std::make_shared<lt::session>(pack, *ios);
|
||||
|
||||
ses->async_add_torrent(atp);
|
||||
|
||||
print_alerts(*ses);
|
||||
|
||||
lt::deadline_timer timer(*ios);
|
||||
timer.expires_from_now(lt::seconds(6));
|
||||
timer.async_wait([&](lt::error_code const& ec)
|
||||
{
|
||||
test(*ses);
|
||||
|
||||
// shut down
|
||||
ses->set_alert_notify([]{});
|
||||
zombie = ses->abort();
|
||||
ses.reset();
|
||||
});
|
||||
|
||||
sim.run();
|
||||
}
|
||||
|
||||
TORRENT_TEST(cache_after_checking)
|
||||
{
|
||||
run_test(
|
||||
[](lt::add_torrent_params& atp, lt::settings_pack& p) {
|
||||
atp.flags |= lt::add_torrent_params::flag_auto_managed;
|
||||
p.set_int(lt::settings_pack::cache_size, 100);
|
||||
},
|
||||
[](lt::session& ses) {
|
||||
int cache = get_cache_size(ses);
|
||||
TEST_CHECK(cache > 0);
|
||||
|
||||
std::vector<lt::torrent_handle> tor = ses.get_torrents();
|
||||
TEST_EQUAL(tor.size(), 1);
|
||||
|
||||
TEST_EQUAL(tor[0].status().is_seeding, true);
|
||||
});
|
||||
}
|
||||
|
||||
TORRENT_TEST(checking_no_cache)
|
||||
{
|
||||
run_test(
|
||||
[](lt::add_torrent_params& atp, lt::settings_pack& p) {
|
||||
atp.flags |= lt::add_torrent_params::flag_auto_managed;
|
||||
p.set_int(lt::settings_pack::cache_size, 0);
|
||||
},
|
||||
[](lt::session& ses) {
|
||||
int cache = get_cache_size(ses);
|
||||
TEST_EQUAL(cache, 0);
|
||||
|
||||
std::vector<lt::torrent_handle> tor = ses.get_torrents();
|
||||
TEST_EQUAL(tor.size(), 1);
|
||||
|
||||
TEST_EQUAL(tor[0].status().is_seeding, true);
|
||||
});
|
||||
}
|
|
@ -97,7 +97,7 @@ TORRENT_TEST(session_stats)
|
|||
// on alert
|
||||
, [=](lt::alert const* a, lt::session& ses)
|
||||
{
|
||||
lt::session_stats_alert const* ss = lt::alert_cast<session_stats_alert>(a);
|
||||
auto const* ss = lt::alert_cast<session_stats_alert>(a);
|
||||
if (!ss) return;
|
||||
|
||||
// there's one downloading torrent
|
||||
|
|
|
@ -35,6 +35,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "create_torrent.hpp"
|
||||
#include "settings.hpp"
|
||||
#include "libtorrent/session.hpp"
|
||||
#include "libtorrent/session_stats.hpp"
|
||||
#include "libtorrent/deadline_timer.hpp"
|
||||
#include "libtorrent/settings_pack.hpp"
|
||||
#include "libtorrent/ip_filter.hpp"
|
||||
|
@ -44,16 +45,12 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "simulator/simulator.hpp"
|
||||
#include "simulator/socks_server.hpp"
|
||||
#include "setup_swarm.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
using namespace sim;
|
||||
|
||||
namespace lt = libtorrent;
|
||||
|
||||
enum flags_t
|
||||
{
|
||||
ipv6 = 1,
|
||||
};
|
||||
|
||||
template <typename Setup, typename HandleAlerts, typename Test>
|
||||
void run_test(
|
||||
Setup const& setup
|
||||
|
@ -63,8 +60,6 @@ void run_test(
|
|||
{
|
||||
using namespace libtorrent;
|
||||
|
||||
lt::time_point start_time = lt::clock_type::now();
|
||||
|
||||
const bool use_ipv6 = flags & ipv6;
|
||||
|
||||
char const* peer0_ip[2] = { "50.0.0.1", "feed:face:baad:f00d::1" };
|
||||
|
@ -112,32 +107,15 @@ void run_test(
|
|||
setup(*ses[0], *ses[1]);
|
||||
|
||||
// only monitor alerts for session 0 (the downloader)
|
||||
ses[0]->set_alert_notify([&] { ios0.post([&] {
|
||||
std::vector<lt::alert*> alerts;
|
||||
ses[0]->pop_alerts(&alerts);
|
||||
|
||||
for (lt::alert const* a : alerts)
|
||||
print_alerts(*ses[0], [=](lt::session& ses, lt::alert const* a) {
|
||||
if (auto ta = alert_cast<lt::torrent_added_alert>(a))
|
||||
{
|
||||
printf("%-3d [0] %s\n", int(lt::duration_cast<lt::seconds>(a->timestamp()
|
||||
- start_time).count()), a->message().c_str());
|
||||
if (auto ta = alert_cast<lt::torrent_added_alert>(a))
|
||||
{
|
||||
ta->handle.connect_peer(lt::tcp::endpoint(peer1, 6881));
|
||||
}
|
||||
// call the user handler
|
||||
on_alert(*ses[0], a);
|
||||
ta->handle.connect_peer(lt::tcp::endpoint(peer1, 6881));
|
||||
}
|
||||
} ); } );
|
||||
on_alert(ses, a);
|
||||
});
|
||||
|
||||
ses[1]->set_alert_notify([&] { ios0.post([&] {
|
||||
std::vector<lt::alert*> alerts;
|
||||
ses[1]->pop_alerts(&alerts);
|
||||
for (lt::alert const* a : alerts)
|
||||
{
|
||||
printf("%-3d [1] %s\n", int(lt::duration_cast<lt::seconds>(a->timestamp()
|
||||
- start_time).count()), a->message().c_str());
|
||||
}
|
||||
} ); } );
|
||||
print_alerts(*ses[1]);
|
||||
|
||||
// the first peer is a downloader, the second peer is a seed
|
||||
lt::add_torrent_params params = create_torrent(1);
|
||||
|
@ -169,52 +147,6 @@ void run_test(
|
|||
sim.run();
|
||||
}
|
||||
|
||||
void utp_only(lt::session& ses)
|
||||
{
|
||||
using namespace libtorrent;
|
||||
settings_pack p;
|
||||
utp_only(p);
|
||||
ses.apply_settings(p);
|
||||
}
|
||||
|
||||
void enable_enc(lt::session& ses)
|
||||
{
|
||||
using namespace libtorrent;
|
||||
settings_pack p;
|
||||
enable_enc(p);
|
||||
ses.apply_settings(p);
|
||||
}
|
||||
|
||||
void filter_ips(lt::session& ses)
|
||||
{
|
||||
using namespace libtorrent;
|
||||
ip_filter filter;
|
||||
filter.add_rule(asio::ip::address_v4::from_string("50.0.0.1")
|
||||
, asio::ip::address_v4::from_string("50.0.0.2"), ip_filter::blocked);
|
||||
ses.set_ip_filter(filter);
|
||||
}
|
||||
|
||||
void set_proxy(lt::session& ses, int proxy_type, int flags = 0, bool proxy_peer_connections = true)
|
||||
{
|
||||
// apply the proxy settings to session 0
|
||||
using namespace libtorrent;
|
||||
settings_pack p;
|
||||
p.set_int(settings_pack::proxy_type, proxy_type);
|
||||
if (proxy_type == settings_pack::socks4)
|
||||
p.set_int(settings_pack::proxy_port, 4444);
|
||||
else
|
||||
p.set_int(settings_pack::proxy_port, 5555);
|
||||
if (flags & ipv6)
|
||||
p.set_str(settings_pack::proxy_hostname, "2001::2");
|
||||
else
|
||||
p.set_str(settings_pack::proxy_hostname, "50.50.50.50");
|
||||
p.set_bool(settings_pack::proxy_hostnames, true);
|
||||
p.set_bool(settings_pack::proxy_peer_connections, proxy_peer_connections);
|
||||
p.set_bool(settings_pack::proxy_tracker_connections, true);
|
||||
|
||||
ses.apply_settings(p);
|
||||
}
|
||||
|
||||
TORRENT_TEST(socks4_tcp)
|
||||
{
|
||||
using namespace libtorrent;
|
||||
|
@ -391,3 +323,36 @@ TORRENT_TEST(no_proxy_utp_banned)
|
|||
);
|
||||
}
|
||||
|
||||
TORRENT_TEST(auto_disk_cache_size)
|
||||
{
|
||||
using namespace libtorrent;
|
||||
run_test(
|
||||
[](lt::session& ses0, lt::session& ses1) { set_cache_size(ses0, -1); },
|
||||
[](lt::session& ses, lt::alert const* alert) {},
|
||||
[](std::shared_ptr<lt::session> ses[2]) {
|
||||
TEST_EQUAL(is_seed(*ses[0]), true);
|
||||
|
||||
int const cache_size = get_cache_size(*ses[0]);
|
||||
printf("cache size: %d\n", cache_size);
|
||||
// this assumes the test torrent is at least 4 blocks
|
||||
TEST_CHECK(cache_size > 4);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
TORRENT_TEST(disable_disk_cache)
|
||||
{
|
||||
using namespace libtorrent;
|
||||
run_test(
|
||||
[](lt::session& ses0, lt::session& ses1) { set_cache_size(ses0, 0); },
|
||||
[](lt::session& ses, lt::alert const* alert) {},
|
||||
[](std::shared_ptr<lt::session> ses[2]) {
|
||||
TEST_EQUAL(is_seed(*ses[0]), true);
|
||||
|
||||
int const cache_size = get_cache_size(*ses[0]);
|
||||
printf("cache size: %d\n", cache_size);
|
||||
TEST_EQUAL(cache_size, 0);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2016, Arvid Norberg
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the author nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "utils.hpp"
|
||||
#include "test.hpp"
|
||||
#include "libtorrent/session.hpp"
|
||||
#include "libtorrent/settings_pack.hpp"
|
||||
#include "libtorrent/address.hpp"
|
||||
#include "libtorrent/ip_filter.hpp"
|
||||
#include "libtorrent/alert_types.hpp"
|
||||
#include "libtorrent/session_stats.hpp"
|
||||
#include "libtorrent/alert.hpp"
|
||||
#include "setup_swarm.hpp"
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
void utp_only(lt::session& ses)
|
||||
{
|
||||
settings_pack p;
|
||||
utp_only(p);
|
||||
ses.apply_settings(p);
|
||||
}
|
||||
|
||||
void enable_enc(lt::session& ses)
|
||||
{
|
||||
settings_pack p;
|
||||
enable_enc(p);
|
||||
ses.apply_settings(p);
|
||||
}
|
||||
|
||||
void filter_ips(lt::session& ses)
|
||||
{
|
||||
ip_filter filter;
|
||||
filter.add_rule(address_v4::from_string("50.0.0.1")
|
||||
, address_v4::from_string("50.0.0.2"), ip_filter::blocked);
|
||||
ses.set_ip_filter(filter);
|
||||
}
|
||||
|
||||
void set_cache_size(lt::session& ses, int val)
|
||||
{
|
||||
settings_pack pack;
|
||||
pack.set_int(settings_pack::cache_size, val);
|
||||
ses.apply_settings(pack);
|
||||
}
|
||||
|
||||
int get_cache_size(lt::session& ses)
|
||||
{
|
||||
std::vector<stats_metric> stats = session_stats_metrics();
|
||||
int const read_cache_idx = find_metric_idx("disk.read_cache_blocks");
|
||||
int const write_cache_idx = find_metric_idx("disk.write_cache_blocks");
|
||||
TEST_CHECK(read_cache_idx >= 0);
|
||||
TEST_CHECK(write_cache_idx >= 0);
|
||||
ses.set_alert_notify([](){});
|
||||
ses.post_session_stats();
|
||||
std::vector<alert*> alerts;
|
||||
ses.pop_alerts(&alerts);
|
||||
int cache_size = -1;
|
||||
for (auto const a : alerts)
|
||||
{
|
||||
if (auto const* st = alert_cast<session_stats_alert>(a))
|
||||
{
|
||||
cache_size = st->values[read_cache_idx];
|
||||
cache_size += st->values[write_cache_idx];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cache_size;
|
||||
}
|
||||
|
||||
void set_proxy(lt::session& ses, int proxy_type, int flags, bool proxy_peer_connections)
|
||||
{
|
||||
// apply the proxy settings to session 0
|
||||
settings_pack p;
|
||||
p.set_int(settings_pack::proxy_type, proxy_type);
|
||||
if (proxy_type == settings_pack::socks4)
|
||||
p.set_int(settings_pack::proxy_port, 4444);
|
||||
else
|
||||
p.set_int(settings_pack::proxy_port, 5555);
|
||||
if (flags & ipv6)
|
||||
p.set_str(settings_pack::proxy_hostname, "2001::2");
|
||||
else
|
||||
p.set_str(settings_pack::proxy_hostname, "50.50.50.50");
|
||||
p.set_bool(settings_pack::proxy_hostnames, true);
|
||||
p.set_bool(settings_pack::proxy_peer_connections, proxy_peer_connections);
|
||||
p.set_bool(settings_pack::proxy_tracker_connections, true);
|
||||
|
||||
ses.apply_settings(p);
|
||||
}
|
||||
|
||||
void print_alerts(lt::session& ses
|
||||
, std::function<void(lt::session&, lt::alert const*)> on_alert)
|
||||
{
|
||||
lt::time_point start_time = lt::clock_type::now();
|
||||
|
||||
ses.set_alert_notify([&ses,start_time,on_alert] {
|
||||
ses.get_io_service().post([&ses,start_time,on_alert] {
|
||||
|
||||
std::vector<lt::alert*> alerts;
|
||||
ses.pop_alerts(&alerts);
|
||||
|
||||
for (lt::alert const* a : alerts)
|
||||
{
|
||||
printf("%-3d [0] %s\n", int(lt::duration_cast<lt::seconds>(a->timestamp()
|
||||
- start_time).count()), a->message().c_str());
|
||||
// call the user handler
|
||||
on_alert(ses, a);
|
||||
}
|
||||
} ); } );
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2016, Arvid Norberg
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the author nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
class session;
|
||||
class alert;
|
||||
}
|
||||
|
||||
namespace lt = libtorrent;
|
||||
|
||||
void utp_only(lt::session& ses);
|
||||
void enable_enc(lt::session& ses);
|
||||
void filter_ips(lt::session& ses);
|
||||
void set_cache_size(lt::session& ses, int val);
|
||||
int get_cache_size(lt::session& ses);
|
||||
|
||||
enum flags_t
|
||||
{
|
||||
ipv6 = 1,
|
||||
};
|
||||
|
||||
void set_proxy(lt::session& ses, int proxy_type, int flags = 0
|
||||
, bool proxy_peer_connections = true);
|
||||
|
||||
void print_alerts(lt::session& ses
|
||||
, std::function<void(lt::session&, lt::alert const*)> on_alert
|
||||
= [](lt::session& ses, lt::alert const* a) {});
|
||||
|
|
@ -87,7 +87,11 @@ namespace libtorrent {
|
|||
|
||||
char const* torrent_alert::torrent_name() const
|
||||
{
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
return name.c_str();
|
||||
#else
|
||||
return m_alloc.ptr(m_name_idx);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string torrent_alert::message() const
|
||||
|
@ -124,7 +128,11 @@ namespace libtorrent {
|
|||
|
||||
char const* tracker_alert::tracker_url() const
|
||||
{
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
return url.c_str();
|
||||
#else
|
||||
return m_alloc.ptr(m_url_idx);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string tracker_alert::message() const
|
||||
|
@ -195,7 +203,11 @@ namespace libtorrent {
|
|||
|
||||
char const* file_renamed_alert::new_name() const
|
||||
{
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
return name.c_str();
|
||||
#else
|
||||
return m_alloc.ptr(m_name_idx);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string file_renamed_alert::message() const
|
||||
|
@ -292,7 +304,11 @@ namespace libtorrent {
|
|||
|
||||
char const* tracker_error_alert::error_message() const
|
||||
{
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
return msg.c_str();
|
||||
#else
|
||||
return m_alloc.ptr(m_msg_idx);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string tracker_error_alert::message() const
|
||||
|
@ -320,7 +336,11 @@ namespace libtorrent {
|
|||
|
||||
char const* tracker_warning_alert::warning_message() const
|
||||
{
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
return msg.c_str();
|
||||
#else
|
||||
return m_alloc.ptr(m_msg_idx);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string tracker_warning_alert::message() const
|
||||
|
@ -378,8 +398,12 @@ namespace libtorrent {
|
|||
|
||||
char const* scrape_failed_alert::error_message() const
|
||||
{
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
return msg.c_str();
|
||||
#else
|
||||
if (m_msg_idx == -1) return "";
|
||||
else return m_alloc.ptr(m_msg_idx);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string scrape_failed_alert::message() const
|
||||
|
@ -649,7 +673,11 @@ namespace libtorrent {
|
|||
|
||||
char const* storage_moved_alert::storage_path() const
|
||||
{
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
return path.c_str();
|
||||
#else
|
||||
return m_alloc.ptr(m_path_idx);
|
||||
#endif
|
||||
}
|
||||
|
||||
storage_moved_failed_alert::storage_moved_failed_alert(
|
||||
|
@ -669,7 +697,11 @@ namespace libtorrent {
|
|||
|
||||
char const* storage_moved_failed_alert::file_path() const
|
||||
{
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
return file.c_str();
|
||||
#else
|
||||
return m_alloc.ptr(m_file_idx);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string storage_moved_failed_alert::message() const
|
||||
|
@ -935,7 +967,11 @@ namespace libtorrent {
|
|||
|
||||
char const* portmap_log_alert::log_message() const
|
||||
{
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
return msg.c_str();
|
||||
#else
|
||||
return m_alloc.ptr(m_log_idx);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string portmap_log_alert::message() const
|
||||
|
@ -976,7 +1012,11 @@ namespace libtorrent {
|
|||
|
||||
char const* fastresume_rejected_alert::file_path() const
|
||||
{
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
return file.c_str();
|
||||
#else
|
||||
return m_alloc.ptr(m_path_idx);
|
||||
#endif
|
||||
}
|
||||
|
||||
peer_blocked_alert::peer_blocked_alert(aux::stack_allocator& alloc
|
||||
|
@ -1141,7 +1181,11 @@ namespace libtorrent {
|
|||
|
||||
char const* trackerid_alert::tracker_id() const
|
||||
{
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
return trackerid.c_str();
|
||||
#else
|
||||
return m_alloc.ptr(m_tracker_idx);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string trackerid_alert::message() const
|
||||
|
@ -1706,8 +1750,12 @@ namespace libtorrent {
|
|||
|
||||
char const* url_seed_alert::error_message() const
|
||||
{
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
return msg.c_str();
|
||||
#else
|
||||
if (m_msg_idx == -1) return "";
|
||||
return m_alloc.ptr(m_msg_idx);
|
||||
#endif
|
||||
}
|
||||
|
||||
file_error_alert::file_error_alert(aux::stack_allocator& alloc
|
||||
|
@ -1730,7 +1778,11 @@ namespace libtorrent {
|
|||
|
||||
char const* file_error_alert::filename() const
|
||||
{
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
return file.c_str();
|
||||
#else
|
||||
return m_alloc.ptr(m_file_idx);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string file_error_alert::message() const
|
||||
|
|
|
@ -1082,7 +1082,7 @@ int block_cache::try_evict_blocks(int num, cached_piece_entry* ignore)
|
|||
// the first pass, only evict blocks that have been
|
||||
// hashed
|
||||
if (pass == 0 && pe->hash)
|
||||
end = pe->hash->offset / block_size();
|
||||
end = pe->hash->offset / block_size();
|
||||
|
||||
// go through the blocks and evict the ones
|
||||
// that are not dirty and not referenced
|
||||
|
|
|
@ -808,7 +808,7 @@ namespace libtorrent
|
|||
// we support FAST extension
|
||||
*(ptr + 7) |= 0x04;
|
||||
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
std::string bitmask;
|
||||
for (int k = 0; k < 8; ++k)
|
||||
{
|
||||
|
@ -3284,8 +3284,7 @@ namespace libtorrent
|
|||
if (!m_recv_buffer.packet_finished()) return;
|
||||
recv_buffer = m_recv_buffer.get();
|
||||
|
||||
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
std::string extensions;
|
||||
extensions.resize(8 * 8);
|
||||
for (int i=0; i < 8; ++i)
|
||||
|
@ -3461,7 +3460,7 @@ namespace libtorrent
|
|||
#endif
|
||||
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
peer_log(peer_log_alert::incoming_message, "HANDSHAKE");
|
||||
peer_log(peer_log_alert::incoming_message, "HANDSHAKE", "connection ready");
|
||||
#endif
|
||||
// consider this a successful connection, reset the failcount
|
||||
if (peer_info_struct())
|
||||
|
|
|
@ -133,14 +133,14 @@ namespace libtorrent
|
|||
// when seeding, prefer the peer we're uploading the fastest to
|
||||
c1 = lhs->uploaded_in_last_round();
|
||||
c2 = rhs->uploaded_in_last_round();
|
||||
|
||||
|
||||
// take torrent priority into account
|
||||
c1 *= prio1;
|
||||
c2 *= prio2;
|
||||
|
||||
if (c1 > c2) return true;
|
||||
if (c2 > c1) return false;
|
||||
|
||||
|
||||
// prioritize the one that has waited the longest to be unchoked
|
||||
// the round-robin unchoker relies on this logic. Don't change it
|
||||
// without moving this into that unchoker logic
|
||||
|
@ -200,7 +200,7 @@ namespace libtorrent
|
|||
? t2_total - rhs->num_have_pieces() : rhs->num_have_pieces()) * 1000 / t2_total;
|
||||
if (score1 > score2) return true;
|
||||
if (score2 > score1) return false;
|
||||
|
||||
|
||||
// prioritize the one that has waited the longest to be unchoked
|
||||
// the round-robin unchoker relies on this logic. Don't change it
|
||||
// without moving this into that unchoker logic
|
||||
|
@ -215,7 +215,7 @@ namespace libtorrent
|
|||
|
||||
c1 = lhs->uploaded_in_last_round();
|
||||
c2 = rhs->uploaded_in_last_round();
|
||||
|
||||
|
||||
// take torrent priority into account
|
||||
c1 *= lhs->get_priority(peer_connection::upload_channel);
|
||||
c2 *= rhs->get_priority(peer_connection::upload_channel);
|
||||
|
@ -256,7 +256,18 @@ namespace libtorrent
|
|||
, time_duration unchoke_interval
|
||||
, aux::session_settings const& sett)
|
||||
{
|
||||
#if TORRENT_USE_ASSERTS
|
||||
for (std::vector<peer_connection*>::iterator i = peers.begin()
|
||||
, end(peers.end()); i != end; ++i)
|
||||
{
|
||||
TORRENT_ASSERT((*i)->self());
|
||||
TORRENT_ASSERT((*i)->associated_torrent().lock());
|
||||
}
|
||||
#endif
|
||||
|
||||
int upload_slots = sett.get_int(settings_pack::unchoke_slots_limit);
|
||||
if (upload_slots < 0)
|
||||
upload_slots = (std::numeric_limits<int>::max)();
|
||||
|
||||
// ==== BitTyrant ====
|
||||
//
|
||||
|
|
|
@ -371,11 +371,14 @@ namespace libtorrent
|
|||
#else
|
||||
if (m_using_pool_allocator)
|
||||
{
|
||||
ret = static_cast<char*>(m_pool.malloc());
|
||||
int effective_block_size = m_cache_buffer_chunk_size
|
||||
int const effective_block_size
|
||||
= m_in_use >= m_max_use
|
||||
? 20 // use small increments once we've exceeded the cache size
|
||||
: m_cache_buffer_chunk_size
|
||||
? m_cache_buffer_chunk_size
|
||||
: (std::max)(m_max_use / 10, 1);
|
||||
m_pool.set_next_size(effective_block_size);
|
||||
ret = static_cast<char*>(m_pool.malloc());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -453,7 +456,9 @@ namespace libtorrent
|
|||
m_cache_buffer_chunk_size = sett.get_int(settings_pack::cache_buffer_chunk_size);
|
||||
m_lock_disk_cache = sett.get_bool(settings_pack::lock_disk_cache);
|
||||
#ifndef TORRENT_DISABLE_POOL_ALLOCATOR
|
||||
m_want_pool_allocator = sett.get_bool(settings_pack::use_disk_cache_pool);
|
||||
// if the chunk size is set to 1, there's no point in creating a pool
|
||||
m_want_pool_allocator = sett.get_bool(settings_pack::use_disk_cache_pool)
|
||||
&& (m_cache_buffer_chunk_size != 1);
|
||||
// if there are no allocated blocks, it's OK to switch allocator
|
||||
if (m_in_use == 0)
|
||||
m_using_pool_allocator = m_want_pool_allocator;
|
||||
|
@ -473,12 +478,38 @@ namespace libtorrent
|
|||
#endif
|
||||
sett.get_str(settings_pack::mmap_cache).empty())
|
||||
{
|
||||
int cache_size = sett.get_int(settings_pack::cache_size);
|
||||
int const cache_size = sett.get_int(settings_pack::cache_size);
|
||||
if (cache_size < 0)
|
||||
{
|
||||
boost::uint64_t phys_ram = total_physical_ram();
|
||||
if (phys_ram == 0) m_max_use = 1024;
|
||||
else m_max_use = phys_ram / 8 / m_block_size;
|
||||
else
|
||||
{
|
||||
// this is the logic to calculate the automatic disk cache size
|
||||
// based on the amount of physical RAM.
|
||||
// The more physical RAM, the smaller portion of it is allocated
|
||||
// for the cache.
|
||||
|
||||
// we take a 30th of everything exceeding 4 GiB
|
||||
// a 20th of everything exceeding 1 GiB
|
||||
// and a 10th of everything below a GiB
|
||||
|
||||
boost::int64_t const gb = 1024 * 1024 * 1024;
|
||||
|
||||
boost::int64_t result = 0;
|
||||
if (phys_ram > 4 * gb)
|
||||
{
|
||||
result += (phys_ram - 4 * gb) / 30;
|
||||
phys_ram = 4 * gb;
|
||||
}
|
||||
if (phys_ram > 1 * gb)
|
||||
{
|
||||
result += (phys_ram - 1 * gb) / 20;
|
||||
phys_ram = 1 * gb;
|
||||
}
|
||||
result += phys_ram / 10;
|
||||
m_max_use = result / m_block_size;
|
||||
}
|
||||
|
||||
if (sizeof(void*) == 4)
|
||||
{
|
||||
|
@ -500,6 +531,8 @@ namespace libtorrent
|
|||
m_exceeded_max_size = true;
|
||||
m_trigger_cache_trim();
|
||||
}
|
||||
if (m_cache_buffer_chunk_size > m_max_use)
|
||||
m_cache_buffer_chunk_size = m_max_use;
|
||||
}
|
||||
|
||||
#if TORRENT_USE_ASSERTS
|
||||
|
|
|
@ -573,7 +573,7 @@ namespace libtorrent
|
|||
|
||||
int piece_size = pe->storage->files()->piece_size(pe->piece);
|
||||
TORRENT_PIECE_ASSERT(piece_size > 0, pe);
|
||||
|
||||
|
||||
int iov_len = 0;
|
||||
// the blocks we're flushing
|
||||
int num_flushing = 0;
|
||||
|
@ -1142,21 +1142,6 @@ namespace libtorrent
|
|||
return;
|
||||
}
|
||||
|
||||
#if TORRENT_USE_ASSERTS
|
||||
// TODO: it should clear the hash state even when there's an error, right?
|
||||
if (j->action == disk_io_job::hash && !j->error.ec)
|
||||
{
|
||||
// a hash job should never return without clearing pe->hash
|
||||
l.lock();
|
||||
cached_piece_entry* pe = m_disk_cache.find_piece(j);
|
||||
if (pe != NULL)
|
||||
{
|
||||
TORRENT_PIECE_ASSERT(pe->hash == NULL, pe);
|
||||
}
|
||||
l.unlock();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ret == defer_handler) return;
|
||||
|
||||
j->ret = ret;
|
||||
|
@ -1202,16 +1187,11 @@ namespace libtorrent
|
|||
|
||||
int disk_io_thread::do_read(disk_io_job* j, jobqueue_t& completed_jobs)
|
||||
{
|
||||
if (!m_settings.get_bool(settings_pack::use_read_cache)
|
||||
|| m_settings.get_int(settings_pack::cache_size) == 0)
|
||||
if ((j->flags & disk_io_job::use_disk_cache) == 0)
|
||||
{
|
||||
// we're not using a cache. This is the simple path
|
||||
// just read straight from the file
|
||||
int ret = do_uncached_read(j);
|
||||
|
||||
mutex::scoped_lock l(m_cache_mutex);
|
||||
cached_piece_entry* pe = m_disk_cache.find_piece(j);
|
||||
if (pe) maybe_issue_queued_read_jobs(pe, completed_jobs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1475,8 +1455,7 @@ namespace libtorrent
|
|||
|
||||
// should we put this write job in the cache?
|
||||
// if we don't use the cache we shouldn't.
|
||||
if (m_settings.get_bool(settings_pack::use_write_cache)
|
||||
&& m_settings.get_int(settings_pack::cache_size) > 0)
|
||||
if (j->flags & disk_io_job::use_disk_cache)
|
||||
{
|
||||
mutex::scoped_lock l(m_cache_mutex);
|
||||
|
||||
|
@ -1592,7 +1571,7 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(j->action == disk_io_job::read);
|
||||
|
||||
if (m_settings.get_bool(settings_pack::use_read_cache)
|
||||
&& m_settings.get_int(settings_pack::cache_size) > 0)
|
||||
&& m_settings.get_int(settings_pack::cache_size) != 0)
|
||||
{
|
||||
int ret = m_disk_cache.try_read(j);
|
||||
if (ret >= 0)
|
||||
|
@ -1629,7 +1608,7 @@ namespace libtorrent
|
|||
j->error.operation = storage_error::read;
|
||||
return 0;
|
||||
}
|
||||
|
||||
j->flags |= disk_io_job::use_disk_cache;
|
||||
if (pe->outstanding_read)
|
||||
{
|
||||
TORRENT_PIECE_ASSERT(j->piece == pe->piece, pe);
|
||||
|
@ -1705,10 +1684,11 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(m_disk_cache.is_disk_buffer(j->buffer.disk_block));
|
||||
l_.unlock();
|
||||
#endif
|
||||
if (m_settings.get_int(settings_pack::cache_size) > 0
|
||||
if (m_settings.get_int(settings_pack::cache_size) != 0
|
||||
&& m_settings.get_bool(settings_pack::use_write_cache))
|
||||
{
|
||||
TORRENT_ASSERT((r.start % m_disk_cache.block_size()) == 0);
|
||||
j->flags |= disk_io_job::use_disk_cache;
|
||||
|
||||
if (storage->is_blocked(j))
|
||||
{
|
||||
|
@ -1798,6 +1778,12 @@ namespace libtorrent
|
|||
}
|
||||
l.unlock();
|
||||
|
||||
if (m_settings.get_bool(settings_pack::use_read_cache)
|
||||
&& m_settings.get_int(settings_pack::cache_size) != 0)
|
||||
{
|
||||
j->flags |= disk_io_job::use_disk_cache;
|
||||
}
|
||||
|
||||
add_job(j);
|
||||
}
|
||||
|
||||
|
@ -2233,10 +2219,10 @@ namespace libtorrent
|
|||
// just read straight from the file
|
||||
TORRENT_ASSERT(m_magic == 0x1337);
|
||||
|
||||
int piece_size = j->storage->files()->piece_size(j->piece);
|
||||
int block_size = m_disk_cache.block_size();
|
||||
int blocks_in_piece = (piece_size + block_size - 1) / block_size;
|
||||
int file_flags = file_flags_for_job(j);
|
||||
int const piece_size = j->storage->files()->piece_size(j->piece);
|
||||
int const block_size = m_disk_cache.block_size();
|
||||
int const blocks_in_piece = (piece_size + block_size - 1) / block_size;
|
||||
int const file_flags = file_flags_for_job(j);
|
||||
|
||||
file::iovec_t iov;
|
||||
iov.iov_base = m_disk_cache.allocate_buffer("hashing");
|
||||
|
@ -2257,7 +2243,7 @@ namespace libtorrent
|
|||
|
||||
if (!j->error.ec)
|
||||
{
|
||||
boost::uint32_t read_time = total_microseconds(clock_type::now() - start_time);
|
||||
boost::uint32_t const read_time = total_microseconds(clock_type::now() - start_time);
|
||||
m_read_time.add_sample(read_time);
|
||||
|
||||
m_stats_counters.inc_stats_counter(counters::num_blocks_read);
|
||||
|
@ -2281,11 +2267,11 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_settings.get_int(settings_pack::cache_size) == 0)
|
||||
if ((j->flags & disk_io_job::use_disk_cache) == 0)
|
||||
return do_uncached_hash(j);
|
||||
|
||||
int piece_size = j->storage->files()->piece_size(j->piece);
|
||||
int file_flags = file_flags_for_job(j);
|
||||
int const piece_size = j->storage->files()->piece_size(j->piece);
|
||||
int const file_flags = file_flags_for_job(j);
|
||||
|
||||
mutex::scoped_lock l(m_cache_mutex);
|
||||
|
||||
|
@ -2324,7 +2310,7 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
|
||||
if (pe == NULL && !m_settings.get_bool(settings_pack::use_read_cache))
|
||||
if (pe == NULL && m_settings.get_bool(settings_pack::use_read_cache) == false)
|
||||
{
|
||||
l.unlock();
|
||||
// if there's no piece in the cache, and the read cache is disabled
|
||||
|
@ -2373,7 +2359,7 @@ namespace libtorrent
|
|||
|
||||
int block_size = m_disk_cache.block_size();
|
||||
int blocks_in_piece = (piece_size + block_size - 1) / block_size;
|
||||
|
||||
|
||||
// keep track of which blocks we have locked by incrementing
|
||||
// their refcounts. This is used to decrement only these blocks
|
||||
// later.
|
||||
|
@ -2616,7 +2602,7 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
TORRENT_ASSERT(j->buffer.disk_block == 0);
|
||||
|
||||
|
||||
if (m_settings.get_int(settings_pack::cache_size) == 0
|
||||
|| m_settings.get_bool(settings_pack::use_read_cache) == false)
|
||||
return 0;
|
||||
|
@ -2819,17 +2805,17 @@ namespace libtorrent
|
|||
if (no_pieces == false)
|
||||
{
|
||||
int block_size = m_disk_cache.block_size();
|
||||
|
||||
|
||||
if (storage)
|
||||
{
|
||||
ret->pieces.reserve(storage->num_pieces());
|
||||
|
||||
|
||||
for (boost::unordered_set<cached_piece_entry*>::iterator i
|
||||
= storage->cached_pieces().begin(), end(storage->cached_pieces().end());
|
||||
i != end; ++i)
|
||||
{
|
||||
TORRENT_ASSERT((*i)->storage.get() == storage);
|
||||
|
||||
|
||||
if ((*i)->cache_state == cached_piece_entry::read_lru2_ghost
|
||||
|| (*i)->cache_state == cached_piece_entry::read_lru1_ghost)
|
||||
continue;
|
||||
|
@ -2840,10 +2826,10 @@ namespace libtorrent
|
|||
else
|
||||
{
|
||||
ret->pieces.reserve(m_disk_cache.num_pieces());
|
||||
|
||||
|
||||
std::pair<block_cache::iterator, block_cache::iterator> range
|
||||
= m_disk_cache.all_pieces();
|
||||
|
||||
|
||||
for (block_cache::iterator i = range.first; i != range.second; ++i)
|
||||
{
|
||||
if (i->cache_state == cached_piece_entry::read_lru2_ghost
|
||||
|
@ -3444,7 +3430,7 @@ namespace libtorrent
|
|||
|
||||
if (j->action == disk_io_job::read
|
||||
&& m_settings.get_bool(settings_pack::use_read_cache)
|
||||
&& m_settings.get_int(settings_pack::cache_size) > 0)
|
||||
&& m_settings.get_int(settings_pack::cache_size) != 0)
|
||||
{
|
||||
int state = prep_read_job_impl(j, false);
|
||||
switch (state)
|
||||
|
|
|
@ -599,6 +599,7 @@ namespace libtorrent
|
|||
if (r == ERROR_BUFFER_OVERFLOW)
|
||||
{
|
||||
buffer.resize(buf_size);
|
||||
adapter_addresses = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(&buffer[0]);
|
||||
r = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER
|
||||
| GAA_FLAG_SKIP_ANYCAST, NULL, adapter_addresses, &buf_size);
|
||||
}
|
||||
|
|
|
@ -152,7 +152,7 @@ namespace
|
|||
}
|
||||
}
|
||||
|
||||
// return true of the first argument is a better canidate for removal, i.e.
|
||||
// return true of the first argument is a better candidate for removal, i.e.
|
||||
// less important to keep
|
||||
struct immutable_item_comparator
|
||||
{
|
||||
|
|
|
@ -803,7 +803,7 @@ namespace libtorrent
|
|||
m_connected = false;
|
||||
if (!m_download_queue.empty())
|
||||
m_counters.inc_stats_counter(counters::num_peers_down_requests, -1);
|
||||
|
||||
|
||||
// defensive
|
||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||
// if t is NULL, we better not be connecting, since
|
||||
|
@ -990,13 +990,13 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(is_single_thread());
|
||||
return m_request_queue;
|
||||
}
|
||||
|
||||
|
||||
std::vector<pending_block> const& peer_connection::download_queue() const
|
||||
{
|
||||
TORRENT_ASSERT(is_single_thread());
|
||||
return m_download_queue;
|
||||
}
|
||||
|
||||
|
||||
std::vector<peer_request> const& peer_connection::upload_queue() const
|
||||
{
|
||||
TORRENT_ASSERT(is_single_thread());
|
||||
|
@ -1878,7 +1878,7 @@ namespace libtorrent
|
|||
m_have_piece.set_bit(index);
|
||||
++m_num_pieces;
|
||||
|
||||
// if the peer is downloading stuff, it must have metadata
|
||||
// if the peer is downloading stuff, it must have metadata
|
||||
m_has_metadata = true;
|
||||
|
||||
// only update the piece_picker if
|
||||
|
@ -2576,9 +2576,9 @@ namespace libtorrent
|
|||
{
|
||||
check_postcondition(boost::shared_ptr<torrent> const& t_
|
||||
, bool init_check = true): t(t_) { if (init_check) check(); }
|
||||
|
||||
|
||||
~check_postcondition() { check(); }
|
||||
|
||||
|
||||
void check()
|
||||
{
|
||||
if (!t->is_seed())
|
||||
|
@ -2596,7 +2596,7 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
shared_ptr<torrent> t;
|
||||
};
|
||||
#endif
|
||||
|
@ -3229,7 +3229,7 @@ namespace libtorrent
|
|||
|
||||
disconnect_if_redundant();
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------
|
||||
// --------- HAVE NONE ---------
|
||||
// -----------------------------
|
||||
|
@ -3495,8 +3495,8 @@ namespace libtorrent
|
|||
|
||||
if (t->alerts().should_post<block_downloading_alert>())
|
||||
{
|
||||
t->alerts().emplace_alert<block_downloading_alert>(t->get_handle(),
|
||||
remote(), pid(), block.block_index, block.piece_index);
|
||||
t->alerts().emplace_alert<block_downloading_alert>(t->get_handle()
|
||||
, remote(), pid(), block.block_index, block.piece_index);
|
||||
}
|
||||
|
||||
pending_block pb(block);
|
||||
|
@ -3643,6 +3643,8 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(is_single_thread());
|
||||
INVARIANT_CHECK;
|
||||
|
||||
TORRENT_ASSERT(!is_connecting());
|
||||
|
||||
if (m_choked)
|
||||
{
|
||||
TORRENT_ASSERT(m_peer_info == NULL
|
||||
|
@ -4082,6 +4084,15 @@ namespace libtorrent
|
|||
, op, ec.message().c_str());
|
||||
break;
|
||||
}
|
||||
|
||||
if (ec == error_code(boost::asio::error::eof
|
||||
, boost::asio::error::get_misc_category())
|
||||
&& !in_handshake()
|
||||
&& !is_connecting()
|
||||
&& clock_type::now() - connected_time() < seconds(15))
|
||||
{
|
||||
peer_log(peer_log_alert::info, "SHORT_LIVED_DISCONNECT", "");
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((m_channel_state[upload_channel] & peer_info::bw_network) == 0)
|
||||
|
@ -4955,8 +4966,8 @@ namespace libtorrent
|
|||
boost::int64_t piece_size = t->torrent_file().piece_length();
|
||||
|
||||
if (m_remote_dl_rate > 0)
|
||||
m_remote_dl_rate = int((m_remote_dl_rate * 2 / 3) +
|
||||
((boost::int64_t(m_remote_pieces_dled) * piece_size / 3) / 60));
|
||||
m_remote_dl_rate = int((m_remote_dl_rate * 2 / 3)
|
||||
+ ((boost::int64_t(m_remote_pieces_dled) * piece_size / 3) / 60));
|
||||
else
|
||||
m_remote_dl_rate = int(boost::int64_t(m_remote_pieces_dled)
|
||||
* piece_size / 60);
|
||||
|
@ -5355,7 +5366,7 @@ namespace libtorrent
|
|||
disconnect(j->error.ec, op_file_read);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (j->ret != r.length)
|
||||
{
|
||||
// handle_disk_error may disconnect us
|
||||
|
@ -5715,7 +5726,7 @@ namespace libtorrent
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!can_read())
|
||||
{
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
|
@ -5980,8 +5991,11 @@ namespace libtorrent
|
|||
|
||||
if (error)
|
||||
{
|
||||
TORRENT_ASSERT_VAL(error.value() != 0, error.value());
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
peer_log(peer_log_alert::info, "ERROR", "in peer_connection::on_receive_data_nb error: %s"
|
||||
peer_log(peer_log_alert::info, "ERROR"
|
||||
, "in peer_connection::on_receive_data_nb error: (%s:%d) %s"
|
||||
, error.category().name(), error.value()
|
||||
, error.message().c_str());
|
||||
#endif
|
||||
on_receive(error, bytes_transferred);
|
||||
|
@ -6106,8 +6120,10 @@ namespace libtorrent
|
|||
{
|
||||
TORRENT_ASSERT(is_single_thread());
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
peer_log(peer_log_alert::incoming, "ON_RECEIVE_DATA", "bytes: %d error: %s"
|
||||
, int(bytes_transferred), error.message().c_str());
|
||||
peer_log(peer_log_alert::incoming, "ON_RECEIVE_DATA"
|
||||
, "bytes: %d error: (%s:%d) %s"
|
||||
, int(bytes_transferred), error.category().name(), error.value()
|
||||
, error.message().c_str());
|
||||
#endif
|
||||
|
||||
// submit all disk jobs later
|
||||
|
@ -6836,7 +6852,7 @@ namespace libtorrent
|
|||
time_duration d;
|
||||
d = aux::time_now() - m_last_sent;
|
||||
if (total_seconds(d) < timeout() / 2) return;
|
||||
|
||||
|
||||
if (m_connecting) return;
|
||||
if (in_handshake()) return;
|
||||
|
||||
|
|
|
@ -2823,8 +2823,6 @@ get_out:
|
|||
if (num_blocks <= 0) return 0;
|
||||
}
|
||||
|
||||
TORRENT_ASSERT(num_blocks >= 0 || prefer_contiguous_blocks > 0);
|
||||
|
||||
if (num_blocks <= 0) return 0;
|
||||
if (options & on_parole) return num_blocks;
|
||||
|
||||
|
|
|
@ -54,8 +54,12 @@ boost::asio::mutable_buffer receive_buffer::reserve(int size)
|
|||
{
|
||||
TORRENT_ASSERT(size > 0);
|
||||
TORRENT_ASSERT(!m_disk_recv_buffer);
|
||||
m_recv_buffer.resize(m_recv_pos + size);
|
||||
return boost::asio::buffer(&m_recv_buffer[m_recv_pos], size);
|
||||
// this is unintuitive, but we used to use m_recv_pos in this function when
|
||||
// we should have used m_recv_end. perhaps they always happen to be equal
|
||||
TORRENT_ASSERT(m_recv_pos == m_recv_end);
|
||||
|
||||
m_recv_buffer.resize(m_recv_end + size);
|
||||
return boost::asio::buffer(&m_recv_buffer[0] + m_recv_end, size);
|
||||
}
|
||||
|
||||
int receive_buffer::reserve(boost::array<boost::asio::mutable_buffer, 2>& vec, int size)
|
||||
|
@ -64,41 +68,48 @@ int receive_buffer::reserve(boost::array<boost::asio::mutable_buffer, 2>& vec, i
|
|||
TORRENT_ASSERT(m_recv_pos >= 0);
|
||||
TORRENT_ASSERT(m_packet_size > 0);
|
||||
|
||||
// normalize() must be called before receiving more data
|
||||
TORRENT_ASSERT(m_recv_start == 0);
|
||||
|
||||
// this is unintuitive, but we used to use m_recv_pos in this function when
|
||||
// we should have used m_recv_end. perhaps they always happen to be equal
|
||||
TORRENT_ASSERT(m_recv_pos == m_recv_end);
|
||||
|
||||
int num_bufs;
|
||||
int regular_buf_size = regular_buffer_size();
|
||||
int const regular_buf_size = regular_buffer_size();
|
||||
|
||||
if (int(m_recv_buffer.size()) < regular_buf_size)
|
||||
m_recv_buffer.resize(round_up8(regular_buf_size));
|
||||
|
||||
if (!m_disk_recv_buffer || regular_buf_size >= m_recv_pos + size)
|
||||
if (!m_disk_recv_buffer || regular_buf_size >= m_recv_end + size)
|
||||
{
|
||||
// only receive into regular buffer
|
||||
TORRENT_ASSERT(m_recv_pos + size <= int(m_recv_buffer.size()));
|
||||
vec[0] = boost::asio::buffer(&m_recv_buffer[m_recv_pos], size);
|
||||
TORRENT_ASSERT(m_recv_end + size <= int(m_recv_buffer.size()));
|
||||
vec[0] = boost::asio::buffer(&m_recv_buffer[0] + m_recv_end, size);
|
||||
TORRENT_ASSERT(boost::asio::buffer_size(vec[0]) > 0);
|
||||
num_bufs = 1;
|
||||
}
|
||||
else if (m_recv_pos >= regular_buf_size)
|
||||
else if (m_recv_end >= regular_buf_size)
|
||||
{
|
||||
// only receive into disk buffer
|
||||
TORRENT_ASSERT(m_recv_pos - regular_buf_size >= 0);
|
||||
TORRENT_ASSERT(m_recv_pos - regular_buf_size + size <= m_disk_recv_buffer_size);
|
||||
vec[0] = boost::asio::buffer(m_disk_recv_buffer.get() + m_recv_pos - regular_buf_size, size);
|
||||
TORRENT_ASSERT(m_recv_end - regular_buf_size >= 0);
|
||||
TORRENT_ASSERT(m_recv_end - regular_buf_size + size <= m_disk_recv_buffer_size);
|
||||
vec[0] = boost::asio::buffer(m_disk_recv_buffer.get() + m_recv_end - regular_buf_size, size);
|
||||
TORRENT_ASSERT(boost::asio::buffer_size(vec[0]) > 0);
|
||||
num_bufs = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// receive into both regular and disk buffer
|
||||
TORRENT_ASSERT(size + m_recv_pos > regular_buf_size);
|
||||
TORRENT_ASSERT(m_recv_pos < regular_buf_size);
|
||||
TORRENT_ASSERT(size + m_recv_end > regular_buf_size);
|
||||
TORRENT_ASSERT(m_recv_end < regular_buf_size);
|
||||
TORRENT_ASSERT(size - regular_buf_size
|
||||
+ m_recv_pos <= m_disk_recv_buffer_size);
|
||||
+ m_recv_end <= m_disk_recv_buffer_size);
|
||||
|
||||
vec[0] = boost::asio::buffer(&m_recv_buffer[m_recv_pos]
|
||||
, regular_buf_size - m_recv_pos);
|
||||
vec[0] = boost::asio::buffer(&m_recv_buffer[0] + m_recv_end
|
||||
, regular_buf_size - m_recv_end);
|
||||
vec[1] = boost::asio::buffer(m_disk_recv_buffer.get()
|
||||
, size - regular_buf_size + m_recv_pos);
|
||||
, size - regular_buf_size + m_recv_end);
|
||||
TORRENT_ASSERT(boost::asio::buffer_size(vec[0])
|
||||
+ boost::asio::buffer_size(vec[1])> 0);
|
||||
num_bufs = 2;
|
||||
|
@ -109,9 +120,9 @@ int receive_buffer::reserve(boost::array<boost::asio::mutable_buffer, 2>& vec, i
|
|||
|
||||
int receive_buffer::advance_pos(int bytes)
|
||||
{
|
||||
int packet_size = m_soft_packet_size ? m_soft_packet_size : m_packet_size;
|
||||
int limit = packet_size > m_recv_pos ? packet_size - m_recv_pos : packet_size;
|
||||
int sub_transferred = (std::min)(bytes, limit);
|
||||
int const packet_size = m_soft_packet_size ? m_soft_packet_size : m_packet_size;
|
||||
int const limit = packet_size > m_recv_pos ? packet_size - m_recv_pos : packet_size;
|
||||
int const sub_transferred = (std::min)(bytes, limit);
|
||||
m_recv_pos += sub_transferred;
|
||||
if (m_recv_pos >= m_soft_packet_size) m_soft_packet_size = 0;
|
||||
return sub_transferred;
|
||||
|
@ -174,7 +185,8 @@ buffer::const_interval receive_buffer::get() const
|
|||
TORRENT_ASSERT(m_recv_pos == 0);
|
||||
return buffer::interval(0,0);
|
||||
}
|
||||
int rcv_pos = (std::min)(m_recv_pos, int(m_recv_buffer.size()));
|
||||
|
||||
int rcv_pos = (std::min)(m_recv_pos, int(m_recv_buffer.size()) - m_recv_start);
|
||||
return buffer::const_interval(&m_recv_buffer[0] + m_recv_start
|
||||
, &m_recv_buffer[0] + m_recv_start + rcv_pos);
|
||||
}
|
||||
|
@ -194,34 +206,48 @@ buffer::interval receive_buffer::mutable_buffer()
|
|||
, &m_recv_buffer[0] + m_recv_start + rcv_pos);
|
||||
}
|
||||
|
||||
void receive_buffer::mutable_buffers(std::vector<boost::asio::mutable_buffer>& vec, int bytes)
|
||||
// TODO: 2 should this take a boost::array<..., 2> instead? it could return the
|
||||
// number of buffers added, just like reserve.
|
||||
void receive_buffer::mutable_buffers(std::vector<boost::asio::mutable_buffer>& vec, int const bytes)
|
||||
{
|
||||
using namespace boost;
|
||||
namespace asio = boost::asio;
|
||||
|
||||
// bytes is the number of bytes we just received, and m_recv_pos has
|
||||
// already been adjusted for these bytes. The receive pos immediately
|
||||
// before we received these bytes was (m_recv_pos - bytes)
|
||||
|
||||
int const last_recv_pos = m_recv_pos - bytes;
|
||||
TORRENT_ASSERT(bytes <= m_recv_pos);
|
||||
|
||||
int regular_buf_size = regular_buffer_size();
|
||||
// the number of bytes in the current packet that are being received into a
|
||||
// regular receive buffer (as opposed to a disk cache buffer)
|
||||
int const regular_buf_size = regular_buffer_size();
|
||||
|
||||
TORRENT_ASSERT(regular_buf_size >= 0);
|
||||
if (!m_disk_recv_buffer || regular_buf_size >= m_recv_pos)
|
||||
{
|
||||
// we just received into a regular disk buffer
|
||||
vec.push_back(asio::mutable_buffer(&m_recv_buffer[0] + m_recv_start
|
||||
+ m_recv_pos - bytes, bytes));
|
||||
+ last_recv_pos, bytes));
|
||||
}
|
||||
else if (m_recv_pos - bytes >= regular_buf_size)
|
||||
else if (last_recv_pos >= regular_buf_size)
|
||||
{
|
||||
vec.push_back(asio::mutable_buffer(m_disk_recv_buffer.get() + m_recv_pos
|
||||
- regular_buf_size - bytes, bytes));
|
||||
// we only received into a disk buffer
|
||||
vec.push_back(asio::mutable_buffer(m_disk_recv_buffer.get()
|
||||
+ last_recv_pos - regular_buf_size, bytes));
|
||||
}
|
||||
else
|
||||
{
|
||||
TORRENT_ASSERT(m_recv_pos - bytes < regular_buf_size);
|
||||
// we received into a regular and a disk buffer
|
||||
TORRENT_ASSERT(last_recv_pos < regular_buf_size);
|
||||
TORRENT_ASSERT(m_recv_pos > regular_buf_size);
|
||||
vec.push_back(asio::mutable_buffer(&m_recv_buffer[0] + m_recv_start + m_recv_pos - bytes
|
||||
, regular_buf_size - (m_recv_start + m_recv_pos - bytes)));
|
||||
vec.push_back(asio::mutable_buffer(&m_recv_buffer[0] + m_recv_start + last_recv_pos
|
||||
, regular_buf_size - last_recv_pos));
|
||||
vec.push_back(asio::mutable_buffer(m_disk_recv_buffer.get()
|
||||
, m_recv_pos - regular_buf_size));
|
||||
}
|
||||
|
||||
#if defined TORRENT_DEBUG || defined TORRENT_RELEASE_ASSERTS
|
||||
#if TORRENT_USE_ASSERTS
|
||||
int vec_bytes = 0;
|
||||
for (std::vector<asio::mutable_buffer>::iterator i = vec.begin();
|
||||
i != vec.end(); ++i)
|
||||
|
|
|
@ -106,11 +106,12 @@ namespace libtorrent
|
|||
TORRENT_SYNC_CALL2(save_state, &e, flags);
|
||||
}
|
||||
|
||||
void session_handle::load_state(bdecode_node const& e)
|
||||
void session_handle::load_state(bdecode_node const& e
|
||||
, boost::uint32_t const flags)
|
||||
{
|
||||
// this needs to be synchronized since the lifespan
|
||||
// of e is tied to the caller
|
||||
TORRENT_SYNC_CALL1(load_state, &e);
|
||||
TORRENT_SYNC_CALL2(load_state, &e, flags);
|
||||
}
|
||||
|
||||
void session_handle::get_torrent_status(std::vector<torrent_status>* ret
|
||||
|
@ -607,7 +608,7 @@ namespace libtorrent
|
|||
void session_handle::start_dht(entry const& startup_state)
|
||||
{
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
TORRENT_ASYNC_CALL1(start_dht, startup_state);
|
||||
TORRENT_ASYNC_CALL1(start_dht_deprecated, startup_state);
|
||||
#else
|
||||
TORRENT_UNUSED(startup_state);
|
||||
#endif
|
||||
|
@ -644,7 +645,8 @@ namespace libtorrent
|
|||
void session_handle::load_country_db(wchar_t const*) {}
|
||||
#endif // TORRENT_USE_WSTRING
|
||||
|
||||
void session_handle::load_state(entry const& ses_state)
|
||||
void session_handle::load_state(entry const& ses_state
|
||||
, boost::uint32_t const flags)
|
||||
{
|
||||
if (ses_state.type() == entry::undefined_t) return;
|
||||
std::vector<char> buf;
|
||||
|
@ -660,7 +662,7 @@ namespace libtorrent
|
|||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
if (ret != 0) throw libtorrent_exception(ec);
|
||||
#endif
|
||||
TORRENT_SYNC_CALL1(load_state, &e);
|
||||
TORRENT_SYNC_CALL2(load_state, &e, flags);
|
||||
}
|
||||
|
||||
entry session_handle::state() const
|
||||
|
@ -670,7 +672,8 @@ namespace libtorrent
|
|||
return ret;
|
||||
}
|
||||
|
||||
void session_handle::load_state(lazy_entry const& ses_state)
|
||||
void session_handle::load_state(lazy_entry const& ses_state
|
||||
, boost::uint32_t const flags)
|
||||
{
|
||||
if (ses_state.type() == lazy_entry::none_t) return;
|
||||
std::pair<char const*, int> buf = ses_state.data_section();
|
||||
|
@ -685,7 +688,7 @@ namespace libtorrent
|
|||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
if (ret != 0) throw libtorrent_exception(ec);
|
||||
#endif
|
||||
TORRENT_SYNC_CALL1(load_state, &e);
|
||||
TORRENT_SYNC_CALL2(load_state, &e, flags);
|
||||
}
|
||||
#endif // TORRENT_NO_DEPRECATE
|
||||
|
||||
|
|
|
@ -640,12 +640,16 @@ namespace aux {
|
|||
void session_impl::save_state(entry* eptr, boost::uint32_t flags) const
|
||||
{
|
||||
TORRENT_ASSERT(is_single_thread());
|
||||
TORRENT_UNUSED(flags); // potentially unused
|
||||
|
||||
entry& e = *eptr;
|
||||
// make it a dict
|
||||
e.dict();
|
||||
|
||||
entry::dictionary_type& sett = e["settings"].dict();
|
||||
save_settings_to_dict(m_settings, sett);
|
||||
if (flags & session::save_settings)
|
||||
{
|
||||
entry::dictionary_type& sett = e["settings"].dict();
|
||||
save_settings_to_dict(m_settings, sett);
|
||||
}
|
||||
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
if (flags & session::save_dht_settings)
|
||||
|
@ -707,7 +711,8 @@ namespace aux {
|
|||
return proxy_settings(m_settings);
|
||||
}
|
||||
|
||||
void session_impl::load_state(bdecode_node const* e)
|
||||
void session_impl::load_state(bdecode_node const* e
|
||||
, boost::uint32_t const flags = 0xffffffff)
|
||||
{
|
||||
TORRENT_ASSERT(is_single_thread());
|
||||
|
||||
|
@ -717,77 +722,86 @@ namespace aux {
|
|||
#ifndef TORRENT_DISABLE_DHT
|
||||
bool need_update_dht = false;
|
||||
// load from the old settings names
|
||||
settings = e->dict_find_dict("dht");
|
||||
if (settings)
|
||||
if (flags & session::save_dht_settings)
|
||||
{
|
||||
bdecode_node val;
|
||||
val = settings.dict_find_int("max_peers_reply");
|
||||
if (val) m_dht_settings.max_peers_reply = val.int_value();
|
||||
val = settings.dict_find_int("search_branching");
|
||||
if (val) m_dht_settings.search_branching = val.int_value();
|
||||
val = settings.dict_find_int("max_fail_count");
|
||||
if (val) m_dht_settings.max_fail_count = val.int_value();
|
||||
val = settings.dict_find_int("max_torrents");
|
||||
if (val) m_dht_settings.max_torrents = val.int_value();
|
||||
val = settings.dict_find_int("max_dht_items");
|
||||
if (val) m_dht_settings.max_dht_items = val.int_value();
|
||||
val = settings.dict_find_int("max_peers");
|
||||
if (val) m_dht_settings.max_peers = val.int_value();
|
||||
val = settings.dict_find_int("max_torrent_search_reply");
|
||||
if (val) m_dht_settings.max_torrent_search_reply = val.int_value();
|
||||
val = settings.dict_find_int("restrict_routing_ips");
|
||||
if (val) m_dht_settings.restrict_routing_ips = val.int_value();
|
||||
val = settings.dict_find_int("restrict_search_ips");
|
||||
if (val) m_dht_settings.restrict_search_ips = val.int_value();
|
||||
val = settings.dict_find_int("extended_routing_table");
|
||||
if (val) m_dht_settings.extended_routing_table = val.int_value();
|
||||
val = settings.dict_find_int("aggressive_lookups");
|
||||
if (val) m_dht_settings.aggressive_lookups = val.int_value();
|
||||
val = settings.dict_find_int("privacy_lookups");
|
||||
if (val) m_dht_settings.privacy_lookups = val.int_value();
|
||||
val = settings.dict_find_int("enforce_node_id");
|
||||
if (val) m_dht_settings.enforce_node_id = val.int_value();
|
||||
val = settings.dict_find_int("ignore_dark_internet");
|
||||
if (val) m_dht_settings.ignore_dark_internet = val.int_value();
|
||||
val = settings.dict_find_int("block_timeout");
|
||||
if (val) m_dht_settings.block_timeout = val.int_value();
|
||||
val = settings.dict_find_int("block_ratelimit");
|
||||
if (val) m_dht_settings.block_ratelimit = val.int_value();
|
||||
val = settings.dict_find_int("read_only");
|
||||
if (val) m_dht_settings.read_only = val.int_value();
|
||||
val = settings.dict_find_int("item_lifetime");
|
||||
if (val) m_dht_settings.item_lifetime = val.int_value();
|
||||
settings = e->dict_find_dict("dht");
|
||||
if (settings)
|
||||
{
|
||||
bdecode_node val;
|
||||
val = settings.dict_find_int("max_peers_reply");
|
||||
if (val) m_dht_settings.max_peers_reply = val.int_value();
|
||||
val = settings.dict_find_int("search_branching");
|
||||
if (val) m_dht_settings.search_branching = val.int_value();
|
||||
val = settings.dict_find_int("max_fail_count");
|
||||
if (val) m_dht_settings.max_fail_count = val.int_value();
|
||||
val = settings.dict_find_int("max_torrents");
|
||||
if (val) m_dht_settings.max_torrents = val.int_value();
|
||||
val = settings.dict_find_int("max_dht_items");
|
||||
if (val) m_dht_settings.max_dht_items = val.int_value();
|
||||
val = settings.dict_find_int("max_peers");
|
||||
if (val) m_dht_settings.max_peers = val.int_value();
|
||||
val = settings.dict_find_int("max_torrent_search_reply");
|
||||
if (val) m_dht_settings.max_torrent_search_reply = val.int_value();
|
||||
val = settings.dict_find_int("restrict_routing_ips");
|
||||
if (val) m_dht_settings.restrict_routing_ips = val.int_value();
|
||||
val = settings.dict_find_int("restrict_search_ips");
|
||||
if (val) m_dht_settings.restrict_search_ips = val.int_value();
|
||||
val = settings.dict_find_int("extended_routing_table");
|
||||
if (val) m_dht_settings.extended_routing_table = val.int_value();
|
||||
val = settings.dict_find_int("aggressive_lookups");
|
||||
if (val) m_dht_settings.aggressive_lookups = val.int_value();
|
||||
val = settings.dict_find_int("privacy_lookups");
|
||||
if (val) m_dht_settings.privacy_lookups = val.int_value();
|
||||
val = settings.dict_find_int("enforce_node_id");
|
||||
if (val) m_dht_settings.enforce_node_id = val.int_value();
|
||||
val = settings.dict_find_int("ignore_dark_internet");
|
||||
if (val) m_dht_settings.ignore_dark_internet = val.int_value();
|
||||
val = settings.dict_find_int("block_timeout");
|
||||
if (val) m_dht_settings.block_timeout = val.int_value();
|
||||
val = settings.dict_find_int("block_ratelimit");
|
||||
if (val) m_dht_settings.block_ratelimit = val.int_value();
|
||||
val = settings.dict_find_int("read_only");
|
||||
if (val) m_dht_settings.read_only = val.int_value();
|
||||
val = settings.dict_find_int("item_lifetime");
|
||||
if (val) m_dht_settings.item_lifetime = val.int_value();
|
||||
}
|
||||
}
|
||||
|
||||
settings = e->dict_find_dict("dht state");
|
||||
if (settings)
|
||||
if (flags & session::save_dht_state)
|
||||
{
|
||||
m_dht_state = settings;
|
||||
need_update_dht = true;
|
||||
settings = e->dict_find_dict("dht state");
|
||||
if (settings)
|
||||
{
|
||||
m_dht_state = settings;
|
||||
need_update_dht = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
bool need_update_proxy = false;
|
||||
settings = e->dict_find_dict("proxy");
|
||||
if (settings)
|
||||
if (flags & session::save_proxy)
|
||||
{
|
||||
bdecode_node val;
|
||||
val = settings.dict_find_int("port");
|
||||
if (val) m_settings.set_int(settings_pack::proxy_port, val.int_value());
|
||||
val = settings.dict_find_int("type");
|
||||
if (val) m_settings.set_int(settings_pack::proxy_type, val.int_value());
|
||||
val = settings.dict_find_int("proxy_hostnames");
|
||||
if (val) m_settings.set_bool(settings_pack::proxy_hostnames, val.int_value());
|
||||
val = settings.dict_find_int("proxy_peer_connections");
|
||||
if (val) m_settings.set_bool(settings_pack::proxy_peer_connections, val.int_value());
|
||||
val = settings.dict_find_string("hostname");
|
||||
if (val) m_settings.set_str(settings_pack::proxy_hostname, val.string_value());
|
||||
val = settings.dict_find_string("password");
|
||||
if (val) m_settings.set_str(settings_pack::proxy_password, val.string_value());
|
||||
val = settings.dict_find_string("username");
|
||||
if (val) m_settings.set_str(settings_pack::proxy_username, val.string_value());
|
||||
need_update_proxy = true;
|
||||
settings = e->dict_find_dict("proxy");
|
||||
if (settings)
|
||||
{
|
||||
bdecode_node val;
|
||||
val = settings.dict_find_int("port");
|
||||
if (val) m_settings.set_int(settings_pack::proxy_port, val.int_value());
|
||||
val = settings.dict_find_int("type");
|
||||
if (val) m_settings.set_int(settings_pack::proxy_type, val.int_value());
|
||||
val = settings.dict_find_int("proxy_hostnames");
|
||||
if (val) m_settings.set_bool(settings_pack::proxy_hostnames, val.int_value());
|
||||
val = settings.dict_find_int("proxy_peer_connections");
|
||||
if (val) m_settings.set_bool(settings_pack::proxy_peer_connections, val.int_value());
|
||||
val = settings.dict_find_string("hostname");
|
||||
if (val) m_settings.set_str(settings_pack::proxy_hostname, val.string_value());
|
||||
val = settings.dict_find_string("password");
|
||||
if (val) m_settings.set_str(settings_pack::proxy_password, val.string_value());
|
||||
val = settings.dict_find_string("username");
|
||||
if (val) m_settings.set_str(settings_pack::proxy_username, val.string_value());
|
||||
need_update_proxy = true;
|
||||
}
|
||||
}
|
||||
|
||||
settings = e->dict_find_dict("encryption");
|
||||
|
@ -804,39 +818,49 @@ namespace aux {
|
|||
if (val) m_settings.set_int(settings_pack::allowed_enc_level, val.int_value());
|
||||
}
|
||||
|
||||
settings = e->dict_find_list("feeds");
|
||||
if (settings)
|
||||
if (flags & session::save_feeds)
|
||||
{
|
||||
m_feeds.reserve(settings.list_size());
|
||||
for (int i = 0; i < settings.list_size(); ++i)
|
||||
settings = e->dict_find_list("feeds");
|
||||
if (settings)
|
||||
{
|
||||
if (settings.list_at(i).type() != bdecode_node::dict_t) continue;
|
||||
boost::shared_ptr<feed> f(new_feed(*this, feed_settings()));
|
||||
f->load_state(settings.list_at(i));
|
||||
f->update_feed();
|
||||
m_feeds.push_back(f);
|
||||
m_feeds.reserve(settings.list_size());
|
||||
for (int i = 0; i < settings.list_size(); ++i)
|
||||
{
|
||||
if (settings.list_at(i).type() != bdecode_node::dict_t) continue;
|
||||
boost::shared_ptr<feed> f(new_feed(*this, feed_settings()));
|
||||
f->load_state(settings.list_at(i));
|
||||
f->update_feed();
|
||||
m_feeds.push_back(f);
|
||||
}
|
||||
update_rss_feeds();
|
||||
}
|
||||
update_rss_feeds();
|
||||
}
|
||||
#endif
|
||||
|
||||
settings = e->dict_find_dict("settings");
|
||||
if (settings)
|
||||
{
|
||||
// apply_settings_pack will update dht and proxy
|
||||
boost::shared_ptr<settings_pack> pack = load_pack_from_dict(settings);
|
||||
apply_settings_pack(pack);
|
||||
}
|
||||
else
|
||||
if (flags & session::save_settings)
|
||||
{
|
||||
settings = e->dict_find_dict("settings");
|
||||
if (settings)
|
||||
{
|
||||
// apply_settings_pack will update dht and proxy
|
||||
boost::shared_ptr<settings_pack> pack = load_pack_from_dict(settings);
|
||||
apply_settings_pack(pack);
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
if (need_update_dht) update_dht();
|
||||
need_update_dht = false;
|
||||
#endif
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
if (need_update_proxy) update_proxy();
|
||||
need_update_proxy = false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
if (need_update_dht) update_dht();
|
||||
#endif
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
if (need_update_proxy) update_proxy();
|
||||
#endif
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
for (ses_extension_list_t::iterator i = m_ses_extensions.begin()
|
||||
, end(m_ses_extensions.end()); i != end; ++i)
|
||||
|
@ -3663,7 +3687,8 @@ namespace aux {
|
|||
t->log_to_all_peers("auto manager pausing torrent");
|
||||
#endif
|
||||
// use graceful pause for auto-managed torrents
|
||||
t->set_allow_peers(false, true);
|
||||
t->set_allow_peers(false, torrent::flag_graceful_pause
|
||||
| torrent::flag_clear_disk_cache);
|
||||
t->set_announce_to_dht(false);
|
||||
t->set_announce_to_trackers(false);
|
||||
t->set_announce_to_lsd(false);
|
||||
|
@ -4141,6 +4166,7 @@ namespace aux {
|
|||
|
||||
int const allowed_upload_slots = unchoke_sort(peers, max_upload_rate
|
||||
, unchoke_interval, m_settings);
|
||||
|
||||
m_stats_counters.set_value(counters::num_unchoke_slots
|
||||
, allowed_upload_slots);
|
||||
|
||||
|
@ -5594,6 +5620,12 @@ namespace aux {
|
|||
if (!m_dht) return entry();
|
||||
return m_dht->state();
|
||||
}
|
||||
|
||||
void session_impl::start_dht_deprecated(entry const& startup_state)
|
||||
{
|
||||
m_settings.set_bool(settings_pack::enable_dht, true);
|
||||
start_dht(startup_state);
|
||||
}
|
||||
#endif
|
||||
|
||||
void session_impl::add_dht_node_name(std::pair<std::string, int> const& node)
|
||||
|
@ -6024,9 +6056,7 @@ namespace aux {
|
|||
|
||||
void session_impl::update_unchoke_limit()
|
||||
{
|
||||
int unchoke_limit = m_settings.get_int(settings_pack::unchoke_slots_limit);
|
||||
|
||||
int allowed_upload_slots = unchoke_limit;
|
||||
int allowed_upload_slots = m_settings.get_int(settings_pack::unchoke_slots_limit);
|
||||
|
||||
if (allowed_upload_slots < 0)
|
||||
allowed_upload_slots = (std::numeric_limits<int>::max)();
|
||||
|
|
|
@ -355,10 +355,10 @@ namespace libtorrent
|
|||
|
||||
// the total number of blocks run through SHA-1 hashing
|
||||
METRIC(disk, num_blocks_hashed)
|
||||
|
||||
|
||||
// the number of blocks read from the disk cache
|
||||
METRIC(disk, num_blocks_cache_hits)
|
||||
|
||||
|
||||
// the number of disk I/O operation for reads and writes. One disk
|
||||
// operation may transfer more then one block.
|
||||
METRIC(disk, num_write_ops)
|
||||
|
|
|
@ -204,7 +204,7 @@ namespace libtorrent
|
|||
SET(support_merkle_torrents, true, 0),
|
||||
SET(report_redundant_bytes, true, 0),
|
||||
SET_NOPREV(listen_system_port_fallback, true, 0),
|
||||
SET(use_disk_cache_pool, false, 0),
|
||||
SET(use_disk_cache_pool, true, 0),
|
||||
SET_NOPREV(announce_crypto_support, true, 0),
|
||||
SET_NOPREV(enable_upnp, true, &session_impl::update_upnp),
|
||||
SET_NOPREV(enable_natpmp, true, &session_impl::update_natpmp),
|
||||
|
@ -237,7 +237,7 @@ namespace libtorrent
|
|||
SET(max_failcount, 3, &session_impl::update_max_failcount),
|
||||
SET(min_reconnect_time, 60, 0),
|
||||
SET(peer_connect_timeout, 15, 0),
|
||||
SET(connection_speed, 6, &session_impl::update_connection_speed),
|
||||
SET(connection_speed, 10, &session_impl::update_connection_speed),
|
||||
SET(inactivity_timeout, 600, 0),
|
||||
SET(unchoke_interval, 15, 0),
|
||||
SET(optimistic_unchoke_interval, 30, 0),
|
||||
|
|
|
@ -1173,6 +1173,8 @@ namespace libtorrent
|
|||
TORRENT_UNUSED(j);
|
||||
TORRENT_UNUSED(b);
|
||||
|
||||
if (m_abort) return;
|
||||
|
||||
update_gauge();
|
||||
// some peers that previously was no longer interesting may
|
||||
// now have become interesting, since we lack this one piece now.
|
||||
|
@ -2201,6 +2203,8 @@ namespace libtorrent
|
|||
return;
|
||||
}
|
||||
|
||||
if (m_abort) return;
|
||||
|
||||
state_updated();
|
||||
|
||||
if (m_add_torrent_params)
|
||||
|
@ -2447,6 +2451,8 @@ namespace libtorrent
|
|||
dec_refcount("force_recheck");
|
||||
state_updated();
|
||||
|
||||
if (m_abort) return;
|
||||
|
||||
if (j->ret == piece_manager::fatal_disk_error)
|
||||
{
|
||||
handle_disk_error(j);
|
||||
|
@ -2476,7 +2482,10 @@ namespace libtorrent
|
|||
|
||||
int num_outstanding = settings().get_int(settings_pack::checking_mem_usage) * block_size()
|
||||
/ m_torrent_file->piece_length();
|
||||
if (num_outstanding <= 0) num_outstanding = 1;
|
||||
// if we only keep a single read operation in-flight at a time, we suffer
|
||||
// significant performance degradation. Always keep at least two jobs
|
||||
// outstanding
|
||||
if (num_outstanding < 2) num_outstanding = 2;
|
||||
|
||||
// we might already have some outstanding jobs, if we were paused and
|
||||
// resumed quickly, before the outstanding jobs completed
|
||||
|
@ -2527,6 +2536,8 @@ namespace libtorrent
|
|||
|
||||
dec_refcount("start_checking");
|
||||
|
||||
if (m_abort) return;
|
||||
|
||||
if (j->ret == piece_manager::disk_check_aborted)
|
||||
{
|
||||
m_checking_piece = 0;
|
||||
|
@ -2668,7 +2679,9 @@ namespace libtorrent
|
|||
{
|
||||
// if we're auto managed. assume we need to be paused until the auto
|
||||
// managed logic runs again (which is triggered further down)
|
||||
pause();
|
||||
// setting flags to 0 prevents the disk cache from being evicted as a
|
||||
// result of this
|
||||
set_allow_peers(false, 0);
|
||||
}
|
||||
|
||||
// we're done checking! (this should cause a call to trigger_auto_manage)
|
||||
|
@ -2844,6 +2857,7 @@ namespace libtorrent
|
|||
, int(peers.size()));
|
||||
#endif
|
||||
|
||||
if (m_abort) return;
|
||||
if (peers.empty()) return;
|
||||
|
||||
if (m_ses.alerts().should_post<dht_reply_alert>())
|
||||
|
@ -3554,7 +3568,7 @@ namespace libtorrent
|
|||
if (ec)
|
||||
debug_log("i2p_resolve error: %s", ec.message().c_str());
|
||||
#endif
|
||||
if (ec || m_ses.is_aborted()) return;
|
||||
if (ec || m_abort || m_ses.is_aborted()) return;
|
||||
|
||||
need_peer_list();
|
||||
torrent_state st = get_peer_list_state();
|
||||
|
@ -3580,7 +3594,7 @@ namespace libtorrent
|
|||
debug_log("peer name lookup error: %s", e.message().c_str());
|
||||
#endif
|
||||
|
||||
if (e || host_list.empty() || m_ses.is_aborted()) return;
|
||||
if (e || m_abort || host_list.empty() || m_ses.is_aborted()) return;
|
||||
|
||||
// TODO: add one peer per IP the hostname resolves to
|
||||
tcp::endpoint host(host_list.front(), port);
|
||||
|
@ -3926,6 +3940,8 @@ namespace libtorrent
|
|||
|
||||
dec_refcount("verify_piece");
|
||||
|
||||
if (m_abort) return;
|
||||
|
||||
int ret = j->ret;
|
||||
if (settings().get_bool(settings_pack::disable_hash_checks))
|
||||
{
|
||||
|
@ -4788,6 +4804,9 @@ namespace libtorrent
|
|||
// seeded by any peer
|
||||
TORRENT_ASSERT(m_super_seeding);
|
||||
|
||||
if (!need_loaded())
|
||||
return -1;
|
||||
|
||||
// do a linear search from the first piece
|
||||
int min_availability = 9999;
|
||||
std::vector<int> avail_vec;
|
||||
|
@ -4820,6 +4839,7 @@ namespace libtorrent
|
|||
avail_vec.push_back(i);
|
||||
}
|
||||
|
||||
if (avail_vec.empty()) return -1;
|
||||
return avail_vec[random() % avail_vec.size()];
|
||||
}
|
||||
|
||||
|
@ -9150,10 +9170,11 @@ namespace libtorrent
|
|||
set_need_save_resume();
|
||||
}
|
||||
|
||||
set_allow_peers(false, graceful);
|
||||
int const flags = graceful ? flag_graceful_pause : 0;
|
||||
set_allow_peers(false, flags | flag_clear_disk_cache);
|
||||
}
|
||||
|
||||
void torrent::do_pause()
|
||||
void torrent::do_pause(bool const clear_disk_cache)
|
||||
{
|
||||
TORRENT_ASSERT(is_single_thread());
|
||||
if (!is_paused()) return;
|
||||
|
@ -9217,7 +9238,7 @@ namespace libtorrent
|
|||
{
|
||||
// this will make the storage close all
|
||||
// files and flush all cached data
|
||||
if (m_storage.get())
|
||||
if (m_storage.get() && clear_disk_cache)
|
||||
{
|
||||
TORRENT_ASSERT(m_storage);
|
||||
m_ses.disk_thread().async_stop_torrent(m_storage.get()
|
||||
|
@ -9317,7 +9338,7 @@ namespace libtorrent
|
|||
set_need_save_resume();
|
||||
}
|
||||
|
||||
void torrent::set_allow_peers(bool b, bool graceful)
|
||||
void torrent::set_allow_peers(bool b, int flags)
|
||||
{
|
||||
TORRENT_ASSERT(is_single_thread());
|
||||
|
||||
|
@ -9327,7 +9348,7 @@ namespace libtorrent
|
|||
// if there are no peers, we must not enter graceful pause mode, and post
|
||||
// the torrent_paused_alert immediately instead.
|
||||
if (m_connections.empty())
|
||||
graceful = false;
|
||||
flags &= ~flag_graceful_pause;
|
||||
|
||||
if (m_allow_peers == b)
|
||||
{
|
||||
|
@ -9336,9 +9357,9 @@ namespace libtorrent
|
|||
// paused mode, we need to actually pause the torrent properly
|
||||
if (m_allow_peers == false
|
||||
&& m_graceful_pause_mode == true
|
||||
&& graceful == false)
|
||||
&& (flags & flag_graceful_pause) == 0)
|
||||
{
|
||||
m_graceful_pause_mode = graceful;
|
||||
m_graceful_pause_mode = false;
|
||||
update_gauge();
|
||||
do_pause();
|
||||
}
|
||||
|
@ -9347,7 +9368,7 @@ namespace libtorrent
|
|||
|
||||
m_allow_peers = b;
|
||||
if (!m_ses.is_paused())
|
||||
m_graceful_pause_mode = graceful;
|
||||
m_graceful_pause_mode = (flags & flag_graceful_pause) ? true : false;
|
||||
|
||||
if (!b)
|
||||
{
|
||||
|
@ -9364,7 +9385,7 @@ namespace libtorrent
|
|||
|
||||
if (!b)
|
||||
{
|
||||
do_pause();
|
||||
do_pause(flags & flag_clear_disk_cache);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -10016,6 +10037,7 @@ namespace libtorrent
|
|||
update_want_peers();
|
||||
}
|
||||
|
||||
// TODO: 2 this should probably be removed
|
||||
void torrent::refresh_explicit_cache(int cache_size)
|
||||
{
|
||||
TORRENT_ASSERT(is_single_thread());
|
||||
|
|
|
@ -923,8 +923,11 @@ int utp_stream::read_buffer_size() const
|
|||
void utp_stream::on_close_reason(void* self, boost::uint16_t close_reason)
|
||||
{
|
||||
utp_stream* s = static_cast<utp_stream*>(self);
|
||||
TORRENT_ASSERT(s->m_impl);
|
||||
s->m_incoming_close_reason = close_reason;
|
||||
|
||||
// it's possible the socket has been unlinked already, in which case m_impl
|
||||
// will be NULL
|
||||
if (s->m_impl)
|
||||
s->m_incoming_close_reason = close_reason;
|
||||
}
|
||||
|
||||
void utp_stream::on_read(void* self, size_t bytes_transferred
|
||||
|
|
|
@ -154,6 +154,7 @@ test-suite libtorrent :
|
|||
test_linked_list.cpp
|
||||
test_file_progress.cpp ]
|
||||
|
||||
[ run test_receive_buffer.cpp ]
|
||||
[ run test_alert_manager.cpp ]
|
||||
[ run test_direct_dht.cpp ]
|
||||
[ run test_magnet.cpp ]
|
||||
|
@ -194,8 +195,8 @@ test-suite libtorrent :
|
|||
[ run test_priority.cpp ]
|
||||
|
||||
# turn these tests into simulations
|
||||
# [ run test_upnp.cpp ]
|
||||
# [ run test_lsd.cpp ]
|
||||
[ run test_upnp.cpp ]
|
||||
[ run test_lsd.cpp ]
|
||||
;
|
||||
|
||||
# these are the tests run on appveyor, while the flapping ones are being
|
||||
|
|
|
@ -18,6 +18,7 @@ test_programs = \
|
|||
test_pe_crypto \
|
||||
test_pex \
|
||||
test_read_piece \
|
||||
test_receive_buffer \
|
||||
test_resume \
|
||||
test_read_resume \
|
||||
test_ssl \
|
||||
|
|
|
@ -94,7 +94,7 @@ void test_checking(int flags = read_only_files)
|
|||
create_directory(combine_path("tmp1_checking", "test_torrent_dir"), ec);
|
||||
if (ec) fprintf(stderr, "ERROR: creating directory test_torrent_dir: (%d) %s\n"
|
||||
, ec.value(), ec.message().c_str());
|
||||
|
||||
|
||||
file_storage fs;
|
||||
std::srand(10);
|
||||
int piece_size = 0x4000;
|
||||
|
|
|
@ -0,0 +1,255 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2016, Arvid Norberg
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the author nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "libtorrent/config.hpp"
|
||||
#include "test.hpp"
|
||||
#include "libtorrent/receive_buffer.hpp"
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
struct allocator : buffer_allocator_interface
|
||||
{
|
||||
void free_disk_buffer(char*) {}
|
||||
char* allocate_disk_buffer(char const*) { TORRENT_ASSERT(false); return NULL; }
|
||||
char* allocate_disk_buffer(bool&
|
||||
, boost::shared_ptr<disk_observer>
|
||||
, char const*) { TORRENT_ASSERT(false); return NULL; }
|
||||
char* async_allocate_disk_buffer(char const*
|
||||
, boost::function<void(char*)> const&) { TORRENT_ASSERT(false); return NULL; }
|
||||
void reclaim_block(block_cache_reference ref) {}
|
||||
};
|
||||
|
||||
TORRENT_TEST(recv_buffer_init)
|
||||
{
|
||||
allocator a;
|
||||
receive_buffer b(a);
|
||||
|
||||
b.cut(0, 10);
|
||||
|
||||
TEST_EQUAL(b.packet_size(), 10);
|
||||
TEST_EQUAL(b.packet_bytes_remaining(), 10);
|
||||
TEST_EQUAL(b.packet_finished(), false);
|
||||
TEST_EQUAL(b.pos(), 0);
|
||||
TEST_EQUAL(b.capacity(), 0);
|
||||
}
|
||||
|
||||
TORRENT_TEST(recv_buffer_pos_at_end_false)
|
||||
{
|
||||
allocator a;
|
||||
receive_buffer b(a);
|
||||
|
||||
b.cut(0, 1000);
|
||||
// allocate some space to receive into
|
||||
boost::array<boost::asio::mutable_buffer, 2> vec;
|
||||
int num_bufs = b.reserve(vec, 1000);
|
||||
|
||||
// since we don't have a disk buffer, there should only be a single
|
||||
// range/buffer
|
||||
TEST_EQUAL(num_bufs, 1);
|
||||
|
||||
b.received(1000);
|
||||
b.advance_pos(999);
|
||||
|
||||
TEST_EQUAL(b.pos_at_end(), false);
|
||||
}
|
||||
|
||||
TORRENT_TEST(recv_buffer_pos_at_end_true)
|
||||
{
|
||||
allocator a;
|
||||
receive_buffer b(a);
|
||||
b.cut(0, 1000);
|
||||
b.reserve(1000);
|
||||
boost::array<boost::asio::mutable_buffer, 2> vec;
|
||||
int num_bufs = b.reserve(vec, 1000);
|
||||
TEST_EQUAL(num_bufs, 1);
|
||||
b.received(1000);
|
||||
b.advance_pos(1000);
|
||||
TEST_EQUAL(b.pos_at_end(), true);
|
||||
}
|
||||
|
||||
TORRENT_TEST(recv_buffer_packet_finished)
|
||||
{
|
||||
allocator a;
|
||||
receive_buffer b(a);
|
||||
// packet_size = 10
|
||||
b.cut(0, 10);
|
||||
b.reserve(1000);
|
||||
boost::array<boost::asio::mutable_buffer, 2> vec;
|
||||
int num_bufs = b.reserve(vec, 1000);
|
||||
TEST_EQUAL(num_bufs, 1);
|
||||
b.received(1000);
|
||||
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
TEST_EQUAL(b.packet_finished(), false);
|
||||
b.advance_pos(1);
|
||||
}
|
||||
TEST_EQUAL(b.packet_finished(), true);
|
||||
}
|
||||
|
||||
TORRENT_TEST(recv_buffer_disk_buffer)
|
||||
{
|
||||
char disk_buffer; // fake disk buffer pointer
|
||||
|
||||
allocator a;
|
||||
receive_buffer b(a);
|
||||
b.reserve(1000);
|
||||
b.cut(0, 1000); // packet size = 1000
|
||||
boost::array<boost::asio::mutable_buffer, 2> vec;
|
||||
b.assign_disk_buffer(&disk_buffer, 137);
|
||||
int num_bufs = b.reserve(vec, 1000);
|
||||
TEST_EQUAL(num_bufs, 2);
|
||||
|
||||
// regular buffer disk buffer
|
||||
// -----------------======
|
||||
//
|
||||
// |----------------------| 1000
|
||||
// |-----| 137
|
||||
// |----------------| 863
|
||||
|
||||
TEST_EQUAL(boost::asio::buffer_size(vec[0]), 863);
|
||||
TEST_EQUAL(boost::asio::buffer_size(vec[1]), 137);
|
||||
}
|
||||
|
||||
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||
|
||||
TORRENT_TEST(recv_buffer_mutable_buffers_regular_and_disk)
|
||||
{
|
||||
char disk_buffer; // fake disk buffer pointer
|
||||
|
||||
allocator a;
|
||||
receive_buffer b(a);
|
||||
b.reserve(1100);
|
||||
b.cut(0, 100); // packet size = 100
|
||||
b.received(1100);
|
||||
int packet_transferred = b.advance_pos(1100);
|
||||
// this is just the first packet
|
||||
TEST_EQUAL(packet_transferred, 100);
|
||||
// the next packet is 1000, and we're done with the first 100 bytes now
|
||||
b.cut(100, 1000); // packet size = 1000
|
||||
// and it has a disk buffer
|
||||
b.assign_disk_buffer(&disk_buffer, 137);
|
||||
std::vector<boost::asio::mutable_buffer> vec;
|
||||
packet_transferred = b.advance_pos(999);
|
||||
TEST_EQUAL(packet_transferred, 999);
|
||||
b.mutable_buffers(vec, 999);
|
||||
TEST_EQUAL(vec.size(), 2);
|
||||
|
||||
// previous packet
|
||||
// |
|
||||
// v regular buffer disk buffer
|
||||
// - - - -----------------======
|
||||
// ^
|
||||
// |
|
||||
// m_recv_start
|
||||
|
||||
// |----------------------| 1000 packet size
|
||||
// |-----| 137 disk buffer
|
||||
// |----------------| 863 regular buffer
|
||||
|
||||
TEST_EQUAL(boost::asio::buffer_size(vec[0]), 863);
|
||||
TEST_EQUAL(boost::asio::buffer_size(vec[1]), 137 - 1);
|
||||
TEST_EQUAL(boost::asio::buffer_size(vec[0])
|
||||
+ boost::asio::buffer_size(vec[1]), 999);
|
||||
}
|
||||
|
||||
TORRENT_TEST(recv_buffer_mutable_buffers_regular_only)
|
||||
{
|
||||
allocator a;
|
||||
receive_buffer b(a);
|
||||
b.reserve(1100);
|
||||
b.cut(0, 100); // packet size = 100
|
||||
b.received(1100);
|
||||
int packet_transferred = b.advance_pos(1100);
|
||||
// this is just the first packet
|
||||
TEST_EQUAL(packet_transferred, 100);
|
||||
// the next packet is 1000, and we're done with the first 100 bytes now
|
||||
b.cut(100, 1000); // packet size = 1000
|
||||
std::vector<boost::asio::mutable_buffer> vec;
|
||||
packet_transferred = b.advance_pos(999);
|
||||
TEST_EQUAL(packet_transferred, 999);
|
||||
b.mutable_buffers(vec, 999);
|
||||
TEST_EQUAL(vec.size(), 1);
|
||||
|
||||
// previous packet
|
||||
// |
|
||||
// v regular buffer
|
||||
// - - - -----------------------
|
||||
// ^
|
||||
// |
|
||||
// m_recv_start
|
||||
|
||||
// |----------------------| 1000 packet size
|
||||
// |---------------------| 999 regular buffer
|
||||
|
||||
TEST_EQUAL(boost::asio::buffer_size(vec[0]), 999);
|
||||
}
|
||||
|
||||
TORRENT_TEST(recv_buffer_mutable_buffers_disk)
|
||||
{
|
||||
char disk_buffer; // fake disk buffer pointer
|
||||
|
||||
allocator a;
|
||||
receive_buffer b(a);
|
||||
b.reserve(1100);
|
||||
b.cut(0, 100); // packet size = 100
|
||||
b.received(1100);
|
||||
int packet_transferred = b.advance_pos(1100);
|
||||
// this is just the first packet
|
||||
TEST_EQUAL(packet_transferred, 100);
|
||||
// the next packet is 1000, and we're done with the first 100 bytes now
|
||||
b.cut(100, 1000); // packet size = 1000
|
||||
// and it has a disk buffer
|
||||
b.assign_disk_buffer(&disk_buffer, 1000);
|
||||
std::vector<boost::asio::mutable_buffer> vec;
|
||||
packet_transferred = b.advance_pos(999);
|
||||
TEST_EQUAL(packet_transferred, 999);
|
||||
b.mutable_buffers(vec, 999);
|
||||
TEST_EQUAL(vec.size(), 1);
|
||||
|
||||
// previous packet
|
||||
// |
|
||||
// v disk buffer
|
||||
// - - - =======================
|
||||
// ^
|
||||
// |
|
||||
// m_recv_start
|
||||
|
||||
// |----------------------| 1000 packet size
|
||||
// |----------------------| 999 disk buffer
|
||||
|
||||
TEST_EQUAL(boost::asio::buffer_size(vec[0]), 999);
|
||||
TEST_EQUAL(boost::asio::buffer_cast<char*>(vec[0]), &disk_buffer);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -55,12 +55,20 @@ const int mask = alert::all_categories & ~(alert::performance_warning | alert::s
|
|||
|
||||
void wait_for_complete(lt::session& ses, torrent_handle h)
|
||||
{
|
||||
for (int i = 0; i < 70; ++i)
|
||||
int last_progress = 0;
|
||||
clock_type::time_point last_change = clock_type::now();
|
||||
for (int i = 0; i < 400; ++i)
|
||||
{
|
||||
print_alerts(ses, "ses1");
|
||||
torrent_status st = h.status();
|
||||
fprintf(stderr, "%f %%\n", st.progress_ppm / 10000.f);
|
||||
if (st.progress_ppm == 1000000) return;
|
||||
if (st.progress_ppm != last_progress)
|
||||
{
|
||||
last_progress = st.progress_ppm;
|
||||
last_change = clock_type::now();
|
||||
}
|
||||
if (clock_type::now() - last_change > seconds(10)) break;
|
||||
test_sleep(500);
|
||||
}
|
||||
TEST_ERROR("torrent did not finish");
|
||||
|
@ -107,3 +115,4 @@ TORRENT_TEST(recheck)
|
|||
TEST_CHECK(st1.progress_ppm <= 1000000);
|
||||
wait_for_complete(ses1, tor1);
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/alert_types.hpp"
|
||||
#include "libtorrent/session_stats.hpp"
|
||||
#include "libtorrent/performance_counters.hpp"
|
||||
#include "libtorrent/bdecode.hpp"
|
||||
#include "libtorrent/bencode.hpp"
|
||||
|
||||
using namespace libtorrent;
|
||||
namespace lt = libtorrent;
|
||||
|
@ -105,4 +107,107 @@ TORRENT_TEST(session_stats)
|
|||
TEST_EQUAL(stats[i].value_index, i);
|
||||
}
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
|
||||
template <typename Set, typename Save, typename Default, typename Load>
|
||||
void test_save_restore(Set setup, Save s, Default d, Load l)
|
||||
{
|
||||
entry st;
|
||||
{
|
||||
settings_pack p;
|
||||
setup(p);
|
||||
lt::session ses(p);
|
||||
s(ses, st);
|
||||
}
|
||||
|
||||
{
|
||||
settings_pack p;
|
||||
d(p);
|
||||
lt::session ses(p);
|
||||
// the loading function takes a bdecode_node, so we have to transform the
|
||||
// entry
|
||||
printf("%s\n", st.to_string().c_str());
|
||||
std::vector<char> buf;
|
||||
bencode(std::back_inserter(buf), st);
|
||||
bdecode_node state;
|
||||
error_code ec;
|
||||
int ret = bdecode(buf.data(), buf.data() + buf.size()
|
||||
, state, ec, nullptr, 100, 1000);
|
||||
TEST_EQUAL(ret, 0);
|
||||
if (ec)
|
||||
{
|
||||
printf("bdecode: %s\n", ec.message().c_str());
|
||||
printf("%s\n", std::string(buf.data(), buf.size()).c_str());
|
||||
}
|
||||
TEST_CHECK(!ec);
|
||||
l(ses, state);
|
||||
}
|
||||
}
|
||||
|
||||
TORRENT_TEST(save_restore_state)
|
||||
{
|
||||
test_save_restore(
|
||||
[](settings_pack& p) {
|
||||
// set the cache size
|
||||
p.set_int(settings_pack::cache_size, 1337);
|
||||
},
|
||||
[](lt::session& ses, entry& st) {
|
||||
ses.save_state(st);
|
||||
},
|
||||
[](settings_pack& p) {
|
||||
p.set_int(settings_pack::cache_size, 90);
|
||||
},
|
||||
[](lt::session& ses, bdecode_node& st) {
|
||||
ses.load_state(st);
|
||||
// make sure we loaded the cache size correctly
|
||||
settings_pack sett = ses.get_settings();
|
||||
TEST_EQUAL(sett.get_int(settings_pack::cache_size), 1337);
|
||||
});
|
||||
}
|
||||
|
||||
TORRENT_TEST(save_restore_state_save_filter)
|
||||
{
|
||||
test_save_restore(
|
||||
[](settings_pack& p) {
|
||||
// set the cache size
|
||||
p.set_int(settings_pack::cache_size, 1337);
|
||||
},
|
||||
[](lt::session& ses, entry& st) {
|
||||
// save everything _but_ the settings
|
||||
ses.save_state(st, ~session::save_settings);
|
||||
},
|
||||
[](settings_pack& p) {
|
||||
p.set_int(settings_pack::cache_size, 90);
|
||||
},
|
||||
[](lt::session& ses, bdecode_node& st) {
|
||||
ses.load_state(st);
|
||||
// make sure whatever we loaded did not include the cache size
|
||||
settings_pack sett = ses.get_settings();
|
||||
TEST_EQUAL(sett.get_int(settings_pack::cache_size), 90);
|
||||
});
|
||||
}
|
||||
|
||||
TORRENT_TEST(save_restore_state_load_filter)
|
||||
{
|
||||
test_save_restore(
|
||||
[](settings_pack& p) {
|
||||
// set the cache size
|
||||
p.set_int(settings_pack::cache_size, 1337);
|
||||
},
|
||||
[](lt::session& ses, entry& st) {
|
||||
// save everything
|
||||
ses.save_state(st);
|
||||
},
|
||||
[](settings_pack& p) {
|
||||
p.set_int(settings_pack::cache_size, 90);
|
||||
},
|
||||
[](lt::session& ses, bdecode_node& st) {
|
||||
// load everything _but_ the settings
|
||||
ses.load_state(st, ~session::save_settings);
|
||||
settings_pack sett = ses.get_settings();
|
||||
TEST_EQUAL(sett.get_int(settings_pack::cache_size), 90);
|
||||
});
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -119,12 +119,12 @@ struct callback_info
|
|||
|
||||
std::list<callback_info> callbacks;
|
||||
|
||||
void callback(int mapping, address const& ip, int port, error_code const& err)
|
||||
void callback(int mapping, address const& ip, int port, int protocol, error_code const& err)
|
||||
{
|
||||
callback_info info = {mapping, port, err};
|
||||
callbacks.push_back(info);
|
||||
std::cerr << "mapping: " << mapping << ", port: " << port << ", IP: " << ip
|
||||
<< ", error: \"" << err.message() << "\"\n";
|
||||
<< ", proto: " << protocol << ", error: \"" << err.message() << "\"\n";
|
||||
}
|
||||
|
||||
void run_upnp_test(char const* root_filename, char const* router_model, char const* control_name, int igd_version)
|
||||
|
@ -160,7 +160,6 @@ void run_upnp_test(char const* root_filename, char const* router_model, char con
|
|||
std::string user_agent = "test agent";
|
||||
|
||||
boost::shared_ptr<upnp> upnp_handler = boost::make_shared<upnp>(boost::ref(ios)
|
||||
, address_v4::from_string("127.0.0.1")
|
||||
, user_agent, &callback, &log_callback, false);
|
||||
upnp_handler->start();
|
||||
upnp_handler->discover_device();
|
||||
|
|
Loading…
Reference in New Issue