Python binding initial checkin.

This commit is contained in:
Daniel Wallin 2007-01-10 16:11:43 +00:00
parent 87f7b186b0
commit aa3ce54455
24 changed files with 2440 additions and 0 deletions

27
bindings/python/Jamfile Executable file
View File

@ -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
;

277
bindings/python/client.py Executable file
View File

@ -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()

162
bindings/python/src/alert.cpp Executable file
View File

@ -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)
;
}

View File

@ -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))
;
}

View File

@ -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)

View File

@ -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>();
}

View File

@ -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`.";

132
bindings/python/src/entry.cpp Executable file
View File

@ -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();
}

View File

@ -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
);
}

View File

@ -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);
}

View File

@ -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)
;
}

144
bindings/python/src/gil.hpp Executable file
View File

@ -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

48
bindings/python/src/module.cpp Executable file
View File

@ -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();
}

View File

@ -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

View File

@ -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;
}

View File

@ -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);
}

204
bindings/python/src/session.cpp Executable file
View File

@ -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> >();
}

View File

@ -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)
;
}

15
bindings/python/src/torrent.cpp Executable file
View File

@ -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);
}

View File

@ -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)
;
}

View File

@ -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)
;
}

View File

@ -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()
;
}

37
bindings/python/src/utility.cpp Executable file
View File

@ -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_);
}

16
bindings/python/src/version.cpp Executable file
View File

@ -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;
}