merged RC_1_1 into master

This commit is contained in:
arvidn 2016-04-08 02:20:24 -04:00
commit 867b83ccda
62 changed files with 868 additions and 512 deletions

View File

@ -93,7 +93,7 @@ script:
- cd ../examples
- bjam --hash -j3 warnings-as-errors=on variant=$variant $toolset link=shared
- if [[ lang == "cpp11" ]]; then
- if [[ $lang == "cpp11" ]]; then
bjam --hash -j3 warnings-as-errors=on variant=$variant $toolset link=shared bt-get bt-get2;
fi
- cd ..

View File

@ -87,6 +87,7 @@ set(sources
torrent_info
torrent_peer
torrent_peer_allocator
torrent_status
tracker_manager
http_tracker_connection
utf8

View File

@ -626,6 +626,7 @@ SOURCES =
torrent_info
torrent_peer
torrent_peer_allocator
torrent_status
time
tracker_manager
http_tracker_connection

View File

@ -21,6 +21,7 @@ EXTRA_DIST = \
src/module.cpp \
src/optional.hpp \
src/peer_info.cpp \
src/boost_python.hpp \
src/session.cpp \
src/session_settings.cpp \
src/string.cpp \

View File

@ -2,20 +2,21 @@
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python.hpp>
#include "boost_python.hpp"
#include <libtorrent/alert.hpp>
#include <libtorrent/alert_types.hpp>
#include <libtorrent/piece_picker.hpp> // for piece_block
#include <libtorrent/session_stats.hpp>
#include <memory>
#include "bytes.hpp"
using namespace boost::python;
using namespace libtorrent;
std::string get_buffer(read_piece_alert const& rpa)
bytes get_buffer(read_piece_alert const& rpa)
{
return rpa.buffer ? std::string(rpa.buffer.get(), rpa.size)
: std::string();
return rpa.buffer ? bytes(rpa.buffer.get(), rpa.size)
: bytes();
}
tuple endpoint_to_tuple(tcp::endpoint const& ep)
@ -269,7 +270,7 @@ void bind_alert()
class_<torrent_removed_alert, bases<torrent_alert>, noncopyable>(
"torrent_removed_alert", no_init)
.def_readonly("info_hash", &torrent_removed_alert::info_hash)
.def_readonly("info_hash", &torrent_removed_alert::info_hash)
;
class_<read_piece_alert, bases<torrent_alert>, noncopyable>(

View File

@ -3,7 +3,7 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <libtorrent/sha1_hash.hpp>
#include <boost/python.hpp>
#include "boost_python.hpp"
#include "bytes.hpp"
long get_hash(boost::python::object o)

View File

@ -0,0 +1,13 @@
// Copyright Daniel Wallin 2006. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PYTHON_HPP
#define BOOST_PYTHON_HPP
#include <libtorrent/aux_/disable_warnings_push.hpp>
#include <boost/python.hpp>
#include <libtorrent/aux_/disable_warnings_pop.hpp>
#endif

View File

@ -9,9 +9,16 @@
struct bytes
{
bytes(std::string const& s): arr(s) {}
bytes() {}
std::string arr;
bytes(char const* s, int len): arr(s, len) {}
bytes(std::string const& s): arr(s) {}
#if __cplusplus >= 201103L
bytes(std::string&& s): arr(std::move(s)) {}
bytes(bytes const&) = default;
bytes(bytes&&) = default;
bytes& operator=(bytes&&) = default;
#endif
bytes() {}
std::string arr;
};
#endif

View File

@ -2,7 +2,7 @@
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python.hpp>
#include "boost_python.hpp"
using namespace boost::python;

View File

@ -2,7 +2,7 @@
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python.hpp>
#include "boost_python.hpp"
#include <libtorrent/create_torrent.hpp>
#include <libtorrent/file_storage.hpp>
#include "libtorrent/torrent_info.hpp"

View File

@ -2,7 +2,7 @@
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python.hpp>
#include "boost_python.hpp"
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include "optional.hpp"
#include <boost/version.hpp>

View File

@ -2,7 +2,7 @@
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python.hpp>
#include "boost_python.hpp"
#include <libtorrent/session.hpp>
#include "bytes.hpp"

View File

@ -34,7 +34,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <libtorrent/bdecode.hpp>
#include <libtorrent/upnp.hpp>
#include <libtorrent/socks5_stream.hpp>
#include <boost/python.hpp>
#include "boost_python.hpp"
using namespace boost::python;
using namespace libtorrent;

View File

@ -3,12 +3,7 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <libtorrent/fingerprint.hpp>
#include <libtorrent/aux_/disable_warnings_push.hpp>
#include <boost/python.hpp>
#include <libtorrent/aux_/disable_warnings_pop.hpp>
#include "boost_python.hpp"
void bind_fingerprint()
{

View File

@ -3,7 +3,7 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <libtorrent/ip_filter.hpp>
#include <boost/python.hpp>
#include "boost_python.hpp"
#include "gil.hpp"
using namespace boost::python;

View File

@ -2,7 +2,7 @@
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt
#include <boost/python.hpp>
#include "boost_python.hpp"
#include <libtorrent/session.hpp>
#include <libtorrent/torrent.hpp>
#include <libtorrent/magnet_uri.hpp>
@ -17,23 +17,23 @@ extern void dict_to_add_torrent_params(dict params, add_torrent_params& p);
namespace {
#ifndef TORRENT_NO_DEPRECATE
torrent_handle _add_magnet_uri(lt::session& s, std::string uri, dict params)
{
add_torrent_params p;
torrent_handle _add_magnet_uri(lt::session& s, std::string uri, dict params)
{
add_torrent_params p;
dict_to_add_torrent_params(params, p);
dict_to_add_torrent_params(params, p);
allow_threading_guard guard;
allow_threading_guard guard;
p.url = uri;
p.url = uri;
#ifndef BOOST_NO_EXCEPTIONS
return s.add_torrent(p);
return s.add_torrent(p);
#else
error_code ec;
return s.add_torrent(p, ec);
error_code ec;
return s.add_torrent(p, ec);
#endif
}
}
#endif
dict parse_magnet_uri_wrap(std::string const& uri)
@ -78,10 +78,10 @@ namespace {
void bind_magnet_uri()
{
#ifndef TORRENT_NO_DEPRECATE
def("add_magnet_uri", &_add_magnet_uri);
def("add_magnet_uri", &_add_magnet_uri);
#endif
def("make_magnet_uri", make_magnet_uri0);
def("make_magnet_uri", make_magnet_uri1);
def("parse_magnet_uri", parse_magnet_uri_wrap);
def("make_magnet_uri", make_magnet_uri0);
def("make_magnet_uri", make_magnet_uri1);
def("parse_magnet_uri", parse_magnet_uri_wrap);
}

View File

@ -5,7 +5,7 @@
#ifndef OPTIONAL_070108_HPP
# define OPTIONAL_070108_HPP
# include <boost/python.hpp>
# include "boost_python.hpp"
# include <boost/optional.hpp>
template <class T>

View File

@ -4,7 +4,7 @@
#include <libtorrent/peer_info.hpp>
#include <libtorrent/bitfield.hpp>
#include <boost/python.hpp>
#include "boost_python.hpp"
#include <boost/python/iterator.hpp>
using namespace boost::python;

View File

@ -29,7 +29,7 @@
#include "libtorrent/aux_/disable_warnings_push.hpp"
#include <boost/python.hpp>
#include "boost_python.hpp"
#include "libtorrent/aux_/disable_warnings_pop.hpp"
@ -136,7 +136,26 @@ namespace
return boost::make_shared<lt::session>(p, flags);
}
void session_set_settings(lt::session& ses, dict const& sett_dict)
#ifndef TORRENT_NO_DEPRECATE
void session_set_settings(lt::session& ses, object const& sett)
{
extract<session_settings> old_settings(sett);
if (old_settings.check())
{
allow_threading_guard guard;
ses.set_settings(old_settings);
}
else
{
settings_pack p;
make_settings_pack(p, extract<dict>(sett));
allow_threading_guard guard;
ses.apply_settings(p);
}
}
#endif
void session_apply_settings(lt::session& ses, dict const& sett_dict)
{
settings_pack p;
make_settings_pack(p, sett_dict);
@ -189,7 +208,16 @@ namespace
{
// torrent_info objects are always held by a shared_ptr in the python binding
if (params.has_key("ti") && params.get("ti") != boost::python::object())
p.ti = extract<boost::shared_ptr<torrent_info> >(params["ti"]);
{
// make a copy here. We don't want to end up holding a python-owned
// object inside libtorrent. If the last reference goes out of scope
// on the C++ side, it will end up freeing the python object
// without holding the GIL and likely crash.
// https://mail.python.org/pipermail/cplusplus-sig/2007-June/012130.html
p.ti = boost::make_shared<torrent_info>(
extract<torrent_info const&>(params["ti"]));
}
if (params.has_key("info_hash"))
p.info_hash = sha1_hash(bytes(extract<bytes>(params["info_hash"])).arr);
@ -401,20 +429,20 @@ namespace
return ret;
}
cache_status get_cache_info1(lt::session& s, torrent_handle h, int flags)
{
cache_status ret;
s.get_cache_info(&ret, h, flags);
return ret;
}
cache_status get_cache_info1(lt::session& s, torrent_handle h, int flags)
{
cache_status ret;
s.get_cache_info(&ret, h, flags);
return ret;
}
#ifndef TORRENT_NO_DEPRECATE
cache_status get_cache_status(lt::session& s)
{
cache_status ret;
s.get_cache_info(&ret);
return ret;
}
cache_status get_cache_status(lt::session& s)
{
cache_status ret;
s.get_cache_info(&ret);
return ret;
}
dict get_utp_stats(session_status const& st)
{
@ -779,14 +807,11 @@ void bind_session()
#ifndef TORRENT_NO_DEPRECATE
.def("add_feed", &add_feed)
.def("status", allow_threads(&lt::session::status))
.def("set_settings", &lt::session::set_settings)
.def("settings", &lt::session::settings)
.def("get_settings", &session_get_settings)
#else
.def("settings", &session_get_settings)
.def("get_settings", &session_get_settings)
.def("set_settings", &session_set_settings)
#endif
.def("apply_settings", &session_set_settings)
.def("get_settings", &session_get_settings)
.def("apply_settings", &session_apply_settings)
#ifndef TORRENT_NO_DEPRECATE
#ifndef TORRENT_DISABLE_ENCRYPTION
.def("set_pe_settings", allow_threads(&lt::session::set_pe_settings))
@ -800,7 +825,7 @@ void bind_session()
#ifdef TORRENT_NO_DEPRECATE
, return_internal_reference<>()
#endif
)
)
.def("add_extension", &add_extension)
#ifndef TORRENT_NO_DEPRECATE
.def("pop_alert", &pop_alert)

View File

@ -2,7 +2,7 @@
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python.hpp>
#include "boost_python.hpp"
#include <libtorrent/session.hpp>
using namespace boost::python;

View File

@ -2,7 +2,7 @@
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python.hpp>
#include "boost_python.hpp"
#include <string>
using namespace boost::python;

View File

@ -2,8 +2,9 @@
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python.hpp>
#include "boost_python.hpp"
#include <boost/python/tuple.hpp>
#include <boost/python/stl_iterator.hpp>
#include <libtorrent/torrent_handle.hpp>
#include <libtorrent/torrent_info.hpp>
#include <libtorrent/torrent_status.hpp>
@ -121,59 +122,44 @@ list get_peer_info(torrent_handle const& handle)
return result;
}
namespace
{
template <typename T>
T extract_fn(object o)
{
return boost::python::extract<T>(o);
}
}
void prioritize_pieces(torrent_handle& info, object o)
{
std::vector<int> result;
std::vector<std::pair<int, int> > piece_list;
try
stl_input_iterator<object> begin(o), end;
if (begin == end) return;
// determine which overload should be selected. the one taking a list of
// priorities or the one taking a list of piece -> priority mappings
bool const is_piece_list = extract<std::pair<int, int> >(*begin).check();
if (is_piece_list)
{
object iter_obj = object( handle<>( PyObject_GetIter( o.ptr() ) ));
while( 1 )
{
object obj = extract<object>( iter_obj.attr( "next" )() );
extract<int const> val1(obj);
if (val1.check())
{
result.push_back(val1);
continue;
}
extract<std::pair<int, int> > val2(obj);
if (val2.check())
{
piece_list.push_back(val2);
continue;
}
}
std::vector<std::pair<int, int> > piece_list;
std::transform(begin, end, std::back_inserter(piece_list)
, &extract_fn<std::pair<int, int> >);
info.prioritize_pieces(piece_list);
}
catch( error_already_set )
else
{
PyErr_Clear();
if (result.size())
info.prioritize_pieces(result);
else
info.prioritize_pieces(piece_list);
return;
std::vector<int> priority_vector;
std::transform(begin, end, std::back_inserter(priority_vector)
, &extract_fn<int>);
info.prioritize_pieces(priority_vector);
}
}
void prioritize_files(torrent_handle& info, object o)
{
std::vector<int> result;
try
{
object iter_obj = object( handle<>( PyObject_GetIter( o.ptr() ) ));
while( 1 )
{
object obj = extract<object>( iter_obj.attr( "next" )() );
result.push_back(extract<int const>( obj ));
}
}
catch( error_already_set )
{
PyErr_Clear();
info.prioritize_files(result);
return;
}
stl_input_iterator<int const> begin(o), end;
info.prioritize_files(std::vector<int> (begin, end));
}
list file_priorities(torrent_handle& handle)

View File

@ -4,7 +4,7 @@
#include "libtorrent/aux_/disable_warnings_push.hpp"
#include <boost/python.hpp>
#include "boost_python.hpp"
#include <boost/shared_ptr.hpp>
#include "libtorrent/aux_/disable_warnings_pop.hpp"
@ -90,15 +90,14 @@ namespace
ti.set_merkle_tree(h);
}
std::string hash_for_piece(torrent_info const& ti, int i)
bytes hash_for_piece(torrent_info const& ti, int i)
{
return ti.hash_for_piece(i).to_string();
return bytes(ti.hash_for_piece(i).to_string());
}
std::string metadata(torrent_info const& ti)
bytes metadata(torrent_info const& ti)
{
std::string result(ti.metadata().get(), ti.metadata_size());
return result;
return bytes(ti.metadata().get(), ti.metadata_size());
}
list map_block(torrent_info& ti, int piece, boost::int64_t offset, int size)

View File

@ -2,7 +2,7 @@
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python.hpp>
#include "boost_python.hpp"
#include <libtorrent/torrent_status.hpp>
#include <libtorrent/torrent_info.hpp>
#include <libtorrent/bitfield.hpp>

View File

@ -4,7 +4,7 @@
#include <libtorrent/identify_client.hpp>
#include <libtorrent/bencode.hpp>
#include <boost/python.hpp>
#include "boost_python.hpp"
#include "bytes.hpp"
using namespace boost::python;

View File

@ -3,7 +3,7 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <libtorrent/version.hpp>
#include <boost/python.hpp>
#include "boost_python.hpp"
using namespace boost::python;
using libtorrent::version;

View File

@ -8,7 +8,22 @@ import os
import shutil
import binascii
# test torrent_info
class test_torrent_handle(unittest.TestCase):
def test_torrent_handle(self):
ses = lt.session({'alert_mask': lt.alert.category_t.all_categories})
ti = lt.torrent_info('url_seed_multi.torrent');
h = ses.add_torrent({'ti': ti, 'save_path': os.getcwd()})
h.prioritize_files([0,1])
self.assertEqual(h.file_priorities(), [0,1])
h.prioritize_pieces([0])
self.assertEqual(h.piece_priorities(), [0])
# also test the overload that takes a list of piece->priority mappings
h.prioritize_pieces([(0, 1)])
self.assertEqual(h.piece_priorities(), [1])
class test_torrent_info(unittest.TestCase):
@ -24,12 +39,36 @@ class test_torrent_info(unittest.TestCase):
self.assertEqual(f.file_size(0), 1234)
self.assertEqual(info.total_size(), 1234)
def test_metadata(self):
ti = lt.torrent_info('base.torrent');
self.assertTrue(len(ti.metadata()) != 0)
self.assertTrue(len(ti.hash_for_piece(0)) != 0)
def test_iterable_files(self):
# this detects whether libtorrent was built with deprecated APIs
# the file_strage object is only iterable for backwards compatibility
if not hasattr(lt, 'version'): return
ses = lt.session({'alert_mask': lt.alert.category_t.all_categories})
ti = lt.torrent_info('url_seed_multi.torrent');
files = ti.files()
idx = 0
expected = ['bar.txt', 'var.txt']
for f in files:
print f.path
self.assertEqual(os.path.split(f.path)[1], expected[idx])
self.assertEqual(os.path.split(f.path)[0], 'temp/foo')
idx += 1
class test_alerts(unittest.TestCase):
def test_alert(self):
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': os.getcwd()})
st = h.status()
@ -53,6 +92,25 @@ class test_alerts(unittest.TestCase):
print(st.info_hash)
self.assertEqual(st.save_path, os.getcwd())
def test_pop_alerts(self):
ses = lt.session({'alert_mask': lt.alert.category_t.all_categories})
ses.async_add_torrent({"ti": lt.torrent_info("base.torrent"), "save_path": "."})
# this will cause an error (because of duplicate torrents) and the
# torrent_info object created here will be deleted once the alert goes out
# of scope. When that happens, it will decrement the python object, to allow
# it to release the object.
# we're trying to catch the error described in this post, with regards to
# torrent_info.
# https://mail.python.org/pipermail/cplusplus-sig/2007-June/012130.html
ses.async_add_torrent({"ti": lt.torrent_info("base.torrent"), "save_path": "."})
time.sleep(1)
for i in range(0, 10):
alerts = ses.pop_alerts()
for a in alerts:
print(a.message())
time.sleep(0.1)
class test_bencoder(unittest.TestCase):
def test_bencode(self):
@ -75,6 +133,7 @@ class test_sha1hash(unittest.TestCase):
class test_session(unittest.TestCase):
def test_post_session_stats(self):
s = lt.session({'alert_mask': lt.alert.category_t.stats_notification})
s.post_session_stats()
@ -83,7 +142,27 @@ class test_session(unittest.TestCase):
self.assertTrue(isinstance(a.values, dict))
self.assertTrue(len(a.values) > 0)
def test_deprecated_settings(self):
# this detects whether libtorrent was built with deprecated APIs
if hasattr(lt, 'version'):
s = lt.session({})
sett = lt.session_settings()
sett.num_want = 10;
s.set_settings(sett)
s.set_settings({'num_want': 33})
self.assertEqual(s.get_settings()['num_want'], 33)
def test_apply_settings(self):
s = lt.session({})
s.apply_settings({'num_want': 66})
self.assertEqual(s.get_settings()['num_want'], 66)
if __name__ == '__main__':
print(lt.__version__)
shutil.copy(os.path.join('..', '..', 'test', 'test_torrents', 'url_seed_multi.torrent'), '.')
shutil.copy(os.path.join('..', '..', 'test', 'test_torrents', 'base.torrent'), '.')
unittest.main()

View File

@ -43,7 +43,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <libtorrent/torrent_status.hpp>
namespace lt = libtorrent;
using clock_t = std::chrono::monotonic_clock;
using clk = std::chrono::steady_clock;
// return the name of a torrent status enum
char const* state(lt::torrent_status::state_t s)
@ -75,7 +75,7 @@ int main(int argc, char const* argv[])
lt::session ses(pack);
lt::add_torrent_params atp;
std::chrono::time_point last_save_resume = clock_t::now();
clk::time_point last_save_resume = clk::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);
@ -135,7 +135,7 @@ int main(int argc, char const* argv[])
ses.post_torrent_updates();
// save resume data once every 30 seconds
if (clock_t::now() - last_save_resume > seconds(30)) {
if (clk::now() - last_save_resume > std::chrono::seconds(30)) {
h.save_resume_data();
}
}

View File

@ -240,7 +240,7 @@ namespace libtorrent
// of the piece. ``piece`` is the piece index that was read. ``size`` is the
// number of bytes that was read.
//
// If the operation fails, ec will indicat what went wrong.
// If the operation fails, ec will indicate what went wrong.
struct TORRENT_EXPORT read_piece_alert TORRENT_FINAL : torrent_alert
{
// internal
@ -1469,11 +1469,11 @@ namespace libtorrent
error_code error;
#ifndef TORRENT_NO_DEPRECATE
// If the error happend to a specific file, ``file`` is the path to it.
// If the error happened to a specific file, ``file`` is the path to it.
std::string file;
#endif
// If the error happend to a specific file, this returns the path to it.
// If the error happened to a specific file, this returns the path to it.
char const* file_path() const;
// If the error happened in a disk operation. a NULL-terminated string of
@ -2226,7 +2226,7 @@ namespace libtorrent
};
// holds statistics about a current dht_lookup operation.
// a DHT lookup is the travesal of nodes, looking up a
// a DHT lookup is the traversal of nodes, looking up a
// set of target nodes in the DHT for retrieving and possibly
// storing information in the DHT
struct TORRENT_EXPORT dht_lookup

View File

@ -33,9 +33,13 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef TORRENT_BANDWIDTH_CHANNEL_HPP_INCLUDED
#define TORRENT_BANDWIDTH_CHANNEL_HPP_INCLUDED
#include "libtorrent/aux_/disable_warnings_push.hpp"
#include <boost/integer_traits.hpp>
#include <boost/cstdint.hpp>
#include "libtorrent/aux_/disable_warnings_pop.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent {

View File

@ -64,11 +64,11 @@ namespace libtorrent
// The disk buffer holder acts like a ``scoped_ptr`` that frees a disk buffer
// when it's destructed, unless it's released. ``release`` returns the disk
// buffer and transferres ownership and responsibility to free it to the caller.
// buffer and transfers ownership and responsibility to free it to the caller.
//
// A disk buffer is freed by passing it to ``session_impl::free_disk_buffer()``.
//
// ``buffer()`` returns the pointer without transferring responsibility. If
// ``get()`` returns the pointer without transferring responsibility. If
// this buffer has been released, ``buffer()`` will return 0.
struct TORRENT_EXPORT disk_buffer_holder
{

View File

@ -350,7 +350,7 @@ namespace libtorrent
void clear_piece(piece_manager* storage, int index) TORRENT_OVERRIDE;
// implements buffer_allocator_interface
void reclaim_block(block_cache_reference ref);
void reclaim_block(block_cache_reference ref) TORRENT_OVERRIDE;
void free_disk_buffer(char* buf) TORRENT_OVERRIDE { m_disk_cache.free_buffer(buf); }
char* allocate_disk_buffer(char const* category) TORRENT_OVERRIDE
{
@ -375,7 +375,8 @@ namespace libtorrent
block_cache* cache() { return &m_disk_cache; }
#if TORRENT_USE_ASSERTS
bool is_disk_buffer(char* buffer) const { return m_disk_cache.is_disk_buffer(buffer); }
bool is_disk_buffer(char* buffer) const TORRENT_OVERRIDE
{ return m_disk_cache.is_disk_buffer(buffer); }
#endif
enum thread_type_t {
@ -386,7 +387,7 @@ namespace libtorrent
void thread_fun(int thread_id, thread_type_t type
, boost::shared_ptr<io_service::work> w);
file_pool& files() { return m_file_pool; }
virtual file_pool& files() TORRENT_OVERRIDE { return m_file_pool; }
io_service& get_io_service() { return m_ios; }

View File

@ -33,12 +33,16 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef TORRENT_HASHER_HPP_INCLUDED
#define TORRENT_HASHER_HPP_INCLUDED
#include <boost/cstdint.hpp>
#include "libtorrent/peer_id.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/aux_/disable_warnings_push.hpp"
#include <boost/cstdint.hpp>
#include "libtorrent/aux_/disable_warnings_pop.hpp"
#ifdef TORRENT_USE_GCRYPT
#include <gcrypt.h>

View File

@ -163,9 +163,9 @@ namespace libtorrent {
const static int header_size = (sizeof(header_t) + sizeof(uintptr_t)
- 1) / sizeof(uintptr_t);
void grow_capacity(int size)
void grow_capacity(int const size)
{
int amount_to_grow = (std::max)(size + header_size
int const amount_to_grow = (std::max)(size + header_size
, (std::max)(m_capacity * 3 / 2, 128));
uintptr_t* new_storage = new uintptr_t[m_capacity + amount_to_grow];

View File

@ -207,7 +207,7 @@ private:
// maximum size of bottled buffer
int m_max_bottled_buffer_size;
// the current download limit, in bytes per second
// 0 is unlimited.
int m_rate_limit;

View File

@ -33,7 +33,10 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef TORRENT_IO_HPP_INCLUDED
#define TORRENT_IO_HPP_INCLUDED
#include "libtorrent/aux_/disable_warnings_push.hpp"
#include <boost/cstdint.hpp>
#include "libtorrent/aux_/disable_warnings_pop.hpp"
#include <string>
#include <algorithm> // for copy
#include <cstring> // for memcpy

View File

@ -588,7 +588,7 @@ namespace libtorrent
// recorded as piece_downloading_reverse, which really means the same
// as piece_downloading, it just saves space to also indicate that it
// has a bit lower priority. The reverse bit is only relevant if the
// state is piece_downloadin.
// state is piece_downloading.
boost::uint32_t download_state : 3;
// TODO: 2 having 8 priority levels is probably excessive. It should
@ -660,7 +660,7 @@ namespace libtorrent
// +---+---+---+
// this '3' is called prio_factor
//
// the manually set priority takes presedence over the availability
// the manually set priority takes precedence over the availability
// by multiplying availability by priority.
int priority(piece_picker const* picker) const
@ -774,7 +774,7 @@ namespace libtorrent
mutable std::vector<int> m_priority_boundries;
// each piece that's currently being downloaded has an entry in this list
// with block allocations. i.e. it says wich parts of the piece that is
// with block allocations. i.e. it says which parts of the piece that is
// being downloaded. This list is ordered by piece index to make lookups
// efficient there are as many buckets as there are piece states. See
// piece_pos::state_t. The only download state that does not have a

View File

@ -194,7 +194,7 @@ namespace libtorrent
//
// ``orig_files()`` returns the original (unmodified) file storage for
// this torrent. This is used by the web server connection, which needs
// to request files with the original names. Filename may be chaged using
// to request files with the original names. Filename may be changed using
// ``torrent_info::rename_file()``.
//
// For more information on the file_storage object, see the separate

View File

@ -73,7 +73,7 @@ namespace libtorrent
// this torrent_peer. i.e. These are only updated
// when the connection is closed. For the
// total amount of upload and download
// we'll have to add thes figures with the
// we'll have to add these figures with the
// statistics from the peer_connection.
// since these values don't need to be stored
// with byte-precision, they specify the number
@ -115,7 +115,7 @@ namespace libtorrent
// this torrent_peer has
unsigned failcount:5; // [0, 31]
// incoming peers (that don't advertize their listen port)
// incoming peers (that don't advertise their listen port)
// will not be considered connectable. Peers that
// we have a listen port for will be assumed to be.
bool connectable:1;
@ -188,7 +188,7 @@ namespace libtorrent
bool supports_holepunch:1;
// this is set to one for web seeds. Web seeds
// are not stored in the policy m_peers list,
// and are excempt from connect candidate bookkeeping
// and are exempt from connect candidate bookkeeping
// so, any torrent_peer with the web_seed bit set, is
// never considered a connect candidate
bool web_seed:1;

View File

@ -150,6 +150,9 @@ namespace libtorrent
boost::uint32_t key;
int num_want;
#if TORRENT_USE_IPV6
address_v6 ipv6;
#endif
sha1_hash info_hash;
peer_id pid;
address bind_ip;

View File

@ -113,25 +113,34 @@ namespace libtorrent
template <class SocketOption>
void get_option(SocketOption const& opt, error_code& ec)
{
m_ipv4_sock.get_option(opt, ec);
#if TORRENT_USE_IPV6
m_ipv6_sock.get_option(opt, ec);
if (opt.level(udp::v6()) == IPPROTO_IPV6)
m_ipv6_sock.get_option(opt, ec);
else
#endif
m_ipv4_sock.get_option(opt, ec);
}
template <class SocketOption>
void set_option(SocketOption const& opt, error_code& ec)
{
m_ipv4_sock.set_option(opt, ec);
if (opt.level(udp::v4()) != IPPROTO_IPV6)
m_ipv4_sock.set_option(opt, ec);
#if TORRENT_USE_IPV6
m_ipv6_sock.set_option(opt, ec);
if (opt.level(udp::v6()) != IPPROTO_IP)
m_ipv6_sock.set_option(opt, ec);
#endif
}
template <class SocketOption>
void get_option(SocketOption& opt, error_code& ec)
{
m_ipv4_sock.get_option(opt, ec);
#if TORRENT_USE_IPV6
if (opt.level(udp::v6()) == IPPROTO_IPV6)
m_ipv6_sock.get_option(opt, ec);
else
#endif
m_ipv4_sock.get_option(opt, ec);
}
udp::endpoint proxy_addr() const { return m_proxy_addr; }

View File

@ -64,10 +64,10 @@ namespace libtorrent
#endif
#if TORRENT_UTP_LOG
bool is_utp_stream_logging();
TORRENT_EXPORT bool is_utp_stream_logging();
// This function should be used at the very beginning and very end of your program.
void set_utp_stream_logging(bool enable);
TORRENT_EXPORT void set_utp_stream_logging(bool enable);
#endif
TORRENT_EXTRA_EXPORT bool compare_less_wrap(boost::uint32_t lhs
@ -90,8 +90,8 @@ namespace libtorrent
};
// internal: the point of the bif_endian_int is two-fold
// one purpuse is to not have any alignment requirements
// so that any byffer received from the network can be cast
// one purpose is to not have any alignment requirements
// so that any buffer received from the network can be cast
// to it and read as an integer of various sizes without
// triggering a bus error. The other purpose is to convert
// from network byte order to host byte order when read and

@ -1 +1 @@
Subproject commit ce7d45687bb10dac8f533cf359afc7c78de705f7
Subproject commit 0151d5c17fa3f4cf0ce518d0b8f90a23792c9b24

View File

@ -39,6 +39,9 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/alert_types.hpp"
#include "libtorrent/announce_entry.hpp"
#include "libtorrent/session.hpp"
#include "libtorrent/create_torrent.hpp"
#include "libtorrent/file_storage.hpp"
#include "libtorrent/torrent_info.hpp"
using namespace libtorrent;
using namespace sim;
@ -397,7 +400,7 @@ void tracker_test(Setup setup, Announce a, Test1 test1, Test2 test2
p.name = "test-torrent";
p.save_path = ".";
p.info_hash.assign("abababababababababab");
int const delay = setup(p);
int const delay = setup(p, *ses);
ses->async_add_torrent(p);
// run the test 5 seconds in
@ -434,7 +437,7 @@ void tracker_test(Setup setup, Announce a, Test1 test1, Test2 test2
template <typename Announce, typename Test1, typename Test2>
void tracker_test(Announce a, Test1 test1, Test2 test2, char const* url_path = "/announce")
{
tracker_test([](lt::add_torrent_params& p) {
tracker_test([](lt::add_torrent_params& p, lt::session&) {
p.trackers.push_back("http://tracker.com:8080/announce");
return 5;
},
@ -629,7 +632,7 @@ TORRENT_TEST(try_next)
bool got_announce = false;
tracker_test(
[](lt::add_torrent_params& p)
[](lt::add_torrent_params& p, lt::session&)
{
// TODO: 3 use tracker_tiers here to put the trackers in different tiers
p.trackers.push_back("udp://failing-tracker.com/announce");
@ -691,6 +694,113 @@ TORRENT_TEST(try_next)
TEST_EQUAL(got_announce, true);
}
boost::shared_ptr<torrent_info> make_torrent(bool priv)
{
file_storage fs;
fs.add_file("foobar", 13241);
create_torrent ct(fs);
ct.add_tracker("http://tracker.com:8080/announce");
for (int i = 0; i < ct.num_pieces(); ++i)
ct.set_hash(i, sha1_hash(0));
ct.set_priv(priv);
entry e = ct.generate();
std::vector<char> buf;
bencode(std::back_inserter(buf), e);
error_code ec;
return boost::make_shared<torrent_info>(buf.data(), buf.size(), ec);
}
// make sure we _do_ send our IPv6 address to trackers for private torrents
TORRENT_TEST(tracker_ipv6_argument)
{
bool got_announce = false;
bool got_ipv6 = false;
tracker_test(
[](lt::add_torrent_params& p, lt::session& ses)
{
settings_pack pack;
pack.set_bool(settings_pack::anonymous_mode, false);
ses.apply_settings(pack);
p.ti = make_torrent(true);
return 60;
},
[&](std::string method, std::string req
, std::map<std::string, std::string>& headers)
{
got_announce = true;
int pos = req.find("&ipv6=");
TEST_CHECK(pos != std::string::npos);
got_ipv6 = pos != std::string::npos;
return sim::send_response(200, "OK", 11) + "d5:peers0:e";
}
, [](torrent_handle h) {}
, [](torrent_handle h) {});
TEST_EQUAL(got_announce, true);
TEST_EQUAL(got_ipv6, true);
}
// make sure we do _not_ send our IPv6 address to trackers for non-private
// torrents
TORRENT_TEST(tracker_ipv6_argument_non_private)
{
bool got_announce = false;
bool got_ipv6 = false;
tracker_test(
[](lt::add_torrent_params& p, lt::session& ses)
{
settings_pack pack;
pack.set_bool(settings_pack::anonymous_mode, false);
ses.apply_settings(pack);
p.ti = make_torrent(false);
return 60;
},
[&](std::string method, std::string req
, std::map<std::string, std::string>& headers)
{
got_announce = true;
int pos = req.find("&ipv6=");
TEST_CHECK(pos == std::string::npos);
got_ipv6 = pos != std::string::npos;
return sim::send_response(200, "OK", 11) + "d5:peers0:e";
}
, [](torrent_handle h) {}
, [](torrent_handle h) {});
TEST_EQUAL(got_announce, true);
TEST_EQUAL(got_ipv6, false);
}
TORRENT_TEST(tracker_ipv6_argument_privacy_mode)
{
bool got_announce = false;
bool got_ipv6 = false;
tracker_test(
[](lt::add_torrent_params& p, lt::session& ses)
{
settings_pack pack;
pack.set_bool(settings_pack::anonymous_mode, true);
ses.apply_settings(pack);
p.ti = make_torrent(true);
return 60;
},
[&](std::string method, std::string req
, std::map<std::string, std::string>& headers)
{
got_announce = true;
int pos = req.find("&ipv6=");
TEST_CHECK(pos == std::string::npos);
got_ipv6 = pos != std::string::npos;
return sim::send_response(200, "OK", 11) + "d5:peers0:e";
}
, [](torrent_handle h) {}
, [](torrent_handle h) {});
TEST_EQUAL(got_announce, true);
TEST_EQUAL(got_ipv6, false);
}
// TODO: test external IP
// TODO: test with different queuing settings
// TODO: test when a torrent transitions from downloading to finished and

View File

@ -1,8 +1,8 @@
/*
* Copyright 2001-2004 Unicode, Inc.
*
*
* Disclaimer
*
*
* This source code is provided as is by Unicode, Inc. No claims are
* made as to fitness for any particular purpose. No warranties of any
* kind are expressed or implied. The recipient agrees to determine
@ -10,9 +10,9 @@
* purchased on magnetic or optical media from Unicode, Inc., the
* sole remedy for any claim will be exchange of defective media
* within 90 days of receipt.
*
*
* Limitations on Rights to Redistribute This Code
*
*
* Unicode, Inc. hereby grants the right to freely use the information
* supplied in this file in the creation of products supporting the
* Unicode Standard, and to make copies of this file in any form
@ -26,10 +26,10 @@
Author: Mark E. Davis, 1994.
Rev History: Rick McGowan, fixes & updates May 2001.
Sept 2001: fixed const & error conditions per
mods suggested by S. Parent & A. Lillich.
mods suggested by S. Parent & A. Lillich.
June 2002: Tim Dodd added detection and handling of incomplete
source sequences, enhanced error detection, added casts
to eliminate compiler warnings.
source sequences, enhanced error detection, added casts
to eliminate compiler warnings.
July 2003: slight mods to back out aggressive FFFE detection.
Jan 2004: updated switches in from-UTF8 conversions.
Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions.
@ -55,113 +55,111 @@ static const UTF32 halfMask = 0x3FFUL;
#define UNI_SUR_HIGH_END (UTF32)0xDBFF
#define UNI_SUR_LOW_START (UTF32)0xDC00
#define UNI_SUR_LOW_END (UTF32)0xDFFF
#define false 0
#define true 1
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF32toUTF16 (
const UTF32** sourceStart, const UTF32* sourceEnd,
const UTF32** sourceStart, const UTF32* sourceEnd,
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF32* source = *sourceStart;
UTF16* target = *targetStart;
while (source < sourceEnd) {
ConversionResult result = conversionOK;
const UTF32* source = *sourceStart;
UTF16* target = *targetStart;
while (source < sourceEnd) {
UTF32 ch;
if (target >= targetEnd) {
result = targetExhausted; break;
result = targetExhausted; break;
}
ch = *source++;
if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
/* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
/* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
if (flags == strictConversion) {
--source; /* return to the illegal value itself */
result = sourceIllegal;
break;
--source; /* return to the illegal value itself */
result = sourceIllegal;
break;
} else {
*target++ = UNI_REPLACEMENT_CHAR;
*target++ = UNI_REPLACEMENT_CHAR;
}
} else {
} else {
*target++ = (UTF16)ch; /* normal case */
}
}
} else if (ch > UNI_MAX_LEGAL_UTF32) {
if (flags == strictConversion) {
if (flags == strictConversion) {
result = sourceIllegal;
} else {
} else {
*target++ = UNI_REPLACEMENT_CHAR;
}
}
} else {
/* target is a character in range 0xFFFF - 0x10FFFF. */
if (target + 1 >= targetEnd) {
/* target is a character in range 0xFFFF - 0x10FFFF. */
if (target + 1 >= targetEnd) {
--source; /* Back up source pointer! */
result = targetExhausted; break;
}
ch -= halfBase;
*target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
*target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
}
ch -= halfBase;
*target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
*target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
}
}
*sourceStart = source;
*targetStart = target;
return result;
}
*sourceStart = source;
*targetStart = target;
return result;
}
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF16toUTF32 (
const UTF16** sourceStart, const UTF16* sourceEnd,
const UTF16** sourceStart, const UTF16* sourceEnd,
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF16* source = *sourceStart;
UTF32* target = *targetStart;
UTF32 ch, ch2;
while (source < sourceEnd) {
ConversionResult result = conversionOK;
const UTF16* source = *sourceStart;
UTF32* target = *targetStart;
UTF32 ch, ch2;
while (source < sourceEnd) {
const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
ch = *source++;
/* If we have a surrogate pair, convert to UTF32 first. */
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
/* If the 16 bits following the high surrogate are in the source buffer... */
if (source < sourceEnd) {
/* If the 16 bits following the high surrogate are in the source buffer... */
if (source < sourceEnd) {
ch2 = *source;
/* If it's a low surrogate, convert to UTF32. */
if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
+ (ch2 - UNI_SUR_LOW_START) + halfBase;
++source;
++source;
} else if (flags == strictConversion) { /* it's an unpaired high surrogate */
--source; /* return to the illegal value itself */
result = sourceIllegal;
break;
--source; /* return to the illegal value itself */
result = sourceIllegal;
break;
}
} else { /* We don't have the 16 bits following the high surrogate. */
} else { /* We don't have the 16 bits following the high surrogate. */
--source; /* return to the high surrogate */
result = sourceExhausted;
break;
}
}
} else if (flags == strictConversion) {
/* UTF-16 surrogate values are illegal in UTF-32 */
if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
/* UTF-16 surrogate values are illegal in UTF-32 */
if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
--source; /* return to the illegal value itself */
result = sourceIllegal;
break;
}
}
}
if (target >= targetEnd) {
source = oldSource; /* Back up source pointer! */
result = targetExhausted; break;
source = oldSource; /* Back up source pointer! */
result = targetExhausted; break;
}
*target++ = ch;
}
*sourceStart = source;
*targetStart = target;
}
*sourceStart = source;
*targetStart = target;
#ifdef CVTUTF_DEBUG
if (result == sourceIllegal) {
fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2);
fflush(stderr);
fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2);
fflush(stderr);
}
#endif
return result;
return result;
}
/* --------------------------------------------------------------------- */
@ -174,14 +172,14 @@ if (result == sourceIllegal) {
* allowed in earlier algorithms.
*/
static const char trailingBytesForUTF8[256] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
};
/*
@ -189,8 +187,8 @@ static const char trailingBytesForUTF8[256] = {
* This table contains as many values as there might be trailing bytes
* in a UTF-8 sequence.
*/
static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL,
0x03C82080UL, 0xFA082080UL, 0x82082080UL };
static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL,
0x03C82080UL, 0xFA082080UL, 0x82082080UL };
/*
* Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
@ -214,71 +212,71 @@ static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF16toUTF8 (
const UTF16** sourceStart, const UTF16* sourceEnd,
const UTF16** sourceStart, const UTF16* sourceEnd,
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF16* source = *sourceStart;
UTF8* target = *targetStart;
while (source < sourceEnd) {
ConversionResult result = conversionOK;
const UTF16* source = *sourceStart;
UTF8* target = *targetStart;
while (source < sourceEnd) {
UTF32 ch;
unsigned short bytesToWrite = 0;
const UTF32 byteMask = 0xBF;
const UTF32 byteMark = 0x80;
const UTF32 byteMark = 0x80;
const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
ch = *source++;
/* If we have a surrogate pair, convert to UTF32 first. */
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
/* If the 16 bits following the high surrogate are in the source buffer... */
if (source < sourceEnd) {
/* If the 16 bits following the high surrogate are in the source buffer... */
if (source < sourceEnd) {
UTF32 ch2 = *source;
/* If it's a low surrogate, convert to UTF32. */
if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
+ (ch2 - UNI_SUR_LOW_START) + halfBase;
++source;
++source;
} else if (flags == strictConversion) { /* it's an unpaired high surrogate */
--source; /* return to the illegal value itself */
result = sourceIllegal;
break;
--source; /* return to the illegal value itself */
result = sourceIllegal;
break;
}
} else { /* We don't have the 16 bits following the high surrogate. */
} else { /* We don't have the 16 bits following the high surrogate. */
--source; /* return to the high surrogate */
result = sourceExhausted;
break;
}
}
} else if (flags == strictConversion) {
/* UTF-16 surrogate values are illegal in UTF-32 */
if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
/* UTF-16 surrogate values are illegal in UTF-32 */
if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
--source; /* return to the illegal value itself */
result = sourceIllegal;
break;
}
}
}
/* Figure out how many bytes the result will require */
if (ch < (UTF32)0x80) { bytesToWrite = 1;
} else if (ch < (UTF32)0x800) { bytesToWrite = 2;
if (ch < (UTF32)0x80) { bytesToWrite = 1;
} else if (ch < (UTF32)0x800) { bytesToWrite = 2;
} else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
} else if (ch < (UTF32)0x110000) { bytesToWrite = 4;
} else { bytesToWrite = 3;
ch = UNI_REPLACEMENT_CHAR;
} else { bytesToWrite = 3;
ch = UNI_REPLACEMENT_CHAR;
}
target += bytesToWrite;
if (target > targetEnd) {
source = oldSource; /* Back up source pointer! */
target -= bytesToWrite; result = targetExhausted; break;
source = oldSource; /* Back up source pointer! */
target -= bytesToWrite; result = targetExhausted; break;
}
switch (bytesToWrite) { /* note: everything falls through. */
case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]);
case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]);
}
target += bytesToWrite;
}
*sourceStart = source;
*targetStart = target;
return result;
}
*sourceStart = source;
*targetStart = target;
return result;
}
/* --------------------------------------------------------------------- */
@ -295,28 +293,28 @@ ConversionResult ConvertUTF16toUTF8 (
*/
static Boolean isLegalUTF8(const UTF8 *source, int length) {
UTF8 a;
const UTF8 *srcptr = source+length;
switch (length) {
default: return false;
UTF8 a;
const UTF8 *srcptr = source+length;
switch (length) {
default: return false;
/* Everything else falls through when "true"... */
case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
case 2: if ((a = (*--srcptr)) > 0xBF) return false;
case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
case 2: if ((a = (*--srcptr)) > 0xBF) return false;
switch (*source) {
/* no fall-through in this inner switch */
case 0xE0: if (a < 0xA0) return false; break;
case 0xED: if (a > 0x9F) return false; break;
case 0xF0: if (a < 0x90) return false; break;
case 0xF4: if (a > 0x8F) return false; break;
default: if (a < 0x80) return false;
/* no fall-through in this inner switch */
case 0xE0: if (a < 0xA0) return false; break;
case 0xED: if (a > 0x9F) return false; break;
case 0xF0: if (a < 0x90) return false; break;
case 0xF4: if (a > 0x8F) return false; break;
default: if (a < 0x80) return false;
}
case 1: if (*source >= 0x80 && *source < 0xC2) return false;
}
if (*source > 0xF4) return false;
return true;
case 1: if (*source >= 0x80 && *source < 0xC2) return false;
}
if (*source > 0xF4) return false;
return true;
}
/* --------------------------------------------------------------------- */
@ -326,216 +324,216 @@ static Boolean isLegalUTF8(const UTF8 *source, int length) {
* This is not used here; it's just exported.
*/
Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) {
int length = trailingBytesForUTF8[*source]+1;
if (source+length > sourceEnd) {
int length = trailingBytesForUTF8[*source]+1;
if (source+length > sourceEnd) {
return false;
}
return isLegalUTF8(source, length);
}
return isLegalUTF8(source, length);
}
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF8toUTF16 (
const UTF8** sourceStart, const UTF8* sourceEnd,
const UTF8** sourceStart, const UTF8* sourceEnd,
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF8* source = *sourceStart;
UTF16* target = *targetStart;
while (source < sourceEnd) {
ConversionResult result = conversionOK;
const UTF8* source = *sourceStart;
UTF16* target = *targetStart;
while (source < sourceEnd) {
UTF32 ch = 0;
unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
if (source + extraBytesToRead >= sourceEnd) {
result = sourceExhausted; break;
result = sourceExhausted; break;
}
/* Do this check whether lenient or strict */
if (! isLegalUTF8(source, extraBytesToRead+1)) {
result = sourceIllegal;
break;
result = sourceIllegal;
break;
}
/*
* The cases all fall through. See "Note A" below.
*/
switch (extraBytesToRead) {
case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
case 3: ch += *source++; ch <<= 6;
case 2: ch += *source++; ch <<= 6;
case 1: ch += *source++; ch <<= 6;
case 0: ch += *source++;
case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
case 3: ch += *source++; ch <<= 6;
case 2: ch += *source++; ch <<= 6;
case 1: ch += *source++; ch <<= 6;
case 0: ch += *source++;
}
ch -= offsetsFromUTF8[extraBytesToRead];
if (target >= targetEnd) {
source -= (extraBytesToRead+1); /* Back up source pointer! */
result = targetExhausted; break;
source -= (extraBytesToRead+1); /* Back up source pointer! */
result = targetExhausted; break;
}
if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
/* UTF-16 surrogate values are illegal in UTF-32 */
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
/* UTF-16 surrogate values are illegal in UTF-32 */
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
if (flags == strictConversion) {
source -= (extraBytesToRead+1); /* return to the illegal value itself */
result = sourceIllegal;
break;
source -= (extraBytesToRead+1); /* return to the illegal value itself */
result = sourceIllegal;
break;
} else {
*target++ = UNI_REPLACEMENT_CHAR;
*target++ = UNI_REPLACEMENT_CHAR;
}
} else {
} else {
*target++ = (UTF16)ch; /* normal case */
}
}
} else if (ch > UNI_MAX_UTF16) {
if (flags == strictConversion) {
if (flags == strictConversion) {
result = sourceIllegal;
source -= (extraBytesToRead+1); /* return to the start */
break; /* Bail out; shouldn't continue */
} else {
} else {
*target++ = UNI_REPLACEMENT_CHAR;
}
}
} else {
/* target is a character in range 0xFFFF - 0x10FFFF. */
if (target + 1 >= targetEnd) {
/* target is a character in range 0xFFFF - 0x10FFFF. */
if (target + 1 >= targetEnd) {
source -= (extraBytesToRead+1); /* Back up source pointer! */
result = targetExhausted; break;
}
ch -= halfBase;
*target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
*target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
}
ch -= halfBase;
*target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
*target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
}
}
*sourceStart = source;
*targetStart = target;
return result;
}
*sourceStart = source;
*targetStart = target;
return result;
}
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF32toUTF8 (
const UTF32** sourceStart, const UTF32* sourceEnd,
const UTF32** sourceStart, const UTF32* sourceEnd,
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF32* source = *sourceStart;
UTF8* target = *targetStart;
while (source < sourceEnd) {
ConversionResult result = conversionOK;
const UTF32* source = *sourceStart;
UTF8* target = *targetStart;
while (source < sourceEnd) {
UTF32 ch;
unsigned short bytesToWrite = 0;
const UTF32 byteMask = 0xBF;
const UTF32 byteMark = 0x80;
const UTF32 byteMark = 0x80;
ch = *source++;
if (flags == strictConversion ) {
/* UTF-16 surrogate values are illegal in UTF-32 */
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
/* UTF-16 surrogate values are illegal in UTF-32 */
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
--source; /* return to the illegal value itself */
result = sourceIllegal;
break;
}
}
}
/*
* Figure out how many bytes the result will require. Turn any
* illegally large UTF32 things (> Plane 17) into replacement chars.
*/
if (ch < (UTF32)0x80) { bytesToWrite = 1;
} else if (ch < (UTF32)0x800) { bytesToWrite = 2;
} else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
} else if (ch <= UNI_MAX_LEGAL_UTF32) { bytesToWrite = 4;
} else { bytesToWrite = 3;
ch = UNI_REPLACEMENT_CHAR;
result = sourceIllegal;
if (ch < (UTF32)0x80) { bytesToWrite = 1;
} else if (ch < (UTF32)0x800) { bytesToWrite = 2;
} else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
} else if (ch <= UNI_MAX_LEGAL_UTF32) { bytesToWrite = 4;
} else { bytesToWrite = 3;
ch = UNI_REPLACEMENT_CHAR;
result = sourceIllegal;
}
target += bytesToWrite;
if (target > targetEnd) {
--source; /* Back up source pointer! */
target -= bytesToWrite; result = targetExhausted; break;
--source; /* Back up source pointer! */
target -= bytesToWrite; result = targetExhausted; break;
}
switch (bytesToWrite) { /* note: everything falls through. */
case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]);
case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]);
}
target += bytesToWrite;
}
*sourceStart = source;
*targetStart = target;
return result;
}
*sourceStart = source;
*targetStart = target;
return result;
}
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF8toUTF32 (
const UTF8** sourceStart, const UTF8* sourceEnd,
const UTF8** sourceStart, const UTF8* sourceEnd,
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF8* source = *sourceStart;
UTF32* target = *targetStart;
while (source < sourceEnd) {
ConversionResult result = conversionOK;
const UTF8* source = *sourceStart;
UTF32* target = *targetStart;
while (source < sourceEnd) {
UTF32 ch = 0;
unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
if (source + extraBytesToRead >= sourceEnd) {
result = sourceExhausted; break;
result = sourceExhausted; break;
}
/* Do this check whether lenient or strict */
if (! isLegalUTF8(source, extraBytesToRead+1)) {
result = sourceIllegal;
break;
result = sourceIllegal;
break;
}
/*
* The cases all fall through. See "Note A" below.
*/
* The cases all fall through. See "Note A" below.
*/
switch (extraBytesToRead) {
case 5: ch += *source++; ch <<= 6;
case 4: ch += *source++; ch <<= 6;
case 3: ch += *source++; ch <<= 6;
case 2: ch += *source++; ch <<= 6;
case 1: ch += *source++; ch <<= 6;
case 0: ch += *source++;
case 5: ch += *source++; ch <<= 6;
case 4: ch += *source++; ch <<= 6;
case 3: ch += *source++; ch <<= 6;
case 2: ch += *source++; ch <<= 6;
case 1: ch += *source++; ch <<= 6;
case 0: ch += *source++;
}
ch -= offsetsFromUTF8[extraBytesToRead];
if (target >= targetEnd) {
source -= (extraBytesToRead+1); /* Back up the source pointer! */
result = targetExhausted; break;
source -= (extraBytesToRead+1); /* Back up the source pointer! */
result = targetExhausted; break;
}
if (ch <= UNI_MAX_LEGAL_UTF32) {
/*
* UTF-16 surrogate values are illegal in UTF-32, and anything
* over Plane 17 (> 0x10FFFF) is illegal.
*/
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
/*
* UTF-16 surrogate values are illegal in UTF-32, and anything
* over Plane 17 (> 0x10FFFF) is illegal.
*/
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
if (flags == strictConversion) {
source -= (extraBytesToRead+1); /* return to the illegal value itself */
result = sourceIllegal;
break;
source -= (extraBytesToRead+1); /* return to the illegal value itself */
result = sourceIllegal;
break;
} else {
*target++ = UNI_REPLACEMENT_CHAR;
*target++ = UNI_REPLACEMENT_CHAR;
}
} else {
} else {
*target++ = ch;
}
}
} else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */
result = sourceIllegal;
*target++ = UNI_REPLACEMENT_CHAR;
result = sourceIllegal;
*target++ = UNI_REPLACEMENT_CHAR;
}
}
*sourceStart = source;
*targetStart = target;
return result;
}
*sourceStart = source;
*targetStart = target;
return result;
}
/* ---------------------------------------------------------------------
Note A.
The fall-through switches in UTF-8 reading code save a
temp variable, some decrements & conditionals. The switches
are equivalent to the following loop:
Note A.
The fall-through switches in UTF-8 reading code save a
temp variable, some decrements & conditionals. The switches
are equivalent to the following loop:
{
int tmpBytesToRead = extraBytesToRead+1;
do {
int tmpBytesToRead = extraBytesToRead+1;
do {
ch += *source++;
--tmpBytesToRead;
if (tmpBytesToRead) ch <<= 6;
} while (tmpBytesToRead > 0);
} while (tmpBytesToRead > 0);
}
In UTF-8 writing code, the switches on "bytesToWrite" are
similarly unrolled loops.
In UTF-8 writing code, the switches on "bytesToWrite" are
similarly unrolled loops.
--------------------------------------------------------------------- */

View File

@ -131,6 +131,7 @@ libtorrent_rasterbar_la_SOURCES = \
torrent_info.cpp \
torrent_peer.cpp \
torrent_peer_allocator.cpp \
torrent_status.cpp \
time.cpp \
timestamp_history.cpp \
tracker_manager.cpp \

View File

@ -30,7 +30,12 @@ POSSIBILITY OF SUCH DAMAGE.
*/
#include "libtorrent/aux_/disable_warnings_push.hpp"
#include <boost/cstdint.hpp>
#include "libtorrent/aux_/disable_warnings_pop.hpp"
#include "libtorrent/bandwidth_queue_entry.hpp"
#include <cstring>
#include <algorithm>

View File

@ -1733,7 +1733,6 @@ void block_cache::check_invariant() const
TORRENT_PIECE_ASSERT(!p.blocks[k].pending, &p);
TORRENT_PIECE_ASSERT(p.blocks[k].refcount == 0, &p);
}
TORRENT_PIECE_ASSERT(p.blocks[k].refcount >= 0, &p);
num_refcount += p.blocks[k].refcount;
}
TORRENT_PIECE_ASSERT(num_blocks == p.num_blocks, &p);

View File

@ -468,7 +468,7 @@ namespace libtorrent
if (::rename(f1.c_str(), f2.c_str()) < 0)
#endif
{
ec.assign(errno, system_category());
ec.assign(errno, generic_category());
return;
}
}

View File

@ -81,6 +81,8 @@ http_connection::http_connection(io_service& ios
, m_connect_handler(ch)
, m_filter_handler(fh)
, m_timer(ios)
, m_read_timeout(seconds(5))
, m_completion_timeout(seconds(5))
, m_limiter_timer(ios)
, m_last_receive(aux::time_now())
, m_start_time(aux::time_now())

View File

@ -183,20 +183,22 @@ namespace libtorrent
{
url += "&ip=" + escape_string(announce_ip.c_str(), announce_ip.size());
}
// TODO: support this somehow
/* else if (settings.get_bool(settings_pack::announce_double_nat)
&& is_local(m_ses.listen_address()))
{
// only use the global external listen address here
// if it turned out to be on a local network
// since otherwise the tracker should use our
// source IP to determine our origin
url += "&ip=" + print_address(m_ses.listen_address());
}
*/
}
}
#if TORRENT_USE_IPV6
if (tracker_req().ipv6 != address_v6() && !i2p)
{
error_code err;
std::string const ip = tracker_req().ipv6.to_string(err);
if (!err)
{
url += "&ipv6=";
url += ip;
}
}
#endif
m_tracker_connection.reset(new http_connection(get_io_service(), m_man.host_resolver()
, boost::bind(&http_tracker_connection::on_response, shared_from_this(), _1, _2, _3, _4)
, true, settings.get_int(settings_pack::max_http_recv_buffer_size)

View File

@ -301,8 +301,10 @@ namespace libtorrent
void part_file::export_file(file& f, boost::int64_t offset, boost::int64_t size, error_code& ec)
{
mutex::scoped_lock l(m_mutex);
int piece = offset / m_piece_size;
int end = ((offset + size) + m_piece_size - 1) / m_piece_size;
int const end = ((offset + size) + m_piece_size - 1) / m_piece_size;
boost::scoped_array<char> buf;
@ -311,30 +313,49 @@ namespace libtorrent
for (; piece < end; ++piece)
{
boost::unordered_map<int, int>::iterator i = m_piece_map.find(piece);
int block_to_copy = (std::min)(m_piece_size - piece_offset, size);
int const block_to_copy = (std::min)(m_piece_size - piece_offset, size);
if (i != m_piece_map.end())
{
int const slot = i->second;
open_file(file::read_only, ec);
if (ec) return;
if (!buf) buf.reset(new char[m_piece_size]);
boost::int64_t slot_offset = boost::int64_t(m_header_size) + boost::int64_t(i->second) * m_piece_size;
file::iovec_t v = { buf.get(), size_t(block_to_copy) };
boost::int64_t const slot_offset = boost::int64_t(m_header_size)
+ boost::int64_t(slot) * m_piece_size;
// don't hold the lock during disk I/O
l.unlock();
file::iovec_t const v = { buf.get(), size_t(block_to_copy) };
int ret = m_file.readv(slot_offset + piece_offset, &v, 1, ec);
TORRENT_ASSERT(ec || ret == block_to_copy);
if (ec || ret != block_to_copy) return;
ret = f.writev(file_offset, &v, 1, ec);
TORRENT_ASSERT(ec || ret == block_to_copy);
if (ec || ret != block_to_copy) return;
// we're done with the disk I/O, grab the lock again to update
// the slot map
l.lock();
if (block_to_copy == m_piece_size)
{
m_free_slots.push_back(i->second);
m_piece_map.erase(i);
m_dirty_metadata = true;
// since we released the lock, it's technically possible that
// another thread removed this slot map entry, and invalidated
// our iterator. Now that we hold the lock again, perform
// another lookup to be sure.
boost::unordered_map<int, int>::iterator j = m_piece_map.find(piece);
if (j != m_piece_map.end())
{
// if the slot moved, that's really suspicious
TORRENT_ASSERT(j->second == slot);
m_free_slots.push_back(j->second);
m_piece_map.erase(j);
m_dirty_metadata = true;
}
}
}
file_offset += block_to_copy;

View File

@ -1893,21 +1893,15 @@ namespace libtorrent
namespace
{
int append_blocks(std::vector<piece_block>& dst, std::vector<piece_block>& src
, int num_blocks)
, int const num_blocks)
{
if (src.empty()) return num_blocks;
int to_copy;
// if (prefer_contiguous_blocks == 0)
to_copy = (std::min)(int(src.size()), num_blocks);
// else
// to_copy = int(src.size());
int const to_copy = (std::min)(int(src.size()), num_blocks);
dst.insert(dst.end()
, src.begin(), src.begin() + to_copy);
src.clear();
dst.insert(dst.end(), src.begin(), src.begin() + to_copy);
src.erase(src.begin(), src.begin() + to_copy);
return num_blocks - to_copy;
}
}
// lower availability comes first. This is a less-than comparison, it returns
@ -2338,8 +2332,7 @@ get_out:
#endif
ret |= picker_log_alert::backup1;
num_blocks = append_blocks(interesting_blocks, backup_blocks
, num_blocks);
num_blocks = append_blocks(interesting_blocks, backup_blocks, num_blocks);
if (num_blocks <= 0) return ret;
ret |= picker_log_alert::backup2;
@ -2390,7 +2383,7 @@ get_out:
// we either don't have this piece, or we've already requested from it
if (!pieces[dp.index]) continue;
// if we already have the piece, obviously we should not have
// if we already have the piece, obviously we should not have
// since this is a partial piece in the piece_downloading state, we
// should not already have it
TORRENT_ASSERT(!m_piece_map[dp.index].have());
@ -3333,7 +3326,6 @@ get_out:
info.peer = peer;
if (info.state == block_info::state_requested) --i->requested;
TORRENT_ASSERT(i->requested >= 0);
if (info.state == block_info::state_writing
|| info.state == block_info::state_finished)
return false;
@ -3493,7 +3485,6 @@ get_out:
info.peer = peer;
TORRENT_ASSERT(info.state == block_info::state_writing
|| peer == 0);
TORRENT_ASSERT(i->writing >= 0);
if (info.state == block_info::state_writing)
{
--i->writing;

View File

@ -33,7 +33,10 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/resolve_links.hpp"
#include "libtorrent/torrent_info.hpp"
#include "libtorrent/aux_/disable_warnings_push.hpp"
#include <boost/shared_ptr.hpp>
#include "libtorrent/aux_/disable_warnings_pop.hpp"
namespace libtorrent
{

View File

@ -1017,9 +1017,13 @@ namespace libtorrent
e.clear();
rename(old_path, new_path, e);
// if the source file doesn't exist. That's not a problem
// we just ignore that file
if (e == boost::system::errc::no_such_file_or_directory)
e.clear();
// on OSX, the error when trying to rename a file across different
// volumes is EXDEV, which will make it fall back to copying.
if (e)
{
if (flags == dont_replace && e == boost::system::errc::file_exists)
@ -1028,6 +1032,15 @@ namespace libtorrent
continue;
}
if (e == boost::system::errc::invalid_argument
|| e == boost::system::errc::permission_denied)
{
ec.ec = e;
ec.file = i->second;
ec.operation = storage_error::rename;
break;
}
if (e != boost::system::errc::no_such_file_or_directory)
{
e.clear();

View File

@ -1079,8 +1079,6 @@ namespace libtorrent
, resolve_filename(j->error.file).c_str());
#endif
TORRENT_ASSERT(j->piece >= 0);
if (j->action == disk_io_job::write)
{
piece_block block_finished(j->piece, j->d.io.offset / block_size());
@ -2942,7 +2940,19 @@ namespace libtorrent
if (req.downloaded < 0) req.downloaded = 0;
req.event = e;
error_code ec;
#if TORRENT_USE_IPV6
// since sending our IPv6 address to the tracker may be sensitive. Only
// do that if we're not in anonymous mode and if it's a private torrent
if (!settings().get_bool(settings_pack::anonymous_mode)
&& m_torrent_file
&& m_torrent_file->priv())
{
tcp::endpoint ep;
ep = m_ses.get_ipv6_interface();
if (ep != tcp::endpoint()) req.ipv6 = ep.address().to_v6();
}
#endif
// if we are aborting. we don't want any new peers
req.num_want = (req.event == tracker_request::stopped)
@ -5266,6 +5276,8 @@ namespace libtorrent
TORRENT_ASSERT(num_have() >= m_picker->num_have_filtered());
}
update_gauge();
update_want_tick();
if (filter_updated)
{
// we need to save this new state

View File

@ -147,77 +147,6 @@ using libtorrent::aux::session_impl;
namespace libtorrent
{
torrent_status::torrent_status()
: error_file(torrent_status::error_file_none)
, total_download(0)
, total_upload(0)
, total_payload_download(0)
, total_payload_upload(0)
, total_failed_bytes(0)
, total_redundant_bytes(0)
, total_done(0)
, total_wanted_done(0)
, total_wanted(0)
, all_time_upload(0)
, all_time_download(0)
, added_time(0)
, completed_time(0)
, last_seen_complete(0)
, storage_mode(storage_mode_sparse)
, progress(0.f)
, progress_ppm(0)
, queue_position(0)
, download_rate(0)
, upload_rate(0)
, download_payload_rate(0)
, upload_payload_rate(0)
, num_seeds(0)
, num_peers(0)
, num_complete(-1)
, num_incomplete(-1)
, list_seeds(0)
, list_peers(0)
, connect_candidates(0)
, num_pieces(0)
, distributed_full_copies(0)
, distributed_fraction(0)
, distributed_copies(0.f)
, block_size(0)
, num_uploads(0)
, num_connections(0)
, uploads_limit(0)
, connections_limit(0)
, up_bandwidth_queue(0)
, down_bandwidth_queue(0)
, time_since_upload(0)
, time_since_download(0)
, active_time(0)
, finished_time(0)
, seeding_time(0)
, seed_rank(0)
, last_scrape(0)
, priority(0)
, state(checking_resume_data)
, need_save_resume(false)
, ip_filter_applies(true)
, upload_mode(false)
, share_mode(false)
, super_seeding(false)
, paused(false)
, auto_managed(false)
, sequential_download(false)
, is_seeding(false)
, is_finished(false)
, has_metadata(false)
, has_incoming(false)
, seed_mode(false)
, moving_storage(false)
, is_loaded(true)
, info_hash(0)
{}
torrent_status::~torrent_status() {}
#ifndef BOOST_NO_EXCEPTIONS
void throw_invalid_handle()
{

View File

@ -376,7 +376,6 @@ namespace libtorrent
--added;
TORRENT_ASSERT(added >= 0);
}
#endif
if (added == 0 && added_separator)
{
@ -384,6 +383,7 @@ namespace libtorrent
path.erase(path.end()-1);
return;
}
#endif
if (path.empty()) path = "_";
}
@ -1346,7 +1346,7 @@ namespace libtorrent
error_code ec;
bdecode(m_info_section.get(), m_info_section.get()
+ m_info_section_size, m_info_dict, ec);
if (ec) return bdecode_node();
if (ec) return bdecode_node();
}
return m_info_dict.dict_find(key);
}

View File

@ -159,7 +159,7 @@ namespace libtorrent
, source(src)
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
// assume no support in order to
// prefer opening non-encrypyed
// prefer opening non-encrypted
// connections. If it fails, we'll
// retry with encryption
, pe_support(false)

114
src/torrent_status.cpp Normal file
View File

@ -0,0 +1,114 @@
/*
Copyright (c) 2015-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/torrent_status.hpp"
namespace libtorrent
{
torrent_status::torrent_status()
: error_file(torrent_status::error_file_none)
, next_announce(seconds(0))
, total_download(0)
, total_upload(0)
, total_payload_download(0)
, total_payload_upload(0)
, total_failed_bytes(0)
, total_redundant_bytes(0)
, total_done(0)
, total_wanted_done(0)
, total_wanted(0)
, all_time_upload(0)
, all_time_download(0)
, added_time(0)
, completed_time(0)
, last_seen_complete(0)
, storage_mode(storage_mode_sparse)
, progress(0.f)
, progress_ppm(0)
, queue_position(0)
, download_rate(0)
, upload_rate(0)
, download_payload_rate(0)
, upload_payload_rate(0)
, num_seeds(0)
, num_peers(0)
, num_complete(-1)
, num_incomplete(-1)
, list_seeds(0)
, list_peers(0)
, connect_candidates(0)
, num_pieces(0)
, distributed_full_copies(0)
, distributed_fraction(0)
, distributed_copies(0.f)
, block_size(0)
, num_uploads(0)
, num_connections(0)
, uploads_limit(0)
, connections_limit(0)
, up_bandwidth_queue(0)
, down_bandwidth_queue(0)
, time_since_upload(0)
, time_since_download(0)
, active_time(0)
, finished_time(0)
, seeding_time(0)
, seed_rank(0)
, last_scrape(0)
, priority(0)
, state(checking_resume_data)
, need_save_resume(false)
, ip_filter_applies(true)
, upload_mode(false)
, share_mode(false)
, super_seeding(false)
, paused(false)
, auto_managed(false)
, sequential_download(false)
, is_seeding(false)
, is_finished(false)
, has_metadata(false)
, has_incoming(false)
, seed_mode(false)
, moving_storage(false)
, is_loaded(true)
, announcing_to_trackers(false)
, announcing_to_lsd(false)
, announcing_to_dht(false)
, stop_when_ready(false)
, info_hash(0)
{}
torrent_status::~torrent_status() {}
}

View File

@ -65,9 +65,7 @@ static struct utp_logger
FILE* utp_log_file;
mutex utp_log_mutex;
utp_logger() : utp_log_file(NULL) {
utp_log_file = fopen("utp.log", "w+");
}
utp_logger() : utp_log_file(NULL) {}
~utp_logger()
{
if (utp_log_file) fclose(utp_log_file);
@ -504,7 +502,7 @@ public:
// this is what we'll send back
boost::uint32_t m_reply_micro;
// this is the advertized receive window the other end sent
// this is the advertised receive window the other end sent
// we'll never have more un-acked bytes in flight
// if this ever gets set to zero, we'll try one packet every
// second until the window opens up again
@ -618,7 +616,7 @@ public:
// this is a counter of how many times the current m_acked_seq_nr
// has been ACKed. If it's ACKed more than 3 times, we assume the
// packet with the next sequence number has been lost, and we trigger
// a re-send. Ovbiously an ACK only counts as a duplicate as long as
// a re-send. Obviously an ACK only counts as a duplicate as long as
// we have outstanding packets following it.
boost::uint8_t m_duplicate_acks;
@ -680,7 +678,7 @@ public:
// this is true while the socket is in slow start mode. It's
// only in slow-start during the start-up phase. Slow start
// (contrary to what its name suggest) means that we're growing
// the congestion window (cwnd) exponetially rather than linearly.
// the congestion window (cwnd) exponentially rather than linearly.
// this is done at startup of a socket in order to find its
// link capacity faster. This behaves similar to TCP slow start
bool m_slow_start:1;

View File

@ -124,11 +124,11 @@ boost::shared_ptr<default_storage> setup_torrent(file_storage& fs
, std::string const& test_path
, aux::session_settings& set)
{
fs.add_file("temp_storage/test1.tmp", 8);
fs.add_file("temp_storage/folder1/test2.tmp", 8);
fs.add_file("temp_storage/folder2/test3.tmp", 0);
fs.add_file("temp_storage/_folder3/test4.tmp", 0);
fs.add_file("temp_storage/_folder3/subfolder/test5.tmp", 8);
fs.add_file(combine_path("temp_storage", "test1.tmp"), 8);
fs.add_file(combine_path("temp_storage", combine_path("folder1", "test2.tmp")), 8);
fs.add_file(combine_path("temp_storage", combine_path("folder2", "test3.tmp")), 0);
fs.add_file(combine_path("temp_storage", combine_path("_folder3", "test4.tmp")), 0);
fs.add_file(combine_path("temp_storage", combine_path("_folder3", combine_path("subfolder", "test5.tmp"))), 8);
libtorrent::create_torrent t(fs, 4, -1, 0);
char buf_[4] = {0, 0, 0, 0};
@ -1263,3 +1263,29 @@ TORRENT_TEST(readwritev_zero_size_files)
TEST_CHECK(check_pattern(buf, 0));
}
TORRENT_TEST(move_storage_into_self)
{
aux::session_settings set;
file_storage fs;
std::vector<char> buf;
file_pool fp;
io_service ios;
disk_buffer_pool dp(16 * 1024, ios, boost::bind(&nop));
boost::shared_ptr<default_storage> s = setup_torrent(fs, fp, buf
, current_working_directory()
, set);
file::iovec_t b = {&buf[0], 4};
storage_error se;
s->writev(&b, 1, 2, 0, 0, se);
s->move_storage(combine_path("temp_storage", "folder1"), 0, se);
printf("move error: %s\n", se.ec.message().c_str());
#ifdef _WIN32
TEST_EQUAL(se.ec, boost::system::errc::permission_denied);
#else
TEST_EQUAL(se.ec, boost::system::errc::invalid_argument);
#endif
}