improve converters for add_torrent_params

This commit is contained in:
arvidn 2016-04-12 20:10:09 -04:00
parent 2529dbba7f
commit d84a38fdf2
8 changed files with 174 additions and 89 deletions

View File

@ -1,5 +1,6 @@
* added new read_resume_data() function, initializing add_torrent_params * added new read_resume_data() function, initializing add_torrent_params
* removed deprecated fields from add_torrent_params * removed deprecated fields from add_torrent_params
* deprecate "resume_data" field in add_torrent_params
* improved support for bind-to-device * improved support for bind-to-device
* deprecated ssl_listen, SSL sockets are specified in listen_interfaces now * deprecated ssl_listen, SSL sockets are specified in listen_interfaces now
* improved support for listening on multiple sockets and interfaces * improved support for listening on multiple sockets and interfaces

View File

@ -19,44 +19,12 @@ bytes get_buffer(read_piece_alert const& rpa)
: bytes(); : bytes();
} }
tuple endpoint_to_tuple(tcp::endpoint const& ep)
{
return boost::python::make_tuple(ep.address().to_string(), ep.port());
}
tuple endpoint_to_tuple(udp::endpoint const& ep)
{
return boost::python::make_tuple(ep.address().to_string(), ep.port());
}
tuple peer_alert_ip(peer_alert const& pa)
{
return endpoint_to_tuple(pa.ip);
}
std::string peer_blocked_alert_ip(peer_blocked_alert const& pa)
{
error_code ec;
return pa.ip.to_string(ec);
}
std::string dht_announce_alert_ip(dht_announce_alert const& pa) std::string dht_announce_alert_ip(dht_announce_alert const& pa)
{ {
error_code ec; error_code ec;
return pa.ip.to_string(ec); return pa.ip.to_string(ec);
} }
tuple incoming_connection_alert_ip(incoming_connection_alert const& ica)
{
return endpoint_to_tuple(ica.ip);
}
tuple dht_outgoing_get_peers_alert_ip(dht_outgoing_get_peers_alert const& a)
{
return endpoint_to_tuple(a.ip);
}
std::string external_ip_alert_ip(external_ip_alert const& eia) std::string external_ip_alert_ip(external_ip_alert const& eia)
{ {
return eia.external_address.to_string(); return eia.external_address.to_string();
@ -282,7 +250,8 @@ void bind_alert()
class_<peer_alert, bases<torrent_alert>, noncopyable>( class_<peer_alert, bases<torrent_alert>, noncopyable>(
"peer_alert", no_init) "peer_alert", no_init)
.add_property("ip", &peer_alert_ip) .add_property("ip", make_getter(&peer_alert::ip
, return_value_policy<return_by_value>()))
.def_readonly("pid", &peer_alert::pid) .def_readonly("pid", &peer_alert::pid)
; ;
class_<tracker_error_alert, bases<tracker_alert>, noncopyable>( class_<tracker_error_alert, bases<tracker_alert>, noncopyable>(
@ -469,7 +438,8 @@ void bind_alert()
class_<peer_blocked_alert, bases<alert>, noncopyable>( class_<peer_blocked_alert, bases<alert>, noncopyable>(
"peer_blocked_alert", no_init) "peer_blocked_alert", no_init)
.add_property("ip", &peer_blocked_alert_ip) .add_property("ip", make_getter(&peer_blocked_alert::ip
, return_value_policy<return_by_value>()))
; ;
class_<scrape_reply_alert, bases<tracker_alert>, noncopyable>( class_<scrape_reply_alert, bases<tracker_alert>, noncopyable>(
@ -494,7 +464,9 @@ void bind_alert()
class_<external_ip_alert, bases<alert>, noncopyable>( class_<external_ip_alert, bases<alert>, noncopyable>(
"external_ip_alert", no_init) "external_ip_alert", no_init)
.add_property("external_address", &external_ip_alert_ip) .add_property("external_address"
, make_getter(&external_ip_alert::external_address
, return_value_policy<return_by_value>()))
; ;
class_<save_resume_data_alert, bases<torrent_alert>, noncopyable>( class_<save_resume_data_alert, bases<torrent_alert>, noncopyable>(
@ -667,11 +639,12 @@ void bind_alert()
class_<incoming_connection_alert, bases<alert>, noncopyable>( class_<incoming_connection_alert, bases<alert>, noncopyable>(
"incoming_connection_alert", no_init) "incoming_connection_alert", no_init)
.def_readonly("socket_type", &incoming_connection_alert::socket_type) .def_readonly("socket_type", &incoming_connection_alert::socket_type)
.add_property("ip", &incoming_connection_alert_ip) .add_property("ip", make_getter(&incoming_connection_alert::ip
, return_value_policy<return_by_value>()))
; ;
class_<torrent_need_cert_alert, bases<torrent_alert>, noncopyable>( class_<torrent_need_cert_alert, bases<torrent_alert>, noncopyable>(
"torrent_need_cert_alert", no_init) "torrent_need_cert_alert", no_init)
.def_readonly("error", &torrent_need_cert_alert::error) .def_readonly("error", &torrent_need_cert_alert::error)
; ;
class_<add_torrent_alert, bases<torrent_alert>, noncopyable>( class_<add_torrent_alert, bases<torrent_alert>, noncopyable>(
@ -692,7 +665,8 @@ void bind_alert()
"dht_outgoing_get_peers_alert", no_init) "dht_outgoing_get_peers_alert", no_init)
.def_readonly("info_hash", &dht_outgoing_get_peers_alert::info_hash) .def_readonly("info_hash", &dht_outgoing_get_peers_alert::info_hash)
.def_readonly("obfuscated_info_hash", &dht_outgoing_get_peers_alert::obfuscated_info_hash) .def_readonly("obfuscated_info_hash", &dht_outgoing_get_peers_alert::obfuscated_info_hash)
.add_property("ip", &dht_outgoing_get_peers_alert_ip) .add_property("ip", make_getter(&dht_outgoing_get_peers_alert::ip
, return_value_policy<return_by_value>()))
; ;
#ifndef TORRENT_DISABLE_LOGGING #ifndef TORRENT_DISABLE_LOGGING

View File

@ -3,15 +3,65 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // 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/socket.hpp"
#include "libtorrent/address.hpp"
#include "libtorrent/error_code.hpp"
#include <vector>
using namespace boost::python; using namespace boost::python;
namespace bp = boost::python;
namespace lt = libtorrent;
template<class T>
struct endpoint_to_tuple
{
static PyObject* convert(T const& ep)
{
return incref(bp::make_tuple(ep.address().to_string(), ep.port()).ptr());
}
};
template<class T>
struct tuple_to_endpoint
{
tuple_to_endpoint()
{
converter::registry::push_back(
&convertible, &construct, type_id<T>()
);
}
static void* convertible(PyObject* x)
{
if (!PyTuple_Check(x)) return NULL;
if (PyTuple_Size(x) != 2) return NULL;
if (!PyString_Check(PyTuple_GetItem(x, 0))) return NULL;
if (!PyNumber_Check(PyTuple_GetItem(x, 1))) return NULL;
lt::error_code ec;
lt::address::from_string(PyString_AsString(PyTuple_GetItem(x, 0)), ec);
if (ec) return NULL;
return x;
}
static void construct(PyObject* x, converter::rvalue_from_python_stage1_data* data)
{
void* storage = ((converter::rvalue_from_python_storage<T*>*)data)
->storage.bytes;
object o(borrowed(x));
new (storage) T(lt::address::from_string(
extract<std::string>(o[0]))
, extract<int>(o[1]));
data->convertible = storage;
}
};
template<class T1, class T2> template<class T1, class T2>
struct pair_to_tuple struct pair_to_tuple
{ {
static PyObject* convert(const std::pair<T1, T2>& p) static PyObject* convert(const std::pair<T1, T2>& p)
{ {
return incref(make_tuple(p.first, p.second).ptr()); return incref(bp::make_tuple(p.first, p.second).ptr());
} }
}; };
@ -27,7 +77,7 @@ struct tuple_to_pair
static void* convertible(PyObject* x) static void* convertible(PyObject* x)
{ {
return PyTuple_Check(x) ? x: 0; return (PyTuple_Check(x) && PyTuple_Size(x) == 2) ? x: NULL;
} }
static void construct(PyObject* x, converter::rvalue_from_python_stage1_data* data) static void construct(PyObject* x, converter::rvalue_from_python_stage1_data* data)
@ -44,8 +94,78 @@ struct tuple_to_pair
} }
}; };
template<class T>
struct vector_to_list
{
static PyObject* convert(const std::vector<T>& v)
{
list l;
for (int i = 0; i < v.size(); ++i)
{
l.append(v[i]);
}
return incref(l.ptr());
}
};
template<class T>
struct list_to_vector
{
list_to_vector()
{
converter::registry::push_back(
&convertible, &construct, type_id<std::vector<T> >()
);
}
static void* convertible(PyObject* x)
{
return PyList_Check(x) ? x: 0;
}
static void construct(PyObject* x, converter::rvalue_from_python_stage1_data* data)
{
void* storage = ((converter::rvalue_from_python_storage<
std::vector<T> >*)data)->storage.bytes;
std::vector<T> p;
int const size = PyList_Size(x);
p.reserve(size);
for (int i = 0; i < size; ++i)
{
object o(borrowed(PyList_GetItem(x, i)));
p.push_back(extract<T>(o));
}
std::vector<T>* ptr = new (storage) std::vector<T>();
ptr->swap(p);
data->convertible = storage;
}
};
void bind_converters() void bind_converters()
{ {
// C++ -> python conversions
to_python_converter<std::pair<int, int>, pair_to_tuple<int, int> >(); to_python_converter<std::pair<int, int>, pair_to_tuple<int, int> >();
to_python_converter<std::pair<std::string, int>, pair_to_tuple<std::string, int> >();
to_python_converter<lt::tcp::endpoint, endpoint_to_tuple<lt::tcp::endpoint> >();
to_python_converter<lt::udp::endpoint, endpoint_to_tuple<lt::udp::endpoint> >();
to_python_converter<std::vector<std::string>, vector_to_list<std::string> >();
to_python_converter<std::vector<int>, vector_to_list<int> >();
to_python_converter<std::vector<boost::uint8_t>, vector_to_list<boost::uint8_t> >();
to_python_converter<std::vector<lt::tcp::endpoint>, vector_to_list<lt::tcp::endpoint> >();
to_python_converter<std::vector<lt::udp::endpoint>, vector_to_list<lt::udp::endpoint> >();
to_python_converter<std::vector<std::pair<std::string, int> >, vector_to_list<std::pair<std::string, int> > >();
// python -> C++ conversions
tuple_to_pair<int, int>(); tuple_to_pair<int, int>();
tuple_to_pair<std::string, int>();
tuple_to_endpoint<lt::tcp::endpoint>();
tuple_to_endpoint<lt::udp::endpoint>();
list_to_vector<int>();
list_to_vector<boost::uint8_t>();
list_to_vector<std::string>();
list_to_vector<lt::tcp::endpoint>();
list_to_vector<lt::udp::endpoint>();
list_to_vector<std::pair<std::string, int> >();
} }

View File

@ -680,17 +680,21 @@ void bind_session()
#endif // TORRENT_DISABLE_DHT #endif // TORRENT_DISABLE_DHT
#endif // TORRENT_NO_DEPRECATE #endif // TORRENT_NO_DEPRECATE
#define PROP(val) \
make_getter(val, return_value_policy<return_by_value>()), \
make_setter(val, return_value_policy<return_by_value>())
class_<add_torrent_params>("add_torrent_params") class_<add_torrent_params>("add_torrent_params")
.def_readwrite("version", &add_torrent_params::version) .def_readwrite("version", &add_torrent_params::version)
.def_readwrite("ti", &add_torrent_params::ti) .def_readwrite("ti", &add_torrent_params::ti)
.def_readwrite("trackers", &add_torrent_params::trackers) .add_property("trackers", PROP(&add_torrent_params::trackers))
.def_readwrite("tracker_tiers", &add_torrent_params::tracker_tiers) .add_property("tracker_tiers", PROP(&add_torrent_params::tracker_tiers))
.def_readwrite("dht_nodes", &add_torrent_params::dht_nodes) .add_property("dht_nodes", PROP(&add_torrent_params::dht_nodes))
.def_readwrite("name", &add_torrent_params::name) .def_readwrite("name", &add_torrent_params::name)
.def_readwrite("save_path", &add_torrent_params::save_path) .def_readwrite("save_path", &add_torrent_params::save_path)
.def_readwrite("storage_mode", &add_torrent_params::storage_mode) .def_readwrite("storage_mode", &add_torrent_params::storage_mode)
.def_readwrite("storage", &add_torrent_params::storage) // .def_readwrite("storage", &add_torrent_params::storage)
.def_readwrite("file_priorities", &add_torrent_params::file_priorities) .add_property("file_priorities", PROP(&add_torrent_params::file_priorities))
.def_readwrite("trackerid", &add_torrent_params::trackerid) .def_readwrite("trackerid", &add_torrent_params::trackerid)
.def_readwrite("url", &add_torrent_params::url) .def_readwrite("url", &add_torrent_params::url)
.def_readwrite("flags", &add_torrent_params::flags) .def_readwrite("flags", &add_torrent_params::flags)
@ -710,16 +714,16 @@ void bind_session()
.def_readwrite("num_complete", &add_torrent_params::num_complete) .def_readwrite("num_complete", &add_torrent_params::num_complete)
.def_readwrite("num_incomplete", &add_torrent_params::num_incomplete) .def_readwrite("num_incomplete", &add_torrent_params::num_incomplete)
.def_readwrite("num_downloaded", &add_torrent_params::num_downloaded) .def_readwrite("num_downloaded", &add_torrent_params::num_downloaded)
.def_readwrite("http_seeds", &add_torrent_params::http_seeds) .add_property("http_seeds", PROP(&add_torrent_params::http_seeds))
.def_readwrite("url_seeds", &add_torrent_params::url_seeds) .add_property("url_seeds", PROP(&add_torrent_params::url_seeds))
.def_readwrite("peers", &add_torrent_params::peers) .add_property("peers", PROP(&add_torrent_params::peers))
.def_readwrite("banned_peers", &add_torrent_params::banned_peers) .add_property("banned_peers", PROP(&add_torrent_params::banned_peers))
.def_readwrite("unfinished_pieces", &add_torrent_params::unfinished_pieces) .add_property("unfinished_pieces", PROP(&add_torrent_params::unfinished_pieces))
.def_readwrite("have_pieces", &add_torrent_params::have_pieces) .add_property("have_pieces", PROP(&add_torrent_params::have_pieces))
.def_readwrite("verified_pieces", &add_torrent_params::verified_pieces) .add_property("verified_pieces", PROP(&add_torrent_params::verified_pieces))
.def_readwrite("piece_priorities", &add_torrent_params::piece_priorities) .add_property("piece_priorities", PROP(&add_torrent_params::piece_priorities))
.def_readwrite("merkle_tree", &add_torrent_params::merkle_tree) .add_property("merkle_tree", PROP(&add_torrent_params::merkle_tree))
.def_readwrite("renamed_files", &add_torrent_params::renamed_files) .add_property("renamed_files", PROP(&add_torrent_params::renamed_files))
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
.def_readwrite("uuid", &add_torrent_params::uuid) .def_readwrite("uuid", &add_torrent_params::uuid)

View File

@ -301,19 +301,6 @@ void set_metadata(torrent_handle& handle, std::string const& buf)
handle.set_metadata(buf.c_str(), buf.size()); handle.set_metadata(buf.c_str(), buf.size());
} }
namespace
{
tcp::endpoint tuple_to_endpoint(tuple const& t)
{
return tcp::endpoint(address::from_string(extract<std::string>(t[0])), extract<int>(t[1]));
}
}
void connect_peer(torrent_handle& th, tuple ip, int source)
{
th.connect_peer(tuple_to_endpoint(ip), source);
}
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
#if BOOST_VERSION > 104200 #if BOOST_VERSION > 104200
@ -336,16 +323,6 @@ boost::shared_ptr<torrent_info> get_torrent_info(torrent_handle const& h)
#endif #endif
void set_peer_upload_limit(torrent_handle& th, tuple const& ip, int limit)
{
th.set_peer_upload_limit(tuple_to_endpoint(ip), limit);
}
void set_peer_download_limit(torrent_handle& th, tuple const& ip, int limit)
{
th.set_peer_download_limit(tuple_to_endpoint(ip), limit);
}
#endif // TORRENT_NO_DEPRECAE #endif // TORRENT_NO_DEPRECAE
void add_piece(torrent_handle& th, int piece, char const *data, int flags) void add_piece(torrent_handle& th, int piece, char const *data, int flags)
@ -471,18 +448,18 @@ void bind_torrent_handle()
.def("download_limit", _(&torrent_handle::download_limit)) .def("download_limit", _(&torrent_handle::download_limit))
.def("set_sequential_download", _(&torrent_handle::set_sequential_download)) .def("set_sequential_download", _(&torrent_handle::set_sequential_download))
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
.def("set_peer_upload_limit", &set_peer_upload_limit) .def("set_peer_upload_limit", &torrent_handle::set_peer_upload_limit)
.def("set_peer_download_limit", &set_peer_download_limit) .def("set_peer_download_limit", &torrent_handle::set_peer_download_limit)
.def("set_ratio", _(&torrent_handle::set_ratio)) .def("set_ratio", _(&torrent_handle::set_ratio))
.def("save_path", _(&torrent_handle::save_path)) .def("save_path", _(&torrent_handle::save_path))
#endif #endif
.def("connect_peer", &connect_peer) .def("connect_peer", &torrent_handle::connect_peer, (arg("endpoint"), arg("source")=0, arg("flags")=0xd))
.def("set_max_uploads", _(&torrent_handle::set_max_uploads)) .def("set_max_uploads", &torrent_handle::set_max_uploads)
.def("max_uploads", _(&torrent_handle::max_uploads)) .def("max_uploads", _(&torrent_handle::max_uploads))
.def("set_max_connections", _(&torrent_handle::set_max_connections)) .def("set_max_connections", &torrent_handle::set_max_connections)
.def("max_connections", _(&torrent_handle::max_connections)) .def("max_connections", _(&torrent_handle::max_connections))
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
.def("set_tracker_login", _(&torrent_handle::set_tracker_login)) .def("set_tracker_login", &torrent_handle::set_tracker_login)
#endif #endif
.def("move_storage", _(move_storage0), (arg("path"), arg("flags") = 0)) .def("move_storage", _(move_storage0), (arg("path"), arg("flags") = 0))
.def("info_hash", _(&torrent_handle::info_hash)) .def("info_hash", _(&torrent_handle::info_hash))

View File

@ -31,15 +31,20 @@ class test_torrent_handle(unittest.TestCase):
'info-hash': 'abababababababababab', 'info-hash': 'abababababababababab',
'name': 'test', 'name': 'test',
'save_path': '.', 'save_path': '.',
'file_priorities': [0, 1, 1]}) 'peers': '\x01\x01\x01\x01\x00\x01\x02\x02\x02\x02\x00\x02',
'file_priority': [0, 1, 1]})
tp = lt.read_resume_data(resume_data) tp = lt.read_resume_data(resume_data)
self.assertEqual(tp.name, 'test') self.assertEqual(tp.name, 'test')
self.assertEqual(tp.info_hash, lt.sha1_hash('abababababababababab')) self.assertEqual(tp.info_hash, lt.sha1_hash('abababababababababab'))
self.assertEqual(tp.file_priorities, [0, 1, 1])
self.assertEqual(tp.peers, [('1.1.1.1', 1), ('2.2.2.2', 2)])
ses = lt.session({'alert_mask': lt.alert.category_t.all_categories}) ses = lt.session({'alert_mask': lt.alert.category_t.all_categories})
h = ses.add_torrent(tp) h = ses.add_torrent(tp)
h.connect_peer(('3.3.3.3', 3))
for i in range(0, 10): for i in range(0, 10):
alerts = ses.pop_alerts() alerts = ses.pop_alerts()
for a in alerts: for a in alerts:

View File

@ -41,6 +41,8 @@ POSSIBILITY OF SUCH DAMAGE.
#include <libtorrent/alert_types.hpp> #include <libtorrent/alert_types.hpp>
#include <libtorrent/bencode.hpp> #include <libtorrent/bencode.hpp>
#include <libtorrent/torrent_status.hpp> #include <libtorrent/torrent_status.hpp>
#include <libtorrent/read_resume_data.hpp>
#include <libtorrent/error_code.hpp>
namespace lt = libtorrent; namespace lt = libtorrent;
using clk = std::chrono::steady_clock; using clk = std::chrono::steady_clock;
@ -74,14 +76,16 @@ int main(int argc, char const* argv[])
| lt::alert::status_notification); | lt::alert::status_notification);
lt::session ses(pack); lt::session ses(pack);
lt::add_torrent_params atp;
clk::time_point last_save_resume = clk::now(); clk::time_point last_save_resume = clk::now();
// load resume data from disk and pass it in as we add the magnet link // load resume data from disk and pass it in as we add the magnet link
std::ifstream ifs(".resume_file", std::ios_base::binary); std::ifstream ifs(".resume_file", std::ios_base::binary);
ifs.unsetf(std::ios_base::skipws); ifs.unsetf(std::ios_base::skipws);
atp.resume_data.assign(std::istream_iterator<char>(ifs) std::vector<char> buf{std::istream_iterator<char>(ifs)
, std::istream_iterator<char>()); , std::istream_iterator<char>()};
lt::error_code ec;
lt::add_torrent_params atp = lt::read_resume_data(&buf[0], buf.size(), ec);
atp.url = argv[1]; atp.url = argv[1];
atp.save_path = "."; // save in current dir atp.save_path = "."; // save in current dir
ses.async_add_torrent(atp); ses.async_add_torrent(atp);

@ -1 +1 @@
Subproject commit 5f7cbb8bd222ed0e5cfdaffc2a2f5010fb5b4a29 Subproject commit 0151d5c17fa3f4cf0ce518d0b8f90a23792c9b24