expose peer class API in python binding

This commit is contained in:
arvidn 2017-09-24 12:59:42 -07:00 committed by Arvid Norberg
parent 08e861cca9
commit 9cad0d8cf2
4 changed files with 154 additions and 5 deletions

View File

@ -1,6 +1,7 @@
1.1.5 release
* expose peer_class API to python binding
* fix integer overflow in whole_pieces_threshold logic
* fix uTP path MTU discovery issue on windows (DF bit was not set correctly)
* fix python binding for torrent_handle, to be hashable

View File

@ -17,6 +17,7 @@
#include <libtorrent/time.hpp>
#include <libtorrent/session_stats.hpp>
#include <libtorrent/session_status.hpp>
#include <libtorrent/peer_class_type_filter.hpp>
#ifndef TORRENT_NO_DEPRECATE
#include <libtorrent/extensions/lt_trackers.hpp>
@ -611,6 +612,72 @@ namespace
ses.load_state(e, flags);
}
dict get_peer_class(lt::session& ses, int const pc)
{
lt::peer_class_info pci;
{
allow_threading_guard guard;
pci = ses.get_peer_class(pc);
}
dict ret;
ret["ignore_unchoke_slots"] = pci.ignore_unchoke_slots;
ret["connection_limit_factor"] = pci.connection_limit_factor;
ret["label"] = pci.label;
ret["upload_limit"] = pci.upload_limit;
ret["download_limit"] = pci.download_limit;
ret["upload_priority"] = pci.upload_priority;
ret["download_priority"] = pci.download_priority;
return ret;
}
void set_peer_class(lt::session& ses, int const pc, dict info)
{
lt::peer_class_info pci;
stl_input_iterator<std::string> i(info.keys()), end;
for (; i != end; ++i)
{
std::string const key = *i;
object const value = info[key];
if (key == "ignore_unchoke_slots")
{
pci.ignore_unchoke_slots = extract<bool>(value);
}
else if (key == "connection_limit_factor")
{
pci.connection_limit_factor = extract<int>(value);
}
else if (key == "label")
{
pci.label = extract<std::string>(value);
}
else if (key == "upload_limit")
{
pci.upload_limit = extract<int>(value);
}
else if (key == "download_limit")
{
pci.download_limit = extract<int>(value);
}
else if (key == "upload_priority")
{
pci.upload_priority = extract<int>(value);
}
else if (key == "download_priority")
{
pci.download_priority = extract<int>(value);
}
else
{
PyErr_SetString(PyExc_KeyError, ("unknown name in peer_class_info: " + key).c_str());
throw_error_already_set();
}
}
allow_threading_guard guard;
ses.set_peer_class(pc, pci);
}
#ifndef TORRENT_DISABLE_DHT
void dht_get_mutable_item(lt::session& ses, std::string key, std::string salt)
{
@ -647,7 +714,7 @@ namespace
, salt);
}
#endif
} // namespace unnamed
} // anonymous namespace
void bind_session()
@ -798,7 +865,25 @@ void bind_session()
#endif
;
class_<lt::session, boost::noncopyable>("session", no_init)
class_<lt::peer_class_type_filter>("peer_class_type_filter")
.def(init<>())
.def("add", &lt::peer_class_type_filter::add)
.def("remove", &lt::peer_class_type_filter::remove)
.def("disallow", &lt::peer_class_type_filter::disallow)
.def("allow", &lt::peer_class_type_filter::allow)
.def("apply", &lt::peer_class_type_filter::apply)
;
enum_<lt::peer_class_type_filter::socket_type_t>("socket_type_t")
.value("tcp_socket", peer_class_type_filter::tcp_socket)
.value("utp_socket", peer_class_type_filter::utp_socket)
.value("ssl_tcp_socket", peer_class_type_filter::ssl_tcp_socket)
.value("ssl_utp_socket", peer_class_type_filter::ssl_utp_socket)
.value("i2p_socket", peer_class_type_filter::i2p_socket)
;
{
scope ses = class_<lt::session, boost::noncopyable>("session", no_init)
.def("__init__", boost::python::make_constructor(&make_session
, default_call_policies()
, (arg("settings")
@ -892,6 +977,12 @@ void bind_session()
.def("get_cache_info", &get_cache_info1, (arg("handle") = torrent_handle(), arg("flags") = 0))
.def("add_port_mapping", allow_threads(&lt::session::add_port_mapping))
.def("delete_port_mapping", allow_threads(&lt::session::delete_port_mapping))
.def("set_peer_class_filter", &lt::session::set_peer_class_filter)
.def("set_peer_class_type_filter", &lt::session::set_peer_class_type_filter)
.def("create_peer_class", &lt::session::create_peer_class)
.def("delete_peer_class", &lt::session::delete_peer_class)
.def("get_peer_class", &get_peer_class)
.def("set_peer_class", &set_peer_class)
#ifndef TORRENT_NO_DEPRECATE
.def(
@ -942,6 +1033,11 @@ void bind_session()
#endif // TORRENT_NO_DEPRECATE
;
ses.attr("global_peer_class_id") = int(session::global_peer_class_id);
ses.attr("tcp_peer_class_id") = int(session::tcp_peer_class_id);
ses.attr("local_peer_class_id") = int(session::local_peer_class_id);
}
enum_<lt::session::protocol_type>("protocol_type")
.value("udp", lt::session::udp)
.value("tcp", lt::session::tcp)

View File

@ -302,6 +302,59 @@ class test_magnet_link(unittest.TestCase):
h = ses.add_torrent(p)
self.assertEqual(str(h.info_hash()), '178882f042c0c33426a6d81e0333ece346e68a68')
class test_peer_class(unittest.TestCase):
def test_peer_class_ids(self):
s = lt.session({'enable_dht': False})
print('global_peer_class_id:', lt.session.global_peer_class_id)
print('tcp_peer_class_id:', lt.session.tcp_peer_class_id)
print('local_peer_class_id:', lt.session.local_peer_class_id)
print('global: ', s.get_peer_class(s.global_peer_class_id))
print('tcp: ', s.get_peer_class(s.local_peer_class_id))
print('local: ', s.get_peer_class(s.local_peer_class_id))
def test_peer_class(self):
s = lt.session({'enable_dht': False})
c = s.create_peer_class('test class')
print('new class: ', s.get_peer_class(c))
nfo = s.get_peer_class(c)
self.assertEqual(nfo['download_limit'], 0)
self.assertEqual(nfo['upload_limit'], 0)
self.assertEqual(nfo['ignore_unchoke_slots'], False)
self.assertEqual(nfo['connection_limit_factor'], 100)
self.assertEqual(nfo['download_priority'], 1)
self.assertEqual(nfo['upload_priority'], 1)
self.assertEqual(nfo['label'], 'test class')
nfo['download_limit'] = 1337
nfo['upload_limit'] = 1338
nfo['ignore_unchoke_slots'] = True
nfo['connection_limit_factor'] = 42
nfo['download_priority'] = 2
nfo['upload_priority'] = 3
s.set_peer_class(c, nfo)
nfo2 = s.get_peer_class(c)
self.assertEqual(nfo, nfo2)
def test_peer_class_filter(self):
filt = lt.peer_class_type_filter()
filt.add(lt.socket_type_t.tcp_socket, lt.session.global_peer_class_id);
filt.remove(lt.socket_type_t.utp_socket, lt.session.local_peer_class_id);
filt.disallow(lt.socket_type_t.tcp_socket, lt.session.global_peer_class_id);
filt.allow(lt.socket_type_t.utp_socket, lt.session.local_peer_class_id);
def test_peer_class_ip_filter(self):
s = lt.session({'enable_dht': False})
s.set_peer_class_type_filter(lt.peer_class_type_filter())
s.set_peer_class_filter(lt.ip_filter())
class test_session(unittest.TestCase):
def test_post_session_stats(self):

View File

@ -62,7 +62,6 @@ namespace libtorrent
num_socket_types
};
// ``add()`` and ``remove()`` adds and removes a peer class to be added
// to new peers based on socket type.
void add(socket_type_t st, int peer_class)
@ -130,9 +129,9 @@ namespace libtorrent
private:
// maps socket type to a bitmask that's used to filter out
// (mask) bits from the m_peer_class_filter.
boost::uint32_t m_peer_class_type_mask[5];
boost::uint32_t m_peer_class_type_mask[num_socket_types];
// peer class bitfield added based on socket type
boost::uint32_t m_peer_class_type[5];
boost::uint32_t m_peer_class_type[num_socket_types];
};
}