merged RC_1_1 into master
This commit is contained in:
commit
867b83ccda
|
@ -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 ..
|
||||
|
|
|
@ -87,6 +87,7 @@ set(sources
|
|||
torrent_info
|
||||
torrent_peer
|
||||
torrent_peer_allocator
|
||||
torrent_status
|
||||
tracker_manager
|
||||
http_tracker_connection
|
||||
utf8
|
||||
|
|
1
Jamfile
1
Jamfile
|
@ -626,6 +626,7 @@ SOURCES =
|
|||
torrent_info
|
||||
torrent_peer
|
||||
torrent_peer_allocator
|
||||
torrent_status
|
||||
time
|
||||
tracker_manager
|
||||
http_tracker_connection
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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>(
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(<::session::status))
|
||||
.def("set_settings", <::session::set_settings)
|
||||
.def("settings", <::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(<::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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
||||
--------------------------------------------------------------------- */
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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() {}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue