forked from premiere/premiere-libtorrent
Python binding initial checkin.
This commit is contained in:
parent
87f7b186b0
commit
aa3ce54455
|
@ -0,0 +1,27 @@
|
||||||
|
import python ;
|
||||||
|
|
||||||
|
python-extension libtorrent
|
||||||
|
: src/module.cpp
|
||||||
|
src/big_number.cpp
|
||||||
|
src/fingerprint.cpp
|
||||||
|
src/utility.cpp
|
||||||
|
src/session.cpp
|
||||||
|
src/entry.cpp
|
||||||
|
src/torrent_info.cpp
|
||||||
|
src/filesystem.cpp
|
||||||
|
src/torrent_handle.cpp
|
||||||
|
src/torrent_status.cpp
|
||||||
|
src/session_settings.cpp
|
||||||
|
src/version.cpp
|
||||||
|
src/alert.cpp
|
||||||
|
src/datetime.cpp
|
||||||
|
src/extensions.cpp
|
||||||
|
src/peer_plugin.cpp
|
||||||
|
src/docstrings.cpp
|
||||||
|
src/torrent.cpp
|
||||||
|
src/peer_info.cpp
|
||||||
|
/torrent//torrent
|
||||||
|
/boost/python//boost_python
|
||||||
|
: <include>src
|
||||||
|
;
|
||||||
|
|
|
@ -0,0 +1,277 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import libtorrent as lt
|
||||||
|
import time
|
||||||
|
import Console
|
||||||
|
import os.path
|
||||||
|
|
||||||
|
class PythonExtension(lt.torrent_plugin):
|
||||||
|
def __init__(self, alerts):
|
||||||
|
lt.torrent_plugin.__init__(self)
|
||||||
|
self.alerts = alerts
|
||||||
|
self.alerts.append('PythonExtension')
|
||||||
|
self.count = 0
|
||||||
|
|
||||||
|
def on_piece_pass(self, index):
|
||||||
|
self.alerts.append('got piece %d' % index)
|
||||||
|
|
||||||
|
def on_piece_failed(self, index):
|
||||||
|
self.alerts.append('failed piece %d' % index)
|
||||||
|
|
||||||
|
def tick(self):
|
||||||
|
self.count += 1
|
||||||
|
if self.count >= 10:
|
||||||
|
self.count = 0
|
||||||
|
self.alerts.append('PythonExtension tick')
|
||||||
|
|
||||||
|
def write_line(console, line):
|
||||||
|
console.write(line)
|
||||||
|
|
||||||
|
def add_suffix(val):
|
||||||
|
prefix = ['B', 'kB', 'MB', 'GB', 'TB']
|
||||||
|
for i in range(len(prefix)):
|
||||||
|
if abs(val) < 1000:
|
||||||
|
if i == 0:
|
||||||
|
return '%5.3g%s' % (val, prefix[i])
|
||||||
|
else:
|
||||||
|
return '%4.3g%s' % (val, prefix[i])
|
||||||
|
val /= 1000
|
||||||
|
|
||||||
|
return '%6.3gPB' % val
|
||||||
|
|
||||||
|
def progress_bar(progress, width):
|
||||||
|
progress_chars = int(progress * width + 0.5)
|
||||||
|
return progress_chars * '#' + (width - progress_chars) * '-'
|
||||||
|
|
||||||
|
def print_peer_info(console, peers):
|
||||||
|
|
||||||
|
out = ' down (total ) up (total ) q r flags block progress client\n'
|
||||||
|
|
||||||
|
for p in peers:
|
||||||
|
|
||||||
|
out += '%s/s ' % add_suffix(p.down_speed)
|
||||||
|
out += '(%s) ' % add_suffix(p.total_download)
|
||||||
|
out += '%s/s ' % add_suffix(p.up_speed)
|
||||||
|
out += '(%s) ' % add_suffix(p.total_upload)
|
||||||
|
out += '%2d ' % p.download_queue_length
|
||||||
|
out += '%2d ' % p.upload_queue_length
|
||||||
|
|
||||||
|
if p.flags & lt.peer_info.interesting: out += 'I'
|
||||||
|
else: out += '.'
|
||||||
|
if p.flags & lt.peer_info.choked: out += 'C'
|
||||||
|
else: out += '.'
|
||||||
|
if p.flags & lt.peer_info.remote_interested: out += 'i'
|
||||||
|
else: out += '.'
|
||||||
|
if p.flags & lt.peer_info.remote_choked: out += 'c'
|
||||||
|
else: out += '.'
|
||||||
|
if p.flags & lt.peer_info.supports_extensions: out += 'e'
|
||||||
|
else: out += '.'
|
||||||
|
if p.flags & lt.peer_info.local_connection: out += 'l'
|
||||||
|
else: out += 'r'
|
||||||
|
out += ' '
|
||||||
|
|
||||||
|
if p.downloading_piece_index >= 0:
|
||||||
|
out += progress_bar(float(p.downloading_progress) / p.downloading_total, 15)
|
||||||
|
else:
|
||||||
|
out += progress_bar(0, 15)
|
||||||
|
out += ' '
|
||||||
|
|
||||||
|
if p.flags & lt.peer_info.handshake:
|
||||||
|
id = 'waiting for handshake'
|
||||||
|
elif p.flags & lt.peer_info.connecting:
|
||||||
|
id = 'connecting to peer'
|
||||||
|
elif p.flags & lt.peer_info.queued:
|
||||||
|
id = 'queued'
|
||||||
|
else:
|
||||||
|
id = p.client
|
||||||
|
|
||||||
|
out += '%s\n' % id[:10]
|
||||||
|
|
||||||
|
write_line(console, out)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
from optparse import OptionParser
|
||||||
|
|
||||||
|
parser = OptionParser()
|
||||||
|
|
||||||
|
parser.add_option('-p', '--port',
|
||||||
|
type='int', help='set listening port')
|
||||||
|
|
||||||
|
parser.add_option('-r', '--ratio',
|
||||||
|
type='float', help='set the preferred upload/download ratio. 0 means infinite. Values smaller than 1 are clamped to 1')
|
||||||
|
|
||||||
|
parser.add_option('-d', '--max-download-rate',
|
||||||
|
type='float', help='the maximum download rate given in kB/s. 0 means infinite.')
|
||||||
|
|
||||||
|
parser.add_option('-u', '--max-upload-rate',
|
||||||
|
type='float', help='the maximum upload rate given in kB/s. 0 means infinite.')
|
||||||
|
|
||||||
|
parser.add_option('-s', '--save-path',
|
||||||
|
type='string', help='the path where the downloaded file/folder should be placed.')
|
||||||
|
|
||||||
|
parser.add_option('-a', '--allocation-mode',
|
||||||
|
type='string', help='sets mode used for allocating the downloaded files on disk. Possible options are [full | compact]')
|
||||||
|
|
||||||
|
parser.set_defaults(
|
||||||
|
port=6881
|
||||||
|
, ratio=0
|
||||||
|
, max_download_rate=0
|
||||||
|
, max_upload_rate=0
|
||||||
|
, save_path='./'
|
||||||
|
, allocation_mode='compact'
|
||||||
|
)
|
||||||
|
|
||||||
|
(options, args) = parser.parse_args()
|
||||||
|
|
||||||
|
if options.port < 0 or options.port > 65525:
|
||||||
|
options.port = 6881
|
||||||
|
|
||||||
|
options.max_upload_rate *= 1000
|
||||||
|
options.max_download_rate *= 1000
|
||||||
|
|
||||||
|
if options.max_upload_rate <= 0:
|
||||||
|
options.max_upload_rate = -1
|
||||||
|
if options.max_download_rate <= 0:
|
||||||
|
options.max_download_rate = -1
|
||||||
|
|
||||||
|
compact_allocation = options.allocation_mode == 'compact'
|
||||||
|
|
||||||
|
settings = lt.session_settings()
|
||||||
|
settings.user_agent = 'python_client/' + lt.version
|
||||||
|
|
||||||
|
ses = lt.session()
|
||||||
|
ses.set_download_rate_limit(options.max_download_rate)
|
||||||
|
ses.set_upload_rate_limit(options.max_upload_rate)
|
||||||
|
ses.listen_on(options.port, options.port + 10)
|
||||||
|
ses.set_settings(settings)
|
||||||
|
ses.set_severity_level(lt.alert.severity_levels.info)
|
||||||
|
|
||||||
|
handles = []
|
||||||
|
alerts = []
|
||||||
|
|
||||||
|
# Extensions
|
||||||
|
# ses.add_extension(lambda x: PythonExtension(alerts))
|
||||||
|
|
||||||
|
for f in args:
|
||||||
|
e = lt.bdecode(open(f, 'rb').read())
|
||||||
|
info = lt.torrent_info(e)
|
||||||
|
print 'Adding \'%s\'...' % info.name()
|
||||||
|
|
||||||
|
try:
|
||||||
|
resume_data = lt.bdecode(open(
|
||||||
|
os.path.join(options.save_path, info.name() + '.fastresume'), 'rb').read())
|
||||||
|
except:
|
||||||
|
resume_data = None
|
||||||
|
|
||||||
|
h = ses.add_torrent(info, options.save_path,
|
||||||
|
resume_data=resume_data, compact_mode=compact_allocation)
|
||||||
|
|
||||||
|
handles.append(h)
|
||||||
|
|
||||||
|
h.set_max_connections(60)
|
||||||
|
h.set_max_uploads(-1)
|
||||||
|
h.set_ratio(options.ratio)
|
||||||
|
h.set_sequenced_download_threshold(15)
|
||||||
|
|
||||||
|
import msvcrt
|
||||||
|
|
||||||
|
console = Console.getconsole()
|
||||||
|
|
||||||
|
alive = True
|
||||||
|
while alive:
|
||||||
|
console.page()
|
||||||
|
|
||||||
|
out = ''
|
||||||
|
|
||||||
|
for h in handles:
|
||||||
|
if h.has_metadata():
|
||||||
|
name = h.torrent_info().name()[:40]
|
||||||
|
else:
|
||||||
|
name = '-'
|
||||||
|
out += 'name: %-40s\n' % name
|
||||||
|
|
||||||
|
s = h.status()
|
||||||
|
|
||||||
|
if s.state != lt.torrent_status.seeding:
|
||||||
|
state_str = ['queued', 'checking', 'connecting', 'downloading metadata', \
|
||||||
|
'downloading', 'finished', 'seeding', 'allocating']
|
||||||
|
out += state_str[s.state] + ' '
|
||||||
|
|
||||||
|
out += '%5.4f%% ' % (s.progress*100)
|
||||||
|
out += progress_bar(s.progress, 49)
|
||||||
|
out += '\n'
|
||||||
|
|
||||||
|
out += 'total downloaded: %d Bytes\n' % s.total_done
|
||||||
|
out += 'peers: %d seeds: %d distributed copies: %d\n' % \
|
||||||
|
(s.num_peers, s.num_seeds, s.distributed_copies)
|
||||||
|
out += '\n'
|
||||||
|
|
||||||
|
out += 'download: %s/s (%s) ' \
|
||||||
|
% (add_suffix(s.download_rate), add_suffix(s.total_download))
|
||||||
|
out += 'upload: %s/s (%s) ' \
|
||||||
|
% (add_suffix(s.upload_rate), add_suffix(s.total_upload))
|
||||||
|
out += 'ratio: %s\n' % '0'
|
||||||
|
|
||||||
|
if s.state != lt.torrent_status.seeding:
|
||||||
|
out += 'info-hash: %s\n' % h.info_hash()
|
||||||
|
out += 'next announce: %s\n' % s.next_announce
|
||||||
|
out += 'tracker: %s\n' % s.current_tracker
|
||||||
|
|
||||||
|
write_line(console, out)
|
||||||
|
|
||||||
|
peers = h.get_peer_info()
|
||||||
|
print_peer_info(console, peers)
|
||||||
|
|
||||||
|
if True and s.state != lt.torrent_status.seeding:
|
||||||
|
out = '\n'
|
||||||
|
fp = h.file_progress()
|
||||||
|
ti = h.torrent_info()
|
||||||
|
for f,p in zip(ti.files(), fp):
|
||||||
|
out += progress_bar(p, 20)
|
||||||
|
out += ' ' + f.path + '\n'
|
||||||
|
write_line(console, out)
|
||||||
|
|
||||||
|
write_line(console, 76 * '-' + '\n')
|
||||||
|
write_line(console, '(q)uit), (p)ause), (u)npause), (r)eannounce\n')
|
||||||
|
write_line(console, 76 * '-' + '\n')
|
||||||
|
|
||||||
|
while 1:
|
||||||
|
a = ses.pop_alert()
|
||||||
|
if not a: break
|
||||||
|
alerts.append(a)
|
||||||
|
|
||||||
|
if len(alerts) > 8:
|
||||||
|
del alerts[:len(alerts) - 8]
|
||||||
|
|
||||||
|
for a in alerts:
|
||||||
|
if type(a) == str:
|
||||||
|
write_line(console, a + '\n')
|
||||||
|
else:
|
||||||
|
write_line(console, a.msg() + '\n')
|
||||||
|
|
||||||
|
time.sleep(0.5)
|
||||||
|
if msvcrt.kbhit():
|
||||||
|
c = msvcrt.getch()
|
||||||
|
if c == 'r':
|
||||||
|
for h in handles: h.force_reannounce()
|
||||||
|
elif c == 'q':
|
||||||
|
alive = False
|
||||||
|
elif c == 'p':
|
||||||
|
for h in handles: h.pause()
|
||||||
|
elif c == 'u':
|
||||||
|
for h in handles: h.resume()
|
||||||
|
|
||||||
|
for h in handles:
|
||||||
|
if not h.is_valid() or not h.has_metadata():
|
||||||
|
continue
|
||||||
|
h.pause()
|
||||||
|
data = lt.bencode(h.write_resume_data())
|
||||||
|
open(os.path.join(options.save_path, h.torrent_info().name() + '.fastresume'), 'wb').write(data)
|
||||||
|
|
||||||
|
main()
|
||||||
|
|
|
@ -0,0 +1,162 @@
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
#include <libtorrent/alert.hpp>
|
||||||
|
#include <libtorrent/alert_types.hpp>
|
||||||
|
#include <boost/python.hpp>
|
||||||
|
|
||||||
|
using namespace boost::python;
|
||||||
|
using namespace libtorrent;
|
||||||
|
|
||||||
|
extern char const* alert_doc;
|
||||||
|
extern char const* alert_msg_doc;
|
||||||
|
extern char const* alert_severity_doc;
|
||||||
|
extern char const* listen_failed_alert_doc;
|
||||||
|
extern char const* file_error_alert_doc;
|
||||||
|
extern char const* tracker_announce_alert_doc;
|
||||||
|
extern char const* tracker_alert_doc;
|
||||||
|
extern char const* tracker_reply_alert_doc;
|
||||||
|
extern char const* tracker_warning_alert_doc;
|
||||||
|
extern char const* url_seed_alert_doc;
|
||||||
|
extern char const* hash_failed_alert_doc;
|
||||||
|
extern char const* peer_ban_alert_doc;
|
||||||
|
extern char const* peer_error_alert_doc;
|
||||||
|
extern char const* invalid_request_alert_doc;
|
||||||
|
extern char const* peer_request_doc;
|
||||||
|
extern char const* torrent_finished_alert_doc;
|
||||||
|
extern char const* metadata_failed_alert_doc;
|
||||||
|
extern char const* metadata_received_alert_doc;
|
||||||
|
extern char const* fastresume_rejected_alert_doc;
|
||||||
|
|
||||||
|
void bind_alert()
|
||||||
|
{
|
||||||
|
using boost::noncopyable;
|
||||||
|
|
||||||
|
{
|
||||||
|
scope alert_scope = class_<alert, noncopyable>("alert", alert_doc, no_init)
|
||||||
|
.def(
|
||||||
|
"msg", &alert::msg, return_value_policy<copy_const_reference>()
|
||||||
|
, alert_msg_doc
|
||||||
|
)
|
||||||
|
.def("severity", &alert::severity, alert_severity_doc)
|
||||||
|
.def(
|
||||||
|
"__str__", &alert::msg, return_value_policy<copy_const_reference>()
|
||||||
|
, alert_msg_doc
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
enum_<alert::severity_t>("severity_levels")
|
||||||
|
.value("debug", alert::severity_t::debug)
|
||||||
|
.value("info", alert::severity_t::info)
|
||||||
|
.value("warning", alert::severity_t::warning)
|
||||||
|
.value("critical", alert::severity_t::critical)
|
||||||
|
.value("fatal", alert::severity_t::fatal)
|
||||||
|
.value("none", alert::severity_t::none)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
class_<listen_failed_alert, bases<alert>, noncopyable>(
|
||||||
|
"listen_failed_alert", listen_failed_alert_doc, no_init
|
||||||
|
);
|
||||||
|
|
||||||
|
class_<file_error_alert, bases<alert>, noncopyable>(
|
||||||
|
"file_error_alert", file_error_alert_doc, no_init
|
||||||
|
)
|
||||||
|
.def_readonly("handle", &file_error_alert::handle)
|
||||||
|
;
|
||||||
|
|
||||||
|
class_<tracker_announce_alert, bases<alert>, noncopyable>(
|
||||||
|
"tracker_announce_alert", tracker_announce_alert_doc, no_init
|
||||||
|
)
|
||||||
|
.def_readonly("handle", &tracker_announce_alert::handle)
|
||||||
|
;
|
||||||
|
|
||||||
|
class_<tracker_alert, bases<alert>, noncopyable>(
|
||||||
|
"tracker_alert", tracker_alert_doc, no_init
|
||||||
|
)
|
||||||
|
.def_readonly("handle", &tracker_alert::handle)
|
||||||
|
.def_readonly("times_in_row", &tracker_alert::times_in_row)
|
||||||
|
.def_readonly("status_code", &tracker_alert::status_code)
|
||||||
|
;
|
||||||
|
|
||||||
|
class_<tracker_reply_alert, bases<alert>, noncopyable>(
|
||||||
|
"tracker_reply_alert", tracker_reply_alert_doc, no_init
|
||||||
|
)
|
||||||
|
.def_readonly("handle", &tracker_reply_alert::handle)
|
||||||
|
;
|
||||||
|
|
||||||
|
class_<tracker_warning_alert, bases<alert>, noncopyable>(
|
||||||
|
"tracker_warning_alert", tracker_warning_alert_doc, no_init
|
||||||
|
)
|
||||||
|
.def_readonly("handle", &tracker_warning_alert::handle)
|
||||||
|
;
|
||||||
|
|
||||||
|
class_<url_seed_alert, bases<alert>, noncopyable>(
|
||||||
|
"url_seed_alert", url_seed_alert_doc, no_init
|
||||||
|
)
|
||||||
|
.def_readonly("url", &url_seed_alert::url)
|
||||||
|
;
|
||||||
|
|
||||||
|
class_<hash_failed_alert, bases<alert>, noncopyable>(
|
||||||
|
"hash_failed_alert", hash_failed_alert_doc, no_init
|
||||||
|
)
|
||||||
|
.def_readonly("handle", &hash_failed_alert::handle)
|
||||||
|
.def_readonly("piece_index", &hash_failed_alert::piece_index)
|
||||||
|
;
|
||||||
|
|
||||||
|
class_<peer_ban_alert, bases<alert>, noncopyable>(
|
||||||
|
"peer_ban_alert", peer_ban_alert_doc, no_init
|
||||||
|
)
|
||||||
|
.def_readonly("ip", &peer_ban_alert::ip)
|
||||||
|
.def_readonly("handle", &peer_ban_alert::handle)
|
||||||
|
;
|
||||||
|
|
||||||
|
class_<peer_error_alert, bases<alert>, noncopyable>(
|
||||||
|
"peer_error_alert", peer_error_alert_doc, no_init
|
||||||
|
)
|
||||||
|
.def_readonly("ip", &peer_error_alert::ip)
|
||||||
|
.def_readonly("pid", &peer_error_alert::pid)
|
||||||
|
;
|
||||||
|
|
||||||
|
class_<invalid_request_alert, bases<alert>, noncopyable>(
|
||||||
|
"invalid_request_alert", invalid_request_alert_doc, no_init
|
||||||
|
)
|
||||||
|
.def_readonly("handle", &invalid_request_alert::handle)
|
||||||
|
.def_readonly("ip", &invalid_request_alert::ip)
|
||||||
|
.def_readonly("request", &invalid_request_alert::request)
|
||||||
|
.def_readonly("pid", &invalid_request_alert::pid)
|
||||||
|
;
|
||||||
|
|
||||||
|
class_<peer_request>("peer_request", peer_request_doc)
|
||||||
|
.def_readonly("piece", &peer_request::piece)
|
||||||
|
.def_readonly("start", &peer_request::start)
|
||||||
|
.def_readonly("length", &peer_request::length)
|
||||||
|
.def(self == self)
|
||||||
|
;
|
||||||
|
|
||||||
|
class_<torrent_finished_alert, bases<alert>, noncopyable>(
|
||||||
|
"torrent_finished_alert", torrent_finished_alert_doc, no_init
|
||||||
|
)
|
||||||
|
.def_readonly("handle", &torrent_finished_alert::handle)
|
||||||
|
;
|
||||||
|
|
||||||
|
class_<metadata_failed_alert, bases<alert>, noncopyable>(
|
||||||
|
"metadata_failed_alert", metadata_failed_alert_doc, no_init
|
||||||
|
)
|
||||||
|
.def_readonly("handle", &metadata_failed_alert::handle)
|
||||||
|
;
|
||||||
|
|
||||||
|
class_<metadata_received_alert, bases<alert>, noncopyable>(
|
||||||
|
"metadata_received_alert", metadata_received_alert_doc, no_init
|
||||||
|
)
|
||||||
|
.def_readonly("handle", &metadata_received_alert::handle)
|
||||||
|
;
|
||||||
|
|
||||||
|
class_<fastresume_rejected_alert, bases<alert>, noncopyable>(
|
||||||
|
"fastresume_rejected_alert", fastresume_rejected_alert_doc, no_init
|
||||||
|
)
|
||||||
|
.def_readonly("handle", &fastresume_rejected_alert::handle)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
#include <libtorrent/peer_id.hpp>
|
||||||
|
#include <boost/python.hpp>
|
||||||
|
|
||||||
|
void bind_big_number()
|
||||||
|
{
|
||||||
|
using namespace boost::python;
|
||||||
|
using namespace libtorrent;
|
||||||
|
|
||||||
|
class_<big_number>("big_number")
|
||||||
|
.def(self == self)
|
||||||
|
.def(self != self)
|
||||||
|
.def(self < self)
|
||||||
|
.def(self_ns::str(self))
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
// Copyright Daniel Wallin 2007. 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)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
#include <boost/python.hpp>
|
||||||
|
#include <boost/date_time/posix_time/posix_time_types.hpp>
|
||||||
|
#include "optional.hpp"
|
||||||
|
|
||||||
|
using namespace boost::python;
|
||||||
|
|
||||||
|
// From Boost 1.34
|
||||||
|
object import(str name)
|
||||||
|
{
|
||||||
|
// should be 'char const *' but older python versions don't use 'const' yet.
|
||||||
|
char *n = extract<char *>(name);
|
||||||
|
handle<> module(borrowed(PyImport_ImportModule(n)));
|
||||||
|
return object(module);
|
||||||
|
}
|
||||||
|
|
||||||
|
object datetime_timedelta;
|
||||||
|
object datetime_datetime;
|
||||||
|
|
||||||
|
struct time_duration_to_python
|
||||||
|
{
|
||||||
|
static PyObject* convert(boost::posix_time::time_duration const& d)
|
||||||
|
{
|
||||||
|
object result = datetime_timedelta(
|
||||||
|
0 // days
|
||||||
|
, 0 // seconds
|
||||||
|
, d.total_microseconds()
|
||||||
|
);
|
||||||
|
|
||||||
|
return incref(result.ptr());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ptime_to_python
|
||||||
|
{
|
||||||
|
static PyObject* convert(boost::posix_time::ptime const& pt)
|
||||||
|
{
|
||||||
|
boost::gregorian::date date = pt.date();
|
||||||
|
boost::posix_time::time_duration td = pt.time_of_day();
|
||||||
|
|
||||||
|
object result = datetime_datetime(
|
||||||
|
(int)date.year()
|
||||||
|
, (int)date.month()
|
||||||
|
, (int)date.day()
|
||||||
|
, td.hours()
|
||||||
|
, td.minutes()
|
||||||
|
, td.seconds()
|
||||||
|
);
|
||||||
|
|
||||||
|
return incref(result.ptr());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void bind_datetime()
|
||||||
|
{
|
||||||
|
object datetime = import("datetime").attr("__dict__");
|
||||||
|
|
||||||
|
datetime_timedelta = datetime["timedelta"];
|
||||||
|
datetime_datetime = datetime["datetime"];
|
||||||
|
|
||||||
|
to_python_converter<
|
||||||
|
boost::posix_time::time_duration
|
||||||
|
, time_duration_to_python
|
||||||
|
>();
|
||||||
|
|
||||||
|
to_python_converter<
|
||||||
|
boost::posix_time::ptime
|
||||||
|
, ptime_to_python
|
||||||
|
>();
|
||||||
|
|
||||||
|
optional_to_python<boost::posix_time::ptime>();
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,266 @@
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
// -- torrent_status --------------------------------------------------------
|
||||||
|
|
||||||
|
char const* torrent_status_doc =
|
||||||
|
"Represents the current status for a torrent.\n"
|
||||||
|
"Returned by `torrent_handle.status()`.";
|
||||||
|
|
||||||
|
char const* torrent_status_state_doc =
|
||||||
|
"The torrents current task. One of `torrent_status.states`.";
|
||||||
|
|
||||||
|
char const* torrent_status_paused_doc =
|
||||||
|
"Indicates if this torrent is paused or not.";
|
||||||
|
|
||||||
|
char const* torrent_status_progress_doc =
|
||||||
|
"A value in the range [0, 1], that represents the progress of\n"
|
||||||
|
"the torrent's current task.";
|
||||||
|
|
||||||
|
char const* torrent_status_next_announce_doc =
|
||||||
|
"The time until the torrent will announce itself to the\n"
|
||||||
|
"tracker. An instance of `datetime.timedelta`.";
|
||||||
|
|
||||||
|
char const* torrent_status_announce_interval_doc =
|
||||||
|
"The interval at which the torrent will reannounce itself to the\n"
|
||||||
|
"tracker. An instance of `datetime.timedelta`.";
|
||||||
|
|
||||||
|
char const* torrent_status_current_tracker_doc =
|
||||||
|
"The URL of the last working tracker. If no tracker request has\n"
|
||||||
|
"been successful yet, it's set to an empty string.";
|
||||||
|
|
||||||
|
char const* torrent_status_total_download_doc = "";
|
||||||
|
char const* torrent_status_total_upload_doc = "";
|
||||||
|
char const* torrent_status_total_payload_download_doc = "";
|
||||||
|
char const* torrent_status_total_payload_upload_doc = "";
|
||||||
|
char const* torrent_status_total_failed_bytes_doc = "";
|
||||||
|
|
||||||
|
// -- session_status --------------------------------------------------------
|
||||||
|
|
||||||
|
char const* session_status_doc =
|
||||||
|
"";
|
||||||
|
char const* session_status_has_incoming_connections_doc =
|
||||||
|
"";
|
||||||
|
char const* session_status_upload_rate_doc =
|
||||||
|
"";
|
||||||
|
char const* session_status_download_rate_doc =
|
||||||
|
"";
|
||||||
|
char const* session_status_payload_upload_rate_doc =
|
||||||
|
"";
|
||||||
|
char const* session_status_payload_download_rate_doc =
|
||||||
|
"";
|
||||||
|
char const* session_status_total_download_doc =
|
||||||
|
"";
|
||||||
|
char const* session_status_total_upload_doc =
|
||||||
|
"";
|
||||||
|
char const* session_status_total_payload_download_doc =
|
||||||
|
"";
|
||||||
|
char const* session_status_total_payload_upload_doc =
|
||||||
|
"";
|
||||||
|
char const* session_status_num_peers_doc =
|
||||||
|
"";
|
||||||
|
char const* session_status_dht_nodes_doc =
|
||||||
|
"";
|
||||||
|
char const* session_status_cache_nodes_doc =
|
||||||
|
"";
|
||||||
|
char const* session_status_dht_torrents_doc =
|
||||||
|
"";
|
||||||
|
|
||||||
|
// -- session ---------------------------------------------------------------
|
||||||
|
|
||||||
|
char const* session_doc =
|
||||||
|
"";
|
||||||
|
char const* session_init_doc =
|
||||||
|
"The `fingerprint` is a short string that will be used in\n"
|
||||||
|
"the peer-id to identify the client and the client's version.\n"
|
||||||
|
"For more details see the `fingerprint` class.\n"
|
||||||
|
"The constructor that only takes a fingerprint will not open\n"
|
||||||
|
"a listen port for the session, to get it running you'll have\n"
|
||||||
|
"to call `session.listen_on()`.";
|
||||||
|
|
||||||
|
char const* session_listen_on_doc =
|
||||||
|
"";
|
||||||
|
char const* session_is_listening_doc =
|
||||||
|
"";
|
||||||
|
char const* session_listen_port_doc =
|
||||||
|
"";
|
||||||
|
|
||||||
|
char const* session_status_m_doc =
|
||||||
|
"Returns an instance of `session_status` with session wide-statistics\n"
|
||||||
|
"and status";
|
||||||
|
|
||||||
|
char const* session_start_dht_doc =
|
||||||
|
"";
|
||||||
|
char const* session_stop_dht_doc =
|
||||||
|
"";
|
||||||
|
char const* session_dht_state_doc =
|
||||||
|
"";
|
||||||
|
|
||||||
|
char const* session_add_torrent_doc =
|
||||||
|
"Adds a new torrent to the session. Return a `torrent_handle`.\n"
|
||||||
|
"\n"
|
||||||
|
":Parameters:\n"
|
||||||
|
" - `torrent_info`: `torrent_info` instance representing the torrent\n"
|
||||||
|
" you want to add.\n"
|
||||||
|
" - `save_path`: The path to the directory where files will be saved.\n"
|
||||||
|
" - `resume_data (optional)`: The resume data for this torrent, as decoded\n"
|
||||||
|
" with `bdecode()`. This can be acquired from a running torrent with\n"
|
||||||
|
" `torrent_handle.write_resume_data()`.\n"
|
||||||
|
" - `compact_mode (optional)`: If set to true (default), the storage\n"
|
||||||
|
" will grow as more pieces are downloaded, and pieces are rearranged\n"
|
||||||
|
" to finally be in their correct places once the entire torrent has\n"
|
||||||
|
" been downloaded. If it is false, the entire storage is allocated\n"
|
||||||
|
" before download begins. I.e. the files contained in the torrent\n"
|
||||||
|
" are filled with zeros, and each downloaded piece is put in its\n"
|
||||||
|
" final place directly when downloaded.\n"
|
||||||
|
" - `block_size (optional)`: Sets the preferred request size, i.e.\n"
|
||||||
|
" the number of bytes to request from a peer at a time. This block size\n"
|
||||||
|
" must be a divisor of the piece size, and since the piece size is an\n"
|
||||||
|
" even power of 2, so must the block size be. If the block size given\n"
|
||||||
|
" here turns out to be greater than the piece size, it will simply be\n"
|
||||||
|
" clamped to the piece size.\n"
|
||||||
|
"\n"
|
||||||
|
":Exceptions:\n"
|
||||||
|
" - `duplicate_torrent`: If the torrent you are trying to add already\n"
|
||||||
|
" exists in the session (is either queued for checking, being checked\n"
|
||||||
|
" or downloading) `add_torrent()` will throw `duplicate_torrent`.\n";
|
||||||
|
|
||||||
|
char const* session_remove_torrent_doc =
|
||||||
|
"Close all peer connections associated with the torrent and tell the\n"
|
||||||
|
"tracker that we've stopped participating in the swarm.";
|
||||||
|
|
||||||
|
char const* session_set_download_rate_limit_doc =
|
||||||
|
"";
|
||||||
|
char const* session_set_upload_rate_limit_doc =
|
||||||
|
"";
|
||||||
|
char const* session_set_max_uploads_doc =
|
||||||
|
"";
|
||||||
|
char const* session_set_max_connections_doc =
|
||||||
|
"";
|
||||||
|
char const* session_set_max_half_open_connections_doc =
|
||||||
|
"Sets the maximum number of half-open connections libtorrent will\n"
|
||||||
|
"have when connecting to peers. A half-open connection is one where\n"
|
||||||
|
"connect() has been called, but the connection still hasn't been\n"
|
||||||
|
"established (nor failed). Windows XP Service Pack 2 sets a default,\n"
|
||||||
|
"system wide, limit of the number of half-open connections to 10. So, \n"
|
||||||
|
"this limit can be used to work nicer together with other network\n"
|
||||||
|
"applications on that system. The default is to have no limit, and passing\n"
|
||||||
|
"-1 as the limit, means to have no limit. When limiting the number of\n"
|
||||||
|
"simultaneous connection attempts, peers will be put in a queue waiting\n"
|
||||||
|
"for their turn to get connected.";
|
||||||
|
|
||||||
|
char const* session_set_settings_doc =
|
||||||
|
"";
|
||||||
|
char const* session_set_severity_level_doc =
|
||||||
|
"";
|
||||||
|
char const* session_pop_alert_doc =
|
||||||
|
"";
|
||||||
|
|
||||||
|
// -- alert -----------------------------------------------------------------
|
||||||
|
|
||||||
|
char const* alert_doc =
|
||||||
|
"Base class for all concrete alert classes.";
|
||||||
|
|
||||||
|
char const* alert_msg_doc =
|
||||||
|
"Returns a string describing this alert.";
|
||||||
|
|
||||||
|
char const* alert_severity_doc =
|
||||||
|
"Returns the severity level for this alert, one of `alert.severity_levels`.";
|
||||||
|
|
||||||
|
char const* listen_failed_alert_doc =
|
||||||
|
"This alert is generated when none of the ports, given in the\n"
|
||||||
|
"port range, to `session` can be opened for listening. This alert\n"
|
||||||
|
"is generated as severity level `alert.severity_levels.fatal`.";
|
||||||
|
|
||||||
|
char const* file_error_alert_doc =
|
||||||
|
"If the storage fails to read or write files that it needs access\n"
|
||||||
|
"to, this alert is generated and the torrent is paused. It is\n"
|
||||||
|
"generated as severity level `alert.severity_levels.fatal`.";
|
||||||
|
|
||||||
|
char const* tracker_announce_alert_doc =
|
||||||
|
"This alert is generated each time a tracker announce is sent\n"
|
||||||
|
"(or attempted to be sent). It is generated at severity level `alert.severity_levels.info`.";
|
||||||
|
|
||||||
|
char const* tracker_alert_doc =
|
||||||
|
"This alert is generated on tracker time outs, premature\n"
|
||||||
|
"disconnects, invalid response or a HTTP response other than\n"
|
||||||
|
"\"200 OK\". From the alert you can get the handle to the torrent\n"
|
||||||
|
"the tracker belongs to. This alert is generated as severity level\n"
|
||||||
|
"`alert.severity_levels.warning`.";
|
||||||
|
|
||||||
|
char const* tracker_reply_alert_doc =
|
||||||
|
"This alert is only for informational purpose. It is generated when\n"
|
||||||
|
"a tracker announce succeeds. It is generated with severity level\n"
|
||||||
|
"`alert.severity_levels.info`.";
|
||||||
|
|
||||||
|
char const* tracker_warning_alert_doc =
|
||||||
|
"This alert is triggered if the tracker reply contains a warning\n"
|
||||||
|
"field. Usually this means that the tracker announce was successful\n"
|
||||||
|
", but the tracker has a message to the client. The message string in\n"
|
||||||
|
"the alert will contain the warning message from the tracker. It is\n"
|
||||||
|
"generated with severity level `alert.severity_levels.warning`.";
|
||||||
|
|
||||||
|
char const* url_seed_alert_doc =
|
||||||
|
"This alert is generated when a HTTP seed name lookup fails. This\n"
|
||||||
|
"alert is generated as severity level `alert.severity_levels.warning`.";
|
||||||
|
|
||||||
|
char const* hash_failed_alert_doc =
|
||||||
|
"This alert is generated when a finished piece fails its hash check.\n"
|
||||||
|
"You can get the handle to the torrent which got the failed piece\n"
|
||||||
|
"and the index of the piece itself from the alert. This alert is\n"
|
||||||
|
"generated as severity level `alert.severity_levels.info`.";
|
||||||
|
|
||||||
|
char const* peer_ban_alert_doc =
|
||||||
|
"This alert is generated when a peer is banned because it has sent\n"
|
||||||
|
"too many corrupt pieces to us. It is generated at severity level\n"
|
||||||
|
"`alert.severity_levels.info`. The handle member is a `torrent_handle` to the torrent that\n"
|
||||||
|
"this peer was a member of.";
|
||||||
|
|
||||||
|
char const* peer_error_alert_doc =
|
||||||
|
"This alert is generated when a peer sends invalid data over the\n"
|
||||||
|
"peer-peer protocol. The peer will be disconnected, but you get its\n"
|
||||||
|
"ip address from the alert, to identify it. This alert is generated\n"
|
||||||
|
"is severity level `alert.severity_levels.debug`.";
|
||||||
|
|
||||||
|
char const* invalid_request_alert_doc =
|
||||||
|
"This is a debug alert that is generated by an incoming invalid\n"
|
||||||
|
"piece request. The handle is a handle to the torrent the peer\n"
|
||||||
|
"is a member of. Ip is the address of the peer and the request is\n"
|
||||||
|
"the actual incoming request from the peer. The alert is generated\n"
|
||||||
|
"as severity level `alert.severity_levels.debug`.";
|
||||||
|
|
||||||
|
char const* peer_request_doc =
|
||||||
|
"The `peer_request` contains the values the client sent in its\n"
|
||||||
|
"request message. ``piece`` is the index of the piece it want data\n"
|
||||||
|
"from, ``start`` is the offset within the piece where the data should be\n"
|
||||||
|
"read, and ``length`` is the amount of data it wants.";
|
||||||
|
|
||||||
|
char const* torrent_finished_alert_doc =
|
||||||
|
"This alert is generated when a torrent switches from being a\n"
|
||||||
|
"downloader to a seed. It will only be generated once per torrent.\n"
|
||||||
|
"It contains a `torrent_handle` to the torrent in question. This alert\n"
|
||||||
|
"is generated as severity level `alert.severity_levels.info`.";
|
||||||
|
|
||||||
|
char const* metadata_failed_alert_doc =
|
||||||
|
"This alert is generated when the metadata has been completely\n"
|
||||||
|
"received and the info-hash failed to match it. i.e. the\n"
|
||||||
|
"metadata that was received was corrupt. libtorrent will\n"
|
||||||
|
"automatically retry to fetch it in this case. This is only\n"
|
||||||
|
"relevant when running a torrent-less download, with the metadata\n"
|
||||||
|
"extension provided by libtorrent. It is generated at severity\n"
|
||||||
|
"level `alert.severity_levels.info`.";
|
||||||
|
|
||||||
|
char const* metadata_received_alert_doc =
|
||||||
|
"This alert is generated when the metadata has been completely\n"
|
||||||
|
"received and the torrent can start downloading. It is not generated\n"
|
||||||
|
"on torrents that are started with metadata, but only those that\n"
|
||||||
|
"needs to download it from peers (when utilizing the libtorrent\n"
|
||||||
|
"extension). It is generated at severity level `alert.severity_levels.info`.";
|
||||||
|
|
||||||
|
char const* fastresume_rejected_alert_doc =
|
||||||
|
"This alert is generated when a fastresume file has been passed\n"
|
||||||
|
"to `session.add_torrent` but the files on disk did not match the\n"
|
||||||
|
"fastresume file. The string explains the reason why the resume\n"
|
||||||
|
"file was rejected. It is generated at severity level `alert.severity_levels.warning`.";
|
||||||
|
|
|
@ -0,0 +1,132 @@
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
#include <libtorrent/session.hpp>
|
||||||
|
#include <boost/python.hpp>
|
||||||
|
|
||||||
|
using namespace boost::python;
|
||||||
|
using namespace libtorrent;
|
||||||
|
|
||||||
|
struct entry_to_python
|
||||||
|
{
|
||||||
|
static object convert(entry::list_type const& l)
|
||||||
|
{
|
||||||
|
list result;
|
||||||
|
|
||||||
|
for (entry::list_type::const_iterator i(l.begin()), e(l.end()); i != e; ++i)
|
||||||
|
{
|
||||||
|
result.append(*i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static object convert(entry::dictionary_type const& d)
|
||||||
|
{
|
||||||
|
dict result;
|
||||||
|
|
||||||
|
for (entry::dictionary_type::const_iterator i(d.begin()), e(d.end()); i != e; ++i)
|
||||||
|
result[i->first] = i->second;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static object convert0(entry const& e)
|
||||||
|
{
|
||||||
|
switch (e.type())
|
||||||
|
{
|
||||||
|
case entry::int_t:
|
||||||
|
return object(e.integer());
|
||||||
|
case entry::string_t:
|
||||||
|
return object(e.string());
|
||||||
|
case entry::list_t:
|
||||||
|
return convert(e.list());
|
||||||
|
case entry::dictionary_t:
|
||||||
|
return convert(e.dict());
|
||||||
|
}
|
||||||
|
|
||||||
|
return object();
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject* convert(entry const& e)
|
||||||
|
{
|
||||||
|
return incref(convert0(e).ptr());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct entry_from_python
|
||||||
|
{
|
||||||
|
entry_from_python()
|
||||||
|
{
|
||||||
|
converter::registry::push_back(
|
||||||
|
&convertible, &construct, type_id<entry>()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* convertible(PyObject* e)
|
||||||
|
{
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
static entry construct0(object e)
|
||||||
|
{
|
||||||
|
if (extract<dict>(e).check())
|
||||||
|
{
|
||||||
|
dict d = extract<dict>(e);
|
||||||
|
list items(d.items());
|
||||||
|
std::size_t length = extract<std::size_t>(items.attr("__len__")());
|
||||||
|
entry result(entry::dictionary_t);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < length; ++i)
|
||||||
|
{
|
||||||
|
result.dict().insert(
|
||||||
|
std::make_pair(
|
||||||
|
extract<char const*>(items[i][0])()
|
||||||
|
, construct0(items[i][1])
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else if (extract<list>(e).check())
|
||||||
|
{
|
||||||
|
list l = extract<list>(e);
|
||||||
|
|
||||||
|
std::size_t length = extract<std::size_t>(l.attr("__len__")());
|
||||||
|
entry result(entry::list_t);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < length; ++i)
|
||||||
|
{
|
||||||
|
result.list().push_back(construct0(l[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else if (extract<str>(e).check())
|
||||||
|
{
|
||||||
|
return entry(extract<std::string>(e)());
|
||||||
|
}
|
||||||
|
else if (extract<entry::integer_type>(e).check())
|
||||||
|
{
|
||||||
|
return entry(extract<entry::integer_type>(e)());
|
||||||
|
}
|
||||||
|
|
||||||
|
return entry();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void construct(PyObject* e, converter::rvalue_from_python_stage1_data* data)
|
||||||
|
{
|
||||||
|
void* storage = ((converter::rvalue_from_python_storage<entry>*)data)->storage.bytes;
|
||||||
|
new (storage) entry(construct0(object(borrowed(e))));
|
||||||
|
data->convertible = storage;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void bind_entry()
|
||||||
|
{
|
||||||
|
to_python_converter<entry, entry_to_python>();
|
||||||
|
entry_from_python();
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,139 @@
|
||||||
|
// Copyright Daniel Wallin 2007. 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)
|
||||||
|
|
||||||
|
#include <libtorrent/extensions.hpp>
|
||||||
|
#include <libtorrent/entry.hpp>
|
||||||
|
#include <libtorrent/peer_request.hpp>
|
||||||
|
#include <boost/python.hpp>
|
||||||
|
#include "gil.hpp"
|
||||||
|
|
||||||
|
using namespace boost::python;
|
||||||
|
using namespace libtorrent;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
struct torrent_plugin_wrap : torrent_plugin, wrapper<torrent_plugin>
|
||||||
|
{
|
||||||
|
boost::shared_ptr<peer_plugin> new_connection(peer_connection* p)
|
||||||
|
{
|
||||||
|
lock_gil lock;
|
||||||
|
|
||||||
|
if (override f = this->get_override("new_connection"))
|
||||||
|
return f(p);
|
||||||
|
return torrent_plugin::new_connection(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::shared_ptr<peer_plugin> default_new_connection(peer_connection* p)
|
||||||
|
{
|
||||||
|
return this->torrent_plugin::new_connection(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_piece_pass(int index)
|
||||||
|
{
|
||||||
|
lock_gil lock;
|
||||||
|
|
||||||
|
if (override f = this->get_override("on_piece_pass"))
|
||||||
|
f(index);
|
||||||
|
else
|
||||||
|
torrent_plugin::on_piece_pass(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void default_on_piece_pass(int index)
|
||||||
|
{
|
||||||
|
this->torrent_plugin::on_piece_pass(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_piece_failed(int index)
|
||||||
|
{
|
||||||
|
lock_gil lock;
|
||||||
|
|
||||||
|
if (override f = this->get_override("on_piece_failed"))
|
||||||
|
f(index);
|
||||||
|
else
|
||||||
|
torrent_plugin::on_piece_failed(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void default_on_piece_failed(int index)
|
||||||
|
{
|
||||||
|
return this->torrent_plugin::on_piece_failed(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tick()
|
||||||
|
{
|
||||||
|
lock_gil lock;
|
||||||
|
|
||||||
|
if (override f = this->get_override("tick"))
|
||||||
|
f();
|
||||||
|
else
|
||||||
|
torrent_plugin::tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
void default_tick()
|
||||||
|
{
|
||||||
|
return this->torrent_plugin::tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool on_pause()
|
||||||
|
{
|
||||||
|
lock_gil lock;
|
||||||
|
|
||||||
|
if (override f = this->get_override("on_pause"))
|
||||||
|
return f();
|
||||||
|
return torrent_plugin::on_pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool default_on_pause()
|
||||||
|
{
|
||||||
|
return this->torrent_plugin::on_pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool on_resume()
|
||||||
|
{
|
||||||
|
lock_gil lock;
|
||||||
|
|
||||||
|
if (override f = this->get_override("on_resume"))
|
||||||
|
return f();
|
||||||
|
return torrent_plugin::on_resume();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool default_on_resume()
|
||||||
|
{
|
||||||
|
return this->torrent_plugin::on_resume();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace unnamed
|
||||||
|
|
||||||
|
void bind_extensions()
|
||||||
|
{
|
||||||
|
class_<
|
||||||
|
torrent_plugin_wrap, boost::shared_ptr<torrent_plugin_wrap>, boost::noncopyable
|
||||||
|
>("torrent_plugin")
|
||||||
|
.def(
|
||||||
|
"new_connection"
|
||||||
|
, &torrent_plugin::new_connection, &torrent_plugin_wrap::default_new_connection
|
||||||
|
)
|
||||||
|
.def(
|
||||||
|
"on_piece_pass"
|
||||||
|
, &torrent_plugin::on_piece_pass, &torrent_plugin_wrap::default_on_piece_pass
|
||||||
|
)
|
||||||
|
.def(
|
||||||
|
"on_piece_failed"
|
||||||
|
, &torrent_plugin::on_piece_failed, &torrent_plugin_wrap::default_on_piece_failed
|
||||||
|
)
|
||||||
|
.def(
|
||||||
|
"tick"
|
||||||
|
, &torrent_plugin::tick, &torrent_plugin_wrap::default_tick
|
||||||
|
)
|
||||||
|
.def(
|
||||||
|
"on_pause"
|
||||||
|
, &torrent_plugin::on_pause, &torrent_plugin_wrap::default_on_pause
|
||||||
|
)
|
||||||
|
.def(
|
||||||
|
"on_resume"
|
||||||
|
, &torrent_plugin::on_resume, &torrent_plugin_wrap::default_on_resume
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
#include <boost/python.hpp>
|
||||||
|
#include <boost/filesystem/path.hpp>
|
||||||
|
|
||||||
|
using namespace boost::python;
|
||||||
|
|
||||||
|
struct path_to_python
|
||||||
|
{
|
||||||
|
static PyObject* convert(boost::filesystem::path const& p)
|
||||||
|
{
|
||||||
|
return incref(object(p.string()).ptr());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct path_from_python
|
||||||
|
{
|
||||||
|
path_from_python()
|
||||||
|
{
|
||||||
|
converter::registry::push_back(
|
||||||
|
&convertible, &construct, type_id<boost::filesystem::path>()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* convertible(PyObject* x)
|
||||||
|
{
|
||||||
|
return PyString_Check(x) ? x : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void construct(PyObject* x, converter::rvalue_from_python_stage1_data* data)
|
||||||
|
{
|
||||||
|
void* storage = ((converter::rvalue_from_python_storage<
|
||||||
|
boost::filesystem::path
|
||||||
|
>*)data)->storage.bytes;
|
||||||
|
new (storage) boost::filesystem::path(PyString_AsString(x));
|
||||||
|
data->convertible = storage;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void bind_filesystem()
|
||||||
|
{
|
||||||
|
to_python_converter<boost::filesystem::path, path_to_python>();
|
||||||
|
path_from_python();
|
||||||
|
|
||||||
|
boost::filesystem::path::default_name_check(boost::filesystem::native);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
#include <libtorrent/fingerprint.hpp>
|
||||||
|
#include <boost/python.hpp>
|
||||||
|
|
||||||
|
void bind_fingerprint()
|
||||||
|
{
|
||||||
|
using namespace boost::python;
|
||||||
|
using namespace libtorrent;
|
||||||
|
|
||||||
|
class_<fingerprint>("fingerprint", no_init)
|
||||||
|
.def(
|
||||||
|
init<char const*,int,int,int,int>(
|
||||||
|
(arg("id"), "major", "minor", "revision", "tag")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.def("__str__", &fingerprint::to_string)
|
||||||
|
.def_readonly("name", &fingerprint::name)
|
||||||
|
.def_readonly("major_version", &fingerprint::major_version)
|
||||||
|
.def_readonly("minor_version", &fingerprint::minor_version)
|
||||||
|
.def_readonly("revision_version", &fingerprint::revision_version)
|
||||||
|
.def_readonly("tag_version", &fingerprint::tag_version)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,144 @@
|
||||||
|
// Copyright Daniel Wallin 2007. 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 GIL_070107_HPP
|
||||||
|
# define GIL_070107_HPP
|
||||||
|
|
||||||
|
# include <boost/python/make_function.hpp>
|
||||||
|
# include <boost/python/def_visitor.hpp>
|
||||||
|
# include <boost/python/signature.hpp>
|
||||||
|
# include <boost/mpl/at.hpp>
|
||||||
|
|
||||||
|
//namespace libtorrent { namespace python {
|
||||||
|
|
||||||
|
// RAII helper to release GIL.
|
||||||
|
struct allow_threading_guard
|
||||||
|
{
|
||||||
|
allow_threading_guard()
|
||||||
|
: save(PyEval_SaveThread())
|
||||||
|
{}
|
||||||
|
|
||||||
|
~allow_threading_guard()
|
||||||
|
{
|
||||||
|
PyEval_RestoreThread(save);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyThreadState* save;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct lock_gil
|
||||||
|
{
|
||||||
|
lock_gil()
|
||||||
|
: state(PyGILState_Ensure())
|
||||||
|
{}
|
||||||
|
|
||||||
|
~lock_gil()
|
||||||
|
{
|
||||||
|
PyGILState_Release(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyGILState_STATE state;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class F, class R>
|
||||||
|
struct allow_threading
|
||||||
|
{
|
||||||
|
allow_threading(F fn)
|
||||||
|
: fn(fn)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template <class A0>
|
||||||
|
R operator()(A0& a0)
|
||||||
|
{
|
||||||
|
allow_threading_guard guard;
|
||||||
|
return (a0.*fn)();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class A0, class A1>
|
||||||
|
R operator()(A0& a0, A1& a1)
|
||||||
|
{
|
||||||
|
allow_threading_guard guard;
|
||||||
|
return (a0.*fn)(a1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class A0, class A1, class A2>
|
||||||
|
R operator()(A0& a0, A1& a1, A2& a2)
|
||||||
|
{
|
||||||
|
allow_threading_guard guard;
|
||||||
|
return (a0.*fn)(a1,a2);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class A0, class A1, class A2, class A3>
|
||||||
|
R operator()(A0& a0, A1& a1, A2& a2, A3& a3)
|
||||||
|
{
|
||||||
|
allow_threading_guard guard;
|
||||||
|
return (a0.*fn)(a1,a2,a3);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class A0, class A1, class A2, class A3, class A4>
|
||||||
|
R operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4)
|
||||||
|
{
|
||||||
|
allow_threading_guard guard;
|
||||||
|
return (a0.*fn)(a1,a2,a3,a4);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class A0, class A1, class A2, class A3, class A4, class A5>
|
||||||
|
R operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5)
|
||||||
|
{
|
||||||
|
allow_threading_guard guard;
|
||||||
|
return (a0.*fn)(a1,a2,a3,a4,a5);
|
||||||
|
}
|
||||||
|
|
||||||
|
F fn;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class F>
|
||||||
|
struct visitor : boost::python::def_visitor<visitor<F> >
|
||||||
|
{
|
||||||
|
visitor(F fn)
|
||||||
|
: fn(fn)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template <class Class, class Options, class Signature>
|
||||||
|
void visit_aux(
|
||||||
|
Class& cl, char const* name
|
||||||
|
, Options const& options, Signature const& signature) const
|
||||||
|
{
|
||||||
|
typedef typename boost::mpl::at_c<Signature,0>::type return_type;
|
||||||
|
|
||||||
|
cl.def(
|
||||||
|
name
|
||||||
|
, boost::python::make_function(
|
||||||
|
allow_threading<F, return_type>(fn)
|
||||||
|
, options.policies()
|
||||||
|
, options.keywords()
|
||||||
|
, signature
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Class, class Options>
|
||||||
|
void visit(Class& cl, char const* name, Options const& options) const
|
||||||
|
{
|
||||||
|
this->visit_aux(
|
||||||
|
cl, name, options
|
||||||
|
, boost::python::detail::get_signature(fn, (typename Class::wrapped_type*)0)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
F fn;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Member function adaptor that releases and aqcuires the GIL
|
||||||
|
// around the function call.
|
||||||
|
template <class F>
|
||||||
|
visitor<F> allow_threads(F fn)
|
||||||
|
{
|
||||||
|
return visitor<F>(fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
//}} // namespace libtorrent::python
|
||||||
|
|
||||||
|
#endif // GIL_070107_HPP
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
#include <boost/python/module.hpp>
|
||||||
|
|
||||||
|
void bind_utility();
|
||||||
|
void bind_fingerprint();
|
||||||
|
void bind_big_number();
|
||||||
|
void bind_session();
|
||||||
|
void bind_entry();
|
||||||
|
void bind_torrent_info();
|
||||||
|
void bind_filesystem();
|
||||||
|
void bind_torrent_handle();
|
||||||
|
void bind_torrent_status();
|
||||||
|
void bind_session_settings();
|
||||||
|
void bind_version();
|
||||||
|
void bind_alert();
|
||||||
|
void bind_datetime();
|
||||||
|
void bind_extensions();
|
||||||
|
void bind_peer_plugin();
|
||||||
|
void bind_torrent();
|
||||||
|
void bind_peer_info();
|
||||||
|
|
||||||
|
BOOST_PYTHON_MODULE(libtorrent)
|
||||||
|
{
|
||||||
|
Py_Initialize();
|
||||||
|
PyEval_InitThreads();
|
||||||
|
|
||||||
|
bind_utility();
|
||||||
|
bind_fingerprint();
|
||||||
|
bind_big_number();
|
||||||
|
bind_entry();
|
||||||
|
bind_session();
|
||||||
|
bind_torrent_info();
|
||||||
|
bind_filesystem();
|
||||||
|
bind_torrent_handle();
|
||||||
|
bind_torrent_status();
|
||||||
|
bind_session_settings();
|
||||||
|
bind_version();
|
||||||
|
bind_alert();
|
||||||
|
bind_datetime();
|
||||||
|
bind_extensions();
|
||||||
|
bind_peer_plugin();
|
||||||
|
bind_torrent();
|
||||||
|
bind_peer_info();
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
// Copyright Daniel Wallin 2007. 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 OPTIONAL_070108_HPP
|
||||||
|
# define OPTIONAL_070108_HPP
|
||||||
|
|
||||||
|
# include <boost/python.hpp>
|
||||||
|
# include <boost/optional.hpp>
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct optional_to_python
|
||||||
|
{
|
||||||
|
optional_to_python()
|
||||||
|
{
|
||||||
|
boost::python::to_python_converter<
|
||||||
|
boost::optional<T>, optional_to_python<T>
|
||||||
|
>();
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject* convert(boost::optional<T> const& x)
|
||||||
|
{
|
||||||
|
if (!x)
|
||||||
|
return boost::python::incref(Py_None);
|
||||||
|
|
||||||
|
return boost::python::incref(boost::python::object(*x).ptr());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // OPTIONAL_070108_HPP
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
// Copyright Daniel Wallin 2007. 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)
|
||||||
|
|
||||||
|
#include <libtorrent/peer_info.hpp>
|
||||||
|
#include <boost/python.hpp>
|
||||||
|
|
||||||
|
using namespace boost::python;
|
||||||
|
using namespace libtorrent;
|
||||||
|
|
||||||
|
void bind_peer_info()
|
||||||
|
{
|
||||||
|
scope pi = class_<peer_info>("peer_info")
|
||||||
|
.def_readonly("flags", &peer_info::flags)
|
||||||
|
.def_readonly("ip", &peer_info::ip)
|
||||||
|
.def_readonly("up_speed", &peer_info::up_speed)
|
||||||
|
.def_readonly("down_speed", &peer_info::down_speed)
|
||||||
|
.def_readonly("payload_up_speed", &peer_info::payload_up_speed)
|
||||||
|
.def_readonly("payload_down_speed", &peer_info::payload_down_speed)
|
||||||
|
.def_readonly("total_download", &peer_info::total_download)
|
||||||
|
.def_readonly("total_upload", &peer_info::total_upload)
|
||||||
|
.def_readonly("pid", &peer_info::pid)
|
||||||
|
.def_readonly("pieces", &peer_info::pieces)
|
||||||
|
.def_readonly("seed", &peer_info::seed)
|
||||||
|
.def_readonly("upload_limit", &peer_info::upload_limit)
|
||||||
|
.def_readonly("download_limit", &peer_info::download_limit)
|
||||||
|
.def_readonly("load_balancing", &peer_info::load_balancing)
|
||||||
|
.def_readonly("download_queue_length", &peer_info::download_queue_length)
|
||||||
|
.def_readonly("upload_queue_length", &peer_info::upload_queue_length)
|
||||||
|
.def_readonly("downloading_piece_index", &peer_info::downloading_piece_index)
|
||||||
|
.def_readonly("downloading_block_index", &peer_info::downloading_block_index)
|
||||||
|
.def_readonly("downloading_progress", &peer_info::downloading_progress)
|
||||||
|
.def_readonly("downloading_total", &peer_info::downloading_total)
|
||||||
|
.def_readonly("client", &peer_info::client)
|
||||||
|
.def_readonly("connection_type", &peer_info::connection_type)
|
||||||
|
;
|
||||||
|
|
||||||
|
pi.attr("interesting") = (int)peer_info::interesting;
|
||||||
|
pi.attr("choked") = (int)peer_info::choked;
|
||||||
|
pi.attr("remote_interested") = (int)peer_info::remote_interested;
|
||||||
|
pi.attr("remote_choked") = (int)peer_info::remote_choked;
|
||||||
|
pi.attr("supports_extensions") = (int)peer_info::supports_extensions;
|
||||||
|
pi.attr("local_connection") = (int)peer_info::local_connection;
|
||||||
|
pi.attr("handshake") = (int)peer_info::handshake;
|
||||||
|
pi.attr("connecting") = (int)peer_info::connecting;
|
||||||
|
pi.attr("queued") = (int)peer_info::queued;
|
||||||
|
|
||||||
|
pi.attr("standard_bittorrent") = 0;
|
||||||
|
pi.attr("web_seed") = 1;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,344 @@
|
||||||
|
// Copyright Daniel Wallin 2007. 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)
|
||||||
|
|
||||||
|
#include <libtorrent/extensions.hpp>
|
||||||
|
#include <libtorrent/entry.hpp>
|
||||||
|
#include <libtorrent/peer_request.hpp>
|
||||||
|
#include <boost/python.hpp>
|
||||||
|
|
||||||
|
using namespace boost::python;
|
||||||
|
using namespace libtorrent;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
struct peer_plugin_wrap : peer_plugin, wrapper<peer_plugin>
|
||||||
|
{
|
||||||
|
void add_handshake(entry& e)
|
||||||
|
{
|
||||||
|
if (override f = this->get_override("add_handshake"))
|
||||||
|
e = call<entry>(f.ptr(), e);
|
||||||
|
else
|
||||||
|
peer_plugin::add_handshake(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
void default_add_handshake(entry& e)
|
||||||
|
{
|
||||||
|
this->peer_plugin::add_handshake(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool on_handshake()
|
||||||
|
{
|
||||||
|
if (override f = this->get_override("on_handshake"))
|
||||||
|
return f();
|
||||||
|
else
|
||||||
|
return peer_plugin::on_handshake();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool default_on_handshake()
|
||||||
|
{
|
||||||
|
return this->peer_plugin::on_handshake();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool on_extension_handshake(entry const& e)
|
||||||
|
{
|
||||||
|
if (override f = this->get_override("on_extension_handshake"))
|
||||||
|
return f(e);
|
||||||
|
else
|
||||||
|
return peer_plugin::on_extension_handshake(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool default_on_extension_handshake(entry const& e)
|
||||||
|
{
|
||||||
|
return this->peer_plugin::on_extension_handshake(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool on_choke()
|
||||||
|
{
|
||||||
|
if (override f = this->get_override("on_choke"))
|
||||||
|
return f();
|
||||||
|
else
|
||||||
|
return peer_plugin::on_choke();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool default_on_choke()
|
||||||
|
{
|
||||||
|
return this->peer_plugin::on_choke();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool on_unchoke()
|
||||||
|
{
|
||||||
|
if (override f = this->get_override("on_unchoke"))
|
||||||
|
return f();
|
||||||
|
else
|
||||||
|
return peer_plugin::on_unchoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool default_on_unchoke()
|
||||||
|
{
|
||||||
|
return this->peer_plugin::on_unchoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool on_interested()
|
||||||
|
{
|
||||||
|
if (override f = this->get_override("on_interested"))
|
||||||
|
return f();
|
||||||
|
else
|
||||||
|
return peer_plugin::on_interested();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool default_on_interested()
|
||||||
|
{
|
||||||
|
return this->peer_plugin::on_interested();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool on_not_interested()
|
||||||
|
{
|
||||||
|
if (override f = this->get_override("on_not_interested"))
|
||||||
|
return f();
|
||||||
|
else
|
||||||
|
return peer_plugin::on_not_interested();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool default_on_not_interested()
|
||||||
|
{
|
||||||
|
return this->peer_plugin::on_not_interested();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool on_have(int index)
|
||||||
|
{
|
||||||
|
if (override f = this->get_override("on_have"))
|
||||||
|
return f(index);
|
||||||
|
else
|
||||||
|
return peer_plugin::on_have(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool default_on_have(int index)
|
||||||
|
{
|
||||||
|
return this->peer_plugin::on_have(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool on_bitfield(std::vector<bool> const& bitfield)
|
||||||
|
{
|
||||||
|
if (override f = this->get_override("on_bitfield"))
|
||||||
|
return f(bitfield);
|
||||||
|
else
|
||||||
|
return peer_plugin::on_bitfield(bitfield);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool default_on_bitfield(std::vector<bool> const& bitfield)
|
||||||
|
{
|
||||||
|
return this->peer_plugin::on_bitfield(bitfield);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool on_request(peer_request const& req)
|
||||||
|
{
|
||||||
|
if (override f = this->get_override("on_request"))
|
||||||
|
return f(req);
|
||||||
|
else
|
||||||
|
return peer_plugin::on_request(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool default_on_request(peer_request const& req)
|
||||||
|
{
|
||||||
|
return this->peer_plugin::on_request(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool on_piece(peer_request const& piece, char const* data)
|
||||||
|
{
|
||||||
|
if (override f = this->get_override("on_piece"))
|
||||||
|
return f(piece, data);
|
||||||
|
else
|
||||||
|
return peer_plugin::on_piece(piece, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool default_on_piece(peer_request const& piece, char const* data)
|
||||||
|
{
|
||||||
|
return this->peer_plugin::on_piece(piece, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool on_cancel(peer_request const& req)
|
||||||
|
{
|
||||||
|
if (override f = this->get_override("on_cancel"))
|
||||||
|
return f(req);
|
||||||
|
else
|
||||||
|
return peer_plugin::on_cancel(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool default_on_cancel(peer_request const& req)
|
||||||
|
{
|
||||||
|
return this->peer_plugin::on_cancel(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool on_extended(int length, int msg, buffer::const_interval body)
|
||||||
|
{
|
||||||
|
if (override f = this->get_override("on_extended"))
|
||||||
|
return f(length, msg, body);
|
||||||
|
else
|
||||||
|
return peer_plugin::on_extended(length, msg, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool default_on_extended(int length, int msg, buffer::const_interval body)
|
||||||
|
{
|
||||||
|
return this->peer_plugin::on_extended(length, msg, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool on_unknown_message(int length, int msg, buffer::const_interval body)
|
||||||
|
{
|
||||||
|
if (override f = this->get_override("on_unknown_message"))
|
||||||
|
return f(length, msg, body);
|
||||||
|
else
|
||||||
|
return peer_plugin::on_unknown_message(length, msg, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool default_on_unknown_message(int length, int msg, buffer::const_interval body)
|
||||||
|
{
|
||||||
|
return this->peer_plugin::on_unknown_message(length, msg, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_piece_pass(int index)
|
||||||
|
{
|
||||||
|
if (override f = this->get_override("on_piece_pass"))
|
||||||
|
f(index);
|
||||||
|
else
|
||||||
|
peer_plugin::on_piece_pass(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void default_on_piece_pass(int index)
|
||||||
|
{
|
||||||
|
this->peer_plugin::on_piece_pass(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_piece_failed(int index)
|
||||||
|
{
|
||||||
|
if (override f = this->get_override("on_piece_failed"))
|
||||||
|
f(index);
|
||||||
|
else
|
||||||
|
peer_plugin::on_piece_failed(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void default_on_piece_failed(int index)
|
||||||
|
{
|
||||||
|
this->peer_plugin::on_piece_failed(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tick()
|
||||||
|
{
|
||||||
|
if (override f = this->get_override("tick"))
|
||||||
|
f();
|
||||||
|
else
|
||||||
|
peer_plugin::tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
void default_tick()
|
||||||
|
{
|
||||||
|
this->peer_plugin::tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool write_request(peer_request const& req)
|
||||||
|
{
|
||||||
|
if (override f = this->get_override("write_request"))
|
||||||
|
return f(req);
|
||||||
|
else
|
||||||
|
return peer_plugin::write_request(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool default_write_request(peer_request const& req)
|
||||||
|
{
|
||||||
|
return this->peer_plugin::write_request(req);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
object get_buffer()
|
||||||
|
{
|
||||||
|
static char const data[] = "foobar";
|
||||||
|
return object(handle<>(PyBuffer_FromMemory((void*)data, 6)));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace unnamed
|
||||||
|
|
||||||
|
void bind_peer_plugin()
|
||||||
|
{
|
||||||
|
class_<
|
||||||
|
peer_plugin_wrap, boost::shared_ptr<peer_plugin_wrap>, boost::noncopyable
|
||||||
|
>("peer_plugin")
|
||||||
|
.def(
|
||||||
|
"add_handshake"
|
||||||
|
, &peer_plugin::add_handshake, &peer_plugin_wrap::default_add_handshake
|
||||||
|
)
|
||||||
|
.def(
|
||||||
|
"on_handshake"
|
||||||
|
, &peer_plugin::on_handshake, &peer_plugin_wrap::default_on_handshake
|
||||||
|
)
|
||||||
|
.def(
|
||||||
|
"on_extension_handshake"
|
||||||
|
, &peer_plugin::on_extension_handshake
|
||||||
|
, &peer_plugin_wrap::default_on_extension_handshake
|
||||||
|
)
|
||||||
|
.def(
|
||||||
|
"on_choke"
|
||||||
|
, &peer_plugin::on_choke, &peer_plugin_wrap::default_on_choke
|
||||||
|
)
|
||||||
|
.def(
|
||||||
|
"on_unchoke"
|
||||||
|
, &peer_plugin::on_unchoke, &peer_plugin_wrap::default_on_unchoke
|
||||||
|
)
|
||||||
|
.def(
|
||||||
|
"on_interested"
|
||||||
|
, &peer_plugin::on_interested, &peer_plugin_wrap::default_on_interested
|
||||||
|
)
|
||||||
|
.def(
|
||||||
|
"on_not_interested"
|
||||||
|
, &peer_plugin::on_not_interested, &peer_plugin_wrap::default_on_not_interested
|
||||||
|
)
|
||||||
|
.def(
|
||||||
|
"on_have"
|
||||||
|
, &peer_plugin::on_have, &peer_plugin_wrap::default_on_have
|
||||||
|
)
|
||||||
|
.def(
|
||||||
|
"on_bitfield"
|
||||||
|
, &peer_plugin::on_bitfield, &peer_plugin_wrap::default_on_bitfield
|
||||||
|
)
|
||||||
|
.def(
|
||||||
|
"on_request"
|
||||||
|
, &peer_plugin::on_request, &peer_plugin_wrap::default_on_request
|
||||||
|
)
|
||||||
|
.def(
|
||||||
|
"on_piece"
|
||||||
|
, &peer_plugin::on_piece, &peer_plugin_wrap::default_on_piece
|
||||||
|
)
|
||||||
|
.def(
|
||||||
|
"on_cancel"
|
||||||
|
, &peer_plugin::on_cancel, &peer_plugin_wrap::default_on_cancel
|
||||||
|
)
|
||||||
|
.def(
|
||||||
|
"on_piece_pass"
|
||||||
|
, &peer_plugin::on_piece_pass, &peer_plugin_wrap::default_on_piece_pass
|
||||||
|
)
|
||||||
|
.def(
|
||||||
|
"on_piece_failed"
|
||||||
|
, &peer_plugin::on_piece_failed, &peer_plugin_wrap::default_on_piece_failed
|
||||||
|
)
|
||||||
|
.def(
|
||||||
|
"tick"
|
||||||
|
, &peer_plugin::tick, &peer_plugin_wrap::default_tick
|
||||||
|
)
|
||||||
|
.def(
|
||||||
|
"write_request"
|
||||||
|
, &peer_plugin::write_request, &peer_plugin_wrap::default_write_request
|
||||||
|
)
|
||||||
|
// These seem to make VC7.1 freeze. Needs special handling.
|
||||||
|
|
||||||
|
/*.def(
|
||||||
|
"on_extended"
|
||||||
|
, &peer_plugin::on_extended, &peer_plugin_wrap::default_on_extended
|
||||||
|
)
|
||||||
|
.def(
|
||||||
|
"on_unknown_message"
|
||||||
|
, &peer_plugin::on_unknown_message, &peer_plugin_wrap::default_on_unknown_message
|
||||||
|
)*/
|
||||||
|
;
|
||||||
|
|
||||||
|
def("get_buffer", &get_buffer);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,204 @@
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
#include <libtorrent/session.hpp>
|
||||||
|
#include <libtorrent/torrent.hpp>
|
||||||
|
#include <boost/python.hpp>
|
||||||
|
#include "gil.hpp"
|
||||||
|
|
||||||
|
using namespace boost::python;
|
||||||
|
using namespace libtorrent;
|
||||||
|
|
||||||
|
extern char const* session_status_doc;
|
||||||
|
extern char const* session_status_has_incoming_connections_doc;
|
||||||
|
extern char const* session_status_upload_rate_doc;
|
||||||
|
extern char const* session_status_download_rate_doc;
|
||||||
|
extern char const* session_status_payload_upload_rate_doc;
|
||||||
|
extern char const* session_status_payload_download_rate_doc;
|
||||||
|
extern char const* session_status_total_download_doc;
|
||||||
|
extern char const* session_status_total_upload_doc;
|
||||||
|
extern char const* session_status_total_payload_download_doc;
|
||||||
|
extern char const* session_status_total_payload_upload_doc;
|
||||||
|
extern char const* session_status_num_peers_doc;
|
||||||
|
extern char const* session_status_dht_nodes_doc;
|
||||||
|
extern char const* session_status_cache_nodes_doc;
|
||||||
|
extern char const* session_status_dht_torrents_doc;
|
||||||
|
|
||||||
|
extern char const* session_doc;
|
||||||
|
extern char const* session_init_doc;
|
||||||
|
extern char const* session_listen_on_doc;
|
||||||
|
extern char const* session_is_listening_doc;
|
||||||
|
extern char const* session_listen_port_doc;
|
||||||
|
extern char const* session_status_m_doc;
|
||||||
|
extern char const* session_start_dht_doc;
|
||||||
|
extern char const* session_stop_dht_doc;
|
||||||
|
extern char const* session_dht_state_doc;
|
||||||
|
extern char const* session_add_torrent_doc;
|
||||||
|
extern char const* session_remove_torrent_doc;
|
||||||
|
extern char const* session_set_download_rate_limit_doc;
|
||||||
|
extern char const* session_set_upload_rate_limit_doc;
|
||||||
|
extern char const* session_set_max_uploads_doc;
|
||||||
|
extern char const* session_set_max_connections_doc;
|
||||||
|
extern char const* session_set_max_half_open_connections_doc;
|
||||||
|
extern char const* session_set_settings_doc;
|
||||||
|
extern char const* session_set_severity_level_doc;
|
||||||
|
extern char const* session_pop_alert_doc;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
bool listen_on(session& s, int min_, int max_, char const* interface)
|
||||||
|
{
|
||||||
|
allow_threading_guard guard;
|
||||||
|
return s.listen_on(std::make_pair(min_, max_), interface);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct invoke_extension_factory
|
||||||
|
{
|
||||||
|
invoke_extension_factory(object const& callback)
|
||||||
|
: cb(callback)
|
||||||
|
{}
|
||||||
|
|
||||||
|
boost::shared_ptr<torrent_plugin> operator()(torrent* t)
|
||||||
|
{
|
||||||
|
lock_gil lock;
|
||||||
|
return extract<boost::shared_ptr<torrent_plugin> >(cb(ptr(t)))();
|
||||||
|
}
|
||||||
|
|
||||||
|
object cb;
|
||||||
|
};
|
||||||
|
|
||||||
|
void add_extension(session& s, object const& e)
|
||||||
|
{
|
||||||
|
// allow_threading_guard guard;
|
||||||
|
s.add_extension(invoke_extension_factory(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace unnamed
|
||||||
|
|
||||||
|
void bind_session()
|
||||||
|
{
|
||||||
|
class_<session_status>("session_status", session_status_doc)
|
||||||
|
.def_readonly(
|
||||||
|
"has_incoming_connections", &session_status::has_incoming_connections
|
||||||
|
, session_status_has_incoming_connections_doc
|
||||||
|
)
|
||||||
|
.def_readonly(
|
||||||
|
"upload_rate", &session_status::upload_rate
|
||||||
|
, session_status_upload_rate_doc
|
||||||
|
)
|
||||||
|
.def_readonly(
|
||||||
|
"download_rate", &session_status::download_rate
|
||||||
|
, session_status_download_rate_doc
|
||||||
|
)
|
||||||
|
.def_readonly(
|
||||||
|
"payload_upload_rate", &session_status::payload_upload_rate
|
||||||
|
, session_status_payload_upload_rate_doc
|
||||||
|
)
|
||||||
|
.def_readonly(
|
||||||
|
"payload_download_rate", &session_status::payload_download_rate
|
||||||
|
, session_status_payload_download_rate_doc
|
||||||
|
)
|
||||||
|
.def_readonly(
|
||||||
|
"total_download", &session_status::total_download
|
||||||
|
, session_status_total_download_doc
|
||||||
|
)
|
||||||
|
.def_readonly(
|
||||||
|
"total_upload", &session_status::total_upload
|
||||||
|
, session_status_total_upload_doc
|
||||||
|
)
|
||||||
|
.def_readonly(
|
||||||
|
"total_payload_download", &session_status::total_payload_download
|
||||||
|
, session_status_total_payload_download_doc
|
||||||
|
)
|
||||||
|
.def_readonly(
|
||||||
|
"total_payload_upload", &session_status::total_payload_upload
|
||||||
|
, session_status_total_payload_upload_doc
|
||||||
|
)
|
||||||
|
.def_readonly(
|
||||||
|
"num_peers", &session_status::num_peers
|
||||||
|
, session_status_num_peers_doc
|
||||||
|
)
|
||||||
|
#ifndef TORRENT_DISABLE_DHT
|
||||||
|
.def_readonly(
|
||||||
|
"dht_nodes", &session_status::dht_nodes
|
||||||
|
, session_status_dht_nodes_doc
|
||||||
|
)
|
||||||
|
.def_readonly(
|
||||||
|
"dht_cache_nodes", &session_status::dht_node_cache
|
||||||
|
, session_status_cache_nodes_doc
|
||||||
|
)
|
||||||
|
.def_readonly(
|
||||||
|
"dht_torrents", &session_status::dht_torrents
|
||||||
|
, session_status_dht_torrents_doc
|
||||||
|
)
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
|
||||||
|
torrent_handle (session::*add_torrent0)(
|
||||||
|
torrent_info const&
|
||||||
|
, boost::filesystem::path const&
|
||||||
|
, entry const&
|
||||||
|
, bool
|
||||||
|
, int
|
||||||
|
) = &session::add_torrent;
|
||||||
|
|
||||||
|
class_<session, boost::noncopyable>("session", session_doc, no_init)
|
||||||
|
.def(
|
||||||
|
init<fingerprint>(arg("fingerprint")=fingerprint("LT",0,1,0,0), session_init_doc)
|
||||||
|
)
|
||||||
|
.def(
|
||||||
|
"listen_on", &listen_on
|
||||||
|
, (arg("min"), "max", arg("interface") = (char const*)0)
|
||||||
|
, session_listen_on_doc
|
||||||
|
)
|
||||||
|
.def("is_listening", allow_threads(&session::is_listening), session_is_listening_doc)
|
||||||
|
.def("listen_port", allow_threads(&session::listen_port), session_listen_port_doc)
|
||||||
|
.def("status", allow_threads(&session::status), session_status_m_doc)
|
||||||
|
#ifndef TORRENT_DISABLE_DHT
|
||||||
|
.def("start_dht", allow_threads(&session::start_dht), session_start_dht_doc)
|
||||||
|
.def("stop_dht", allow_threads(&session::stop_dht), session_stop_dht_doc)
|
||||||
|
.def("dht_state", allow_threads(&session::dht_state), session_dht_state_doc)
|
||||||
|
#endif
|
||||||
|
.def(
|
||||||
|
"add_torrent", allow_threads(add_torrent0)
|
||||||
|
, (
|
||||||
|
arg("torrent_info"), "save_path", arg("resume_data") = entry()
|
||||||
|
, arg("compact_mode") = true, arg("block_size") = 16 * 1024
|
||||||
|
)
|
||||||
|
, session_add_torrent_doc
|
||||||
|
)
|
||||||
|
.def("remove_torrent", allow_threads(&session::remove_torrent), session_remove_torrent_doc)
|
||||||
|
.def(
|
||||||
|
"set_download_rate_limit", allow_threads(&session::set_download_rate_limit)
|
||||||
|
, session_set_download_rate_limit_doc
|
||||||
|
)
|
||||||
|
.def(
|
||||||
|
"set_upload_rate_limit", allow_threads(&session::set_upload_rate_limit)
|
||||||
|
, session_set_upload_rate_limit_doc
|
||||||
|
)
|
||||||
|
.def(
|
||||||
|
"set_max_uploads", allow_threads(&session::set_max_uploads)
|
||||||
|
, session_set_max_uploads_doc
|
||||||
|
)
|
||||||
|
.def(
|
||||||
|
"set_max_connections", allow_threads(&session::set_max_connections)
|
||||||
|
, session_set_max_connections_doc
|
||||||
|
)
|
||||||
|
.def(
|
||||||
|
"set_max_half_open_connections", allow_threads(&session::set_max_half_open_connections)
|
||||||
|
, session_set_max_half_open_connections_doc
|
||||||
|
)
|
||||||
|
.def("set_settings", allow_threads(&session::set_settings), session_set_settings_doc)
|
||||||
|
.def(
|
||||||
|
"set_severity_level", allow_threads(&session::set_severity_level)
|
||||||
|
, session_set_severity_level_doc
|
||||||
|
)
|
||||||
|
.def("pop_alert", allow_threads(&session::pop_alert), session_pop_alert_doc)
|
||||||
|
.def("add_extension", &add_extension)
|
||||||
|
;
|
||||||
|
|
||||||
|
register_ptr_to_python<std::auto_ptr<alert> >();
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
#include <libtorrent/session.hpp>
|
||||||
|
#include <boost/python.hpp>
|
||||||
|
|
||||||
|
using namespace boost::python;
|
||||||
|
using namespace libtorrent;
|
||||||
|
|
||||||
|
void bind_session_settings()
|
||||||
|
{
|
||||||
|
class_<session_settings>("session_settings")
|
||||||
|
.def_readwrite("proxy_ip", &session_settings::proxy_ip)
|
||||||
|
.def_readwrite("proxy_port", &session_settings::proxy_port)
|
||||||
|
.def_readwrite("proxy_login", &session_settings::proxy_login)
|
||||||
|
.def_readwrite("proxy_password", &session_settings::proxy_password)
|
||||||
|
.def_readwrite("user_agent", &session_settings::user_agent)
|
||||||
|
.def_readwrite("tracker_completion_timeout", &session_settings::tracker_completion_timeout)
|
||||||
|
.def_readwrite("tracker_receive_timeout", &session_settings::tracker_receive_timeout)
|
||||||
|
.def_readwrite("tracker_maximum_response_length", &session_settings::tracker_maximum_response_length)
|
||||||
|
.def_readwrite("piece_timeout", &session_settings::piece_timeout)
|
||||||
|
.def_readwrite("request_queue_time", &session_settings::request_queue_time)
|
||||||
|
.def_readwrite("max_allowed_in_request_queue", &session_settings::max_allowed_in_request_queue)
|
||||||
|
.def_readwrite("max_out_request_queue", &session_settings::max_out_request_queue)
|
||||||
|
.def_readwrite("whole_pieces_threshold", &session_settings::whole_pieces_threshold)
|
||||||
|
.def_readwrite("peer_timeout", &session_settings::peer_timeout)
|
||||||
|
.def_readwrite("urlseed_timeout", &session_settings::urlseed_timeout)
|
||||||
|
.def_readwrite("urlseed_pipeline_size", &session_settings::urlseed_pipeline_size)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
// Copyright Daniel Wallin 2007. 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)
|
||||||
|
|
||||||
|
#include <libtorrent/torrent.hpp>
|
||||||
|
#include <boost/python.hpp>
|
||||||
|
|
||||||
|
using namespace boost::python;
|
||||||
|
using namespace libtorrent;
|
||||||
|
|
||||||
|
void bind_torrent()
|
||||||
|
{
|
||||||
|
class_<torrent, boost::noncopyable>("torrent", no_init);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,128 @@
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
#include <libtorrent/torrent_handle.hpp>
|
||||||
|
#include <boost/python.hpp>
|
||||||
|
#include "gil.hpp"
|
||||||
|
|
||||||
|
using namespace boost::python;
|
||||||
|
using namespace libtorrent;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
std::vector<announce_entry>::const_iterator begin_trackers(torrent_handle& i)
|
||||||
|
{
|
||||||
|
allow_threading_guard guard;
|
||||||
|
return i.trackers().begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<announce_entry>::const_iterator end_trackers(torrent_handle& i)
|
||||||
|
{
|
||||||
|
allow_threading_guard guard;
|
||||||
|
return i.trackers().end();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace unnamed
|
||||||
|
|
||||||
|
list file_progress(torrent_handle& handle)
|
||||||
|
{
|
||||||
|
std::vector<float> p;
|
||||||
|
|
||||||
|
{
|
||||||
|
allow_threading_guard guard;
|
||||||
|
p.reserve(handle.get_torrent_info().num_files());
|
||||||
|
handle.file_progress(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
list result;
|
||||||
|
|
||||||
|
for (std::vector<float>::iterator i(p.begin()), e(p.end()); i != e; ++i)
|
||||||
|
result.append(*i);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
list get_peer_info(torrent_handle const& handle)
|
||||||
|
{
|
||||||
|
std::vector<peer_info> pi;
|
||||||
|
|
||||||
|
{
|
||||||
|
allow_threading_guard guard;
|
||||||
|
handle.get_peer_info(pi);
|
||||||
|
}
|
||||||
|
|
||||||
|
list result;
|
||||||
|
|
||||||
|
for (std::vector<peer_info>::iterator i = pi.begin(); i != pi.end(); ++i)
|
||||||
|
{
|
||||||
|
result.append(*i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void replace_trackers(torrent_handle& info, object trackers)
|
||||||
|
{
|
||||||
|
object iter(trackers.attr("__iter__")());
|
||||||
|
|
||||||
|
std::vector<announce_entry> result;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
handle<> entry(allow_null(PyIter_Next(iter.ptr())));
|
||||||
|
|
||||||
|
if (entry == handle<>())
|
||||||
|
break;
|
||||||
|
|
||||||
|
result.push_back(extract<announce_entry const&>(object(entry)));
|
||||||
|
}
|
||||||
|
|
||||||
|
allow_threading_guard guard;
|
||||||
|
info.replace_trackers(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bind_torrent_handle()
|
||||||
|
{
|
||||||
|
void (torrent_handle::*force_reannounce0)() const = &torrent_handle::force_reannounce;
|
||||||
|
void (torrent_handle::*force_reannounce1)(boost::posix_time::time_duration) const
|
||||||
|
= &torrent_handle::force_reannounce;
|
||||||
|
|
||||||
|
return_value_policy<copy_const_reference> copy;
|
||||||
|
|
||||||
|
#define _ allow_threads
|
||||||
|
|
||||||
|
class_<torrent_handle>("torrent_handle")
|
||||||
|
.def("status", _(&torrent_handle::status))
|
||||||
|
.def("torrent_info", _(&torrent_handle::get_torrent_info), return_internal_reference<>())
|
||||||
|
.def("is_valid", _(&torrent_handle::is_valid))
|
||||||
|
.def("write_resume_data", _(&torrent_handle::write_resume_data))
|
||||||
|
.def("force_reannounce", _(force_reannounce0))
|
||||||
|
.def("force_reannounce", _(force_reannounce1))
|
||||||
|
.def("set_tracker_login", _(&torrent_handle::set_tracker_login))
|
||||||
|
.def("add_url_seed", _(&torrent_handle::add_url_seed))
|
||||||
|
.def("set_ratio", _(&torrent_handle::set_ratio))
|
||||||
|
.def("set_max_uploads", _(&torrent_handle::set_max_uploads))
|
||||||
|
.def("set_max_connections", _(&torrent_handle::set_max_connections))
|
||||||
|
.def("set_upload_limit", _(&torrent_handle::set_upload_limit))
|
||||||
|
.def("set_download_limit", _(&torrent_handle::set_download_limit))
|
||||||
|
.def("set_sequenced_download_threshold", _(&torrent_handle::set_sequenced_download_threshold))
|
||||||
|
.def("pause", _(&torrent_handle::pause))
|
||||||
|
.def("resume", _(&torrent_handle::resume))
|
||||||
|
.def("is_paused", _(&torrent_handle::is_paused))
|
||||||
|
.def("is_seed", _(&torrent_handle::is_seed))
|
||||||
|
.def("filter_piece", _(&torrent_handle::filter_piece))
|
||||||
|
.def("is_piece_filtered", _(&torrent_handle::is_piece_filtered))
|
||||||
|
.def("has_metadata", _(&torrent_handle::has_metadata))
|
||||||
|
.def("save_path", _(&torrent_handle::save_path))
|
||||||
|
.def("move_storage", _(&torrent_handle::move_storage))
|
||||||
|
.def("info_hash", _(&torrent_handle::info_hash), copy)
|
||||||
|
.def("file_progress", file_progress)
|
||||||
|
.def("trackers", range(begin_trackers, end_trackers))
|
||||||
|
.def("replace_trackers", replace_trackers)
|
||||||
|
.def("get_peer_info", get_peer_info)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,103 @@
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
#include <boost/python.hpp>
|
||||||
|
#include <libtorrent/torrent_info.hpp>
|
||||||
|
|
||||||
|
using namespace boost::python;
|
||||||
|
using namespace libtorrent;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
std::vector<announce_entry>::const_iterator begin_trackers(torrent_info& i)
|
||||||
|
{
|
||||||
|
return i.trackers().begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<announce_entry>::const_iterator end_trackers(torrent_info& i)
|
||||||
|
{
|
||||||
|
return i.trackers().end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_node(torrent_info& ti, char const* hostname, int port)
|
||||||
|
{
|
||||||
|
ti.add_node(std::make_pair(hostname, port));
|
||||||
|
}
|
||||||
|
|
||||||
|
list nodes(torrent_info const& ti)
|
||||||
|
{
|
||||||
|
list result;
|
||||||
|
|
||||||
|
typedef std::vector<std::pair<std::string, int> > list_type;
|
||||||
|
|
||||||
|
for (list_type::const_iterator i = ti.nodes().begin(); i != ti.nodes().end(); ++i)
|
||||||
|
{
|
||||||
|
result.append(make_tuple(i->first, i->second));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace unnamed
|
||||||
|
|
||||||
|
void bind_torrent_info()
|
||||||
|
{
|
||||||
|
return_value_policy<copy_const_reference> copy;
|
||||||
|
|
||||||
|
class_<torrent_info>("torrent_info")
|
||||||
|
.def(init<entry const&>())
|
||||||
|
.def(init<sha1_hash const&>())
|
||||||
|
|
||||||
|
.def("create_torrent", &torrent_info::create_torrent)
|
||||||
|
.def("set_comment", &torrent_info::set_comment)
|
||||||
|
.def("set_piece_size", &torrent_info::set_piece_size)
|
||||||
|
.def("set_creator", &torrent_info::set_creator)
|
||||||
|
.def("set_hash", &torrent_info::set_hash)
|
||||||
|
.def("add_tracker", &torrent_info::add_tracker, (arg("url"), arg("tier")=0))
|
||||||
|
.def("add_file", &torrent_info::add_file)
|
||||||
|
.def("add_url_seed", &torrent_info::add_url_seed)
|
||||||
|
|
||||||
|
.def("name", &torrent_info::name, copy)
|
||||||
|
.def("comment", &torrent_info::comment, copy)
|
||||||
|
.def("creator", &torrent_info::creator, copy)
|
||||||
|
.def("total_size", &torrent_info::total_size)
|
||||||
|
.def("piece_length", &torrent_info::piece_length)
|
||||||
|
.def("num_pieces", &torrent_info::num_pieces)
|
||||||
|
.def("info_hash", &torrent_info::info_hash, copy)
|
||||||
|
|
||||||
|
.def("hash_for_piece", &torrent_info::hash_for_piece, copy)
|
||||||
|
.def("piece_size", &torrent_info::piece_size)
|
||||||
|
|
||||||
|
.def("file_at", &torrent_info::file_at, return_internal_reference<>())
|
||||||
|
.def("files", range(&torrent_info::begin_files, &torrent_info::end_files))
|
||||||
|
|
||||||
|
.def("priv", &torrent_info::priv)
|
||||||
|
.def("set_priv", &torrent_info::set_priv)
|
||||||
|
.def("trackers", range(begin_trackers, end_trackers))
|
||||||
|
|
||||||
|
.def("creation_date", &torrent_info::creation_date)
|
||||||
|
|
||||||
|
.def("add_node", &add_node)
|
||||||
|
.def("nodes", &nodes)
|
||||||
|
;
|
||||||
|
|
||||||
|
class_<file_entry>("file_entry")
|
||||||
|
.add_property(
|
||||||
|
"path"
|
||||||
|
, make_getter(
|
||||||
|
&file_entry::path, return_value_policy<copy_non_const_reference>()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.def_readonly("offset", &file_entry::offset)
|
||||||
|
.def_readonly("size", &file_entry::size)
|
||||||
|
;
|
||||||
|
|
||||||
|
class_<announce_entry>("announce_entry", init<std::string const&>())
|
||||||
|
.def_readwrite("url", &announce_entry::url)
|
||||||
|
.def_readwrite("tier", &announce_entry::tier)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
#include <libtorrent/torrent_handle.hpp>
|
||||||
|
#include <boost/python.hpp>
|
||||||
|
|
||||||
|
using namespace boost::python;
|
||||||
|
using namespace libtorrent;
|
||||||
|
|
||||||
|
object pieces(torrent_status const& s)
|
||||||
|
{
|
||||||
|
list result;
|
||||||
|
|
||||||
|
for (std::vector<bool>::const_iterator i(s.pieces->begin()), e(s.pieces->end()); i != e; ++i)
|
||||||
|
result.append(*i);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern char const* torrent_status_doc;
|
||||||
|
extern char const* torrent_status_state_doc;
|
||||||
|
extern char const* torrent_status_paused_doc;
|
||||||
|
extern char const* torrent_status_progress_doc;
|
||||||
|
extern char const* torrent_status_next_announce_doc;
|
||||||
|
extern char const* torrent_status_announce_interval_doc;
|
||||||
|
extern char const* torrent_status_current_tracker_doc;
|
||||||
|
extern char const* torrent_status_total_download_doc;
|
||||||
|
extern char const* torrent_status_total_upload_doc;
|
||||||
|
extern char const* torrent_status_total_payload_download_doc;
|
||||||
|
extern char const* torrent_status_total_payload_upload_doc;
|
||||||
|
extern char const* torrent_status_total_failed_bytes_doc;
|
||||||
|
|
||||||
|
void bind_torrent_status()
|
||||||
|
{
|
||||||
|
scope status = class_<torrent_status>("torrent_status", torrent_status_doc)
|
||||||
|
.def_readonly("state", &torrent_status::state, torrent_status_state_doc)
|
||||||
|
.def_readonly("paused", &torrent_status::paused, torrent_status_paused_doc)
|
||||||
|
.def_readonly("progress", &torrent_status::progress, torrent_status_progress_doc)
|
||||||
|
.add_property(
|
||||||
|
"next_announce"
|
||||||
|
, make_getter(
|
||||||
|
&torrent_status::next_announce, return_value_policy<return_by_value>()
|
||||||
|
)
|
||||||
|
, torrent_status_next_announce_doc
|
||||||
|
)
|
||||||
|
.add_property(
|
||||||
|
"announce_interval"
|
||||||
|
, make_getter(
|
||||||
|
&torrent_status::announce_interval, return_value_policy<return_by_value>()
|
||||||
|
)
|
||||||
|
, torrent_status_announce_interval_doc
|
||||||
|
)
|
||||||
|
.def_readonly(
|
||||||
|
"current_tracker", &torrent_status::current_tracker
|
||||||
|
, torrent_status_current_tracker_doc
|
||||||
|
)
|
||||||
|
.def_readonly(
|
||||||
|
"total_download", &torrent_status::total_download
|
||||||
|
, torrent_status_total_download_doc
|
||||||
|
)
|
||||||
|
.def_readonly(
|
||||||
|
"total_upload", &torrent_status::total_upload
|
||||||
|
, torrent_status_total_upload_doc
|
||||||
|
)
|
||||||
|
.def_readonly(
|
||||||
|
"total_payload_download", &torrent_status::total_payload_download
|
||||||
|
, torrent_status_total_payload_download_doc
|
||||||
|
)
|
||||||
|
.def_readonly(
|
||||||
|
"total_payload_upload", &torrent_status::total_payload_upload
|
||||||
|
, torrent_status_total_payload_upload_doc
|
||||||
|
)
|
||||||
|
.def_readonly(
|
||||||
|
"total_failed_bytes", &torrent_status::total_failed_bytes
|
||||||
|
, torrent_status_total_failed_bytes_doc
|
||||||
|
)
|
||||||
|
.def_readonly("total_redundant_bytes", &torrent_status::total_redundant_bytes)
|
||||||
|
.def_readonly("download_rate", &torrent_status::download_rate)
|
||||||
|
.def_readonly("upload_rate", &torrent_status::upload_rate)
|
||||||
|
.def_readonly("download_payload_rate", &torrent_status::download_payload_rate)
|
||||||
|
.def_readonly("upload_payload_rate", &torrent_status::upload_payload_rate)
|
||||||
|
.def_readonly("num_peers", &torrent_status::num_peers)
|
||||||
|
.def_readonly("num_complete", &torrent_status::num_complete)
|
||||||
|
.def_readonly("num_incomplete", &torrent_status::num_incomplete)
|
||||||
|
.add_property("pieces", pieces)
|
||||||
|
.def_readonly("num_pieces", &torrent_status::num_pieces)
|
||||||
|
.def_readonly("total_done", &torrent_status::total_done)
|
||||||
|
.def_readonly("total_wanted_done", &torrent_status::total_wanted_done)
|
||||||
|
.def_readonly("total_wanted", &torrent_status::total_wanted)
|
||||||
|
.def_readonly("num_seeds", &torrent_status::num_seeds)
|
||||||
|
.def_readonly("distributed_copies", &torrent_status::distributed_copies)
|
||||||
|
.def_readonly("block_size", &torrent_status::block_size)
|
||||||
|
;
|
||||||
|
|
||||||
|
enum_<torrent_status::state_t>("states")
|
||||||
|
.value("queued_for_checking", torrent_status::queued_for_checking)
|
||||||
|
.value("checking_files", torrent_status::checking_files)
|
||||||
|
.value("connecting_to_tracker", torrent_status::connecting_to_tracker)
|
||||||
|
.value("downloading", torrent_status::downloading)
|
||||||
|
.value("finished", torrent_status::finished)
|
||||||
|
.value("seeding", torrent_status::seeding)
|
||||||
|
.value("allocating", torrent_status::allocating)
|
||||||
|
.export_values()
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
#include <libtorrent/identify_client.hpp>
|
||||||
|
#include <libtorrent/bencode.hpp>
|
||||||
|
#include <boost/python.hpp>
|
||||||
|
|
||||||
|
using namespace boost::python;
|
||||||
|
using namespace libtorrent;
|
||||||
|
|
||||||
|
object client_fingerprint_(peer_id const& id)
|
||||||
|
{
|
||||||
|
boost::optional<fingerprint> result = client_fingerprint(id);
|
||||||
|
return result ? object(*result) : object();
|
||||||
|
}
|
||||||
|
|
||||||
|
entry bdecode_(std::string const& data)
|
||||||
|
{
|
||||||
|
return bdecode(data.begin(), data.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string bencode_(entry const& e)
|
||||||
|
{
|
||||||
|
std::string result;
|
||||||
|
bencode(std::back_inserter(result), e);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bind_utility()
|
||||||
|
{
|
||||||
|
def("identify_client", &libtorrent::identify_client);
|
||||||
|
def("client_fingerprint", &client_fingerprint_);
|
||||||
|
def("bdecode", &bdecode_);
|
||||||
|
def("bencode", &bencode_);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
#include <libtorrent/version.hpp>
|
||||||
|
#include <boost/python.hpp>
|
||||||
|
|
||||||
|
using namespace boost::python;
|
||||||
|
|
||||||
|
void bind_version()
|
||||||
|
{
|
||||||
|
scope().attr("version") = LIBTORRENT_VERSION;
|
||||||
|
scope().attr("version_major") = LIBTORRENT_VERSION_MAJOR;
|
||||||
|
scope().attr("version_minor") = LIBTORRENT_VERSION_MINOR;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue