land libtorrent_aio branch in trunk

This commit is contained in:
Arvid Norberg 2014-07-06 19:18:00 +00:00
parent 6ef1b98717
commit 7351389ce8
357 changed files with 58707 additions and 40644 deletions

View File

@ -24,7 +24,7 @@ build_features:
project: libtorrent
branch: trunk
branch: aio
clean:
- test_tmp_*

View File

@ -11,6 +11,7 @@ set(sources
bandwidth_limit
bandwidth_manager
bandwidth_queue_entry
block_cache
bloom_filter
chained_buffer
connection_queue
@ -32,31 +33,43 @@ set(sources
identify_client
ip_filter
ip_voter
performance_counters
peer_class
peer_class_set
peer_connection
bt_peer_connection
web_peer_connection
http_seed_connection
instantiate_connection
natpmp
part_file
packet_buffer
piece_picker
platform_util
proxy_base
policy
puff
random
request_blocks
rss
session
session_impl
settings
session_stats
settings_pack
socket_io
socket_type
socks5_stream
stat
stat_cache
storage
tailqueue
time
timestamp_history
torrent
torrent_handle
torrent_info
torrent_peer
torrent_peer_allocator
tracker_manager
http_tracker_connection
utf8
@ -68,6 +81,8 @@ set(sources
logger
file_pool
lsd
disk_io_job
disk_job_pool
disk_buffer_pool
disk_io_thread
enum_net
@ -298,7 +313,7 @@ set_target_properties(torrent-rasterbar PROPERTIES
SOVERSION 1
VERSION 1)
set (VERSION "1.0.0")
set (VERSION "1.1.0")
get_property (COMPILETIME_OPTIONS_LIST
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIRECTORY}

View File

@ -1,3 +1,32 @@
* deprecate proxy settings in favor of regular settings
* deprecate separate settings for peer protocol encryption
* support specifying listen interfaces and outgoing interfaces as device
names (eth0, en2, tun0 etc.)
* support for using purgrable memory as disk cache on Mac OS.
* be more aggressive in corking sockets, to coalesce messages into larger packets.
* pre-emptively unchoke peers to save one round-trip at connection start-up.
* add session constructor overload that takes a settings_pack
* torrent_info is no longer an intrusive_ptr type. It is held by shared_ptr. This is a non-backwards compatible change
* move listen interface and port to the settings
* move use_interfaces() to be a setting
* extend storage interface to allow deferred flushing and flush the part-file metadata periodically
* make statistics propagate instantly rather than on the second tick
* support for partfiles, where partial pieces belonging to skipped files are put
* support using multiple threads for socket operations (especially useful for high performance SSL connections)
* allow setting rate limits for arbitrary peer groups. Generalizes per-torrent rate limits, and local peer limits
* improved disk cache complexity O(1) instead of O(log(n))
* add feature to allow storing disk cache blocks in an mmapped file (presumably on an SSD)
* optimize peer connection distribution logic across torrents to scale better with many torrents
* replaced std::map with boost::unordered_map for torrent list, to scale better with many torrents
* optimized piece picker
* optimized disk cache
* optimized .torrent file parsing
* optimized initialization of storage when adding a torrent
* added support for adding torrents asynchronously (for improved startup performance)
* added support for asynchronous disk I/O
* almost completely changed the storage interface (for custom storage)
* added support for hashing pieces in multiple threads
* fix compiler warnings
1.0 release

75
Jamfile
View File

@ -23,7 +23,7 @@ if $(BOOST_ROOT)
use-project /boost : $(BOOST_ROOT) ;
}
VERSION = 1.0.0 ;
VERSION = 1.1.0 ;
rule coverage ( properties * )
{
@ -178,10 +178,12 @@ rule linking ( properties * )
# library, so that it properly exports its symbols
result += <define>BOOST_ALL_DYN_LINK ;
result += <library>/boost/system//boost_system/<link>static/<define>BOOST_ALL_DYN_LINK ;
result += <library>/boost/chrono//boost_chrono/<link>static/<define>BOOST_ALL_DYN_LINK ;
}
else
{
result += <library>/boost/system//boost_system/<link>static ;
result += <library>/boost/chrono//boost_chrono/<link>static ;
}
if <toolset>gcc in $(properties) && <link>shared in $(properties)
@ -193,14 +195,7 @@ rule linking ( properties * )
else
{
result += <library>/boost/system//boost_system/<link>shared ;
# when building a shared library with openssl, for some reason we really need
# boost date time (at least on windows). Hopefully a future version of asio
# will allow disabling this dependency
if <encryption>openssl in $(properties)
{
result += <library>/boost/date_time//boost_date_time/<link>shared ;
}
result += <library>/boost/chrono//boost_chrono/<link>shared ;
}
result += <include>$(BOOST_ROOT)
<define>BOOST_ALL_NO_LIB
@ -211,11 +206,7 @@ rule linking ( properties * )
else
{
result += <library>boost_system ;
if <boost-link>shared in $(properties) && <encryption>openssl in $(properties)
{
result += <library>boost_date_time ;
}
result += <library>boost_chrono ;
# on mac the boost headers are installed in
# a directory that isn't automatically accessable
@ -326,14 +317,6 @@ rule tag ( name : type ? : property-set )
feature tcmalloc : no yes : composite propagated link-incompatible ;
feature timer : auto boost absolute performance clock system_time
: composite propagated link-incompatible ;
feature.compose <timer>boost : <define>TORRENT_USE_BOOST_DATE_TIME=1 ;
feature.compose <timer>absolute : <define>TORRENT_USE_ABSOLUTE_TIME=1 ;
feature.compose <timer>performance : <define>TORRENT_USE_PERFORMANCE_TIMER=1 ;
feature.compose <timer>clock : <define>TORRENT_USE_CLOCK_GETTIME=1 ;
feature.compose <timer>system_time : <define>TORRENT_USE_SYSTEM_TIME=1 ;
feature ipv6 : on off : composite propagated link-incompatible ;
feature.compose <ipv6>off : <define>TORRENT_USE_IPV6=0 ;
@ -350,6 +333,9 @@ feature need-librt : no yes : composite propagated link-incompatible ;
feature fiemap : off on : composite propagated ;
feature.compose <fiemap>on : <define>HAVE_LINUX_FIEMAP_H ;
feature file-leak-logging : off on : composite propagated ;
feature.compose <file-leak-logging>on : <define>TORRENT_DEBUG_FILE_LEAKS=1 ;
feature i2p : on off : composite propagated ;
feature.compose <i2p>on : <define>TORRENT_USE_I2P=1 ;
feature.compose <i2p>off : <define>TORRENT_USE_I2P=0 ;
@ -364,6 +350,9 @@ feature.compose <valgrind>on : <define>TORRENT_USE_VALGRIND=1 ;
feature full-stats : on off : composite propagated link-incompatible ;
feature.compose <full-stats>off : <define>TORRENT_DISABLE_FULL_STATS ;
feature memory-optimization : off on : composite propagated link-incompatible ;
feature.compose <memory-optimization>on : <define>TORRENT_OPTIMIZE_MEMORY_USAGE ;
feature asserts : auto on off production system : composite propagated ;
feature.compose <asserts>on : <define>TORRENT_RELEASE_ASSERTS=1 ;
feature.compose <asserts>production : <define>TORRENT_PRODUCTION_ASSERTS=1 <define>TORRENT_RELEASE_ASSERTS=1 ;
@ -381,9 +370,13 @@ feature.compose <extensions>off : <define>TORRENT_DISABLE_EXTENSIONS ;
feature asio-debugging : off on : composite propagated link-incompatible ;
feature.compose <asio-debugging>on : <define>TORRENT_ASIO_DEBUGGING ;
feature picker-debugging : off on : composite propagated link-incompatible ;
feature.compose <picker-debugging>on : <define>TORRENT_DEBUG_REFCOUNTS ;
# deprecated use allocator=pool instead
feature pool-allocators : on off : composite propagated link-incompatible ;
feature pool-allocators : on off debug : composite propagated link-incompatible ;
feature.compose <pool-allocators>off : <define>TORRENT_DISABLE_POOL_ALLOCATOR ;
feature.compose <pool-allocators>debug : <define>TORRENT_DISABLE_POOL_ALLOCATOR <define>TORRENT_DEBUG_BUFFERS ;
feature allocator : pool system debug : composite propagated ;
feature.compose <allocator>system : <define>TORRENT_DISABLE_POOL_ALLOCATOR ;
@ -409,6 +402,9 @@ feature.compose <request-log>on : <define>TORRENT_REQUEST_LOGGING ;
feature disk-stats : off on : composite propagated link-incompatible ;
feature.compose <disk-stats>on : <define>TORRENT_DISK_STATS ;
feature buffer-stats : off on : composite propagated link-incompatible ;
feature.compose <buffer-stats>on : <define>TORRENT_BUFFER_STATS ;
feature simulate-slow-read : off on : composite propagated ;
feature.compose <simulate-slow-read>on : <define>TORRENT_SIMULATE_SLOW_READ ;
@ -455,6 +451,9 @@ feature fpic : off on : composite propagated link-incompatible ;
feature.compose <fpic>on : <cflags>-fPIC ;
feature.compose <fpic>off : <toolset>darwin:<cflags>-mdynamic-no-pic ;
feature profile-calls : off on : composite propagated link-incompatible ;
feature.compose <profile-calls>on : <define>TORRENT_PROFILE_CALLS=1 ;
# controls whether or not to export some internal
# libtorrent functions. Used for unit testing
feature export-extra : off on : composite propagated ;
@ -487,9 +486,9 @@ lib boost_system : : <target-os>darwin <name>boost_system-mt $(boost-library-sea
lib boost_system : : <target-os>solaris <name>boost_system $(boost-library-search-path) ;
lib boost_system : : <name>boost_system ;
lib boost_date_time : : <target-os>darwin <name>boost_date_time-mt $(boost-library-search-path) ;
lib boost_date_time : : <target-os>solaris <name>boost_date_time $(boost-library-search-path) ;
lib boost_date_time : : <name>boost_date_time ;
lib boost_chrono : : <target-os>darwin <name>boost_chrono-mt $(boost-library-search-path) ;
lib boost_chrono : : <target-os>solaris <name>boost_chrono $(boost-library-search-path) ;
lib boost_chrono : : <name>boost_chrono ;
# openssl on linux/bsd/macos etc.
lib gcrypt : : <name>gcrypt <link>shared <search>/opt/local/lib ;
@ -497,6 +496,7 @@ lib z : : <link>shared <name>z <search>/usr/lib ;
lib crypto : : <name>crypto <search>/usr/lib <use>z ;
lib ssl : : <name>ssl <link>shared <use>crypto <search>/opt/local/lib ;
lib dl : : <link>shared <name>dl ;
lib aio : : <link>shared <name>aio ;
# time functions used on linux require librt
lib librt : : <name>rt <link>shared ;
@ -523,11 +523,16 @@ SOURCES =
bandwidth_limit
bandwidth_manager
bandwidth_queue_entry
block_cache
bloom_filter
chained_buffer
connection_queue
crc32c
create_torrent
disk_buffer_holder
disk_buffer_pool
disk_io_job
disk_job_pool
entry
error_code
file_storage
@ -544,6 +549,7 @@ SOURCES =
ip_filter
ip_voter
peer_connection
platform_util
bt_peer_connection
web_connection_base
web_peer_connection
@ -554,12 +560,13 @@ SOURCES =
packet_buffer
piece_picker
policy
proxy_base
puff
random
rss
session
session_impl
settings
settings_pack
socket_io
socket_type
socks5_stream
@ -568,11 +575,14 @@ SOURCES =
torrent
torrent_handle
torrent_info
torrent_peer
torrent_peer_allocator
time
tracker_manager
http_tracker_connection
udp_tracker_connection
sha1
tailqueue
timestamp_history
udp_socket
upnp
@ -591,6 +601,14 @@ SOURCES =
ConvertUTF
thread
xml_parse
peer_class
peer_class_set
part_file
stat_cache
request_blocks
session_stats
performance_counters
resolver
# -- extensions --
metadata_transfer
@ -610,6 +628,7 @@ KADEMLIA_SOURCES =
routing_table
traversal_algorithm
logging
dos_blocker
get_peers
item
get_item
@ -683,6 +702,7 @@ lib torrent
<include>./ed25519/src
<threading>multi
<link>shared:<define>TORRENT_BUILDING_SHARED
<define>BOOST_NO_DEPRECATED
# on windows, when linking statically against asio
# but producing a DLL, everything inside the DLL needs
@ -708,6 +728,7 @@ lib torrent
: # usage requirements
$(usage-requirements)
<link>shared:<define>TORRENT_LINKING_SHARED
;
headers = [ path.glob-tree include/libtorrent : *.hpp ] ;

View File

@ -104,6 +104,8 @@ DOCS_PAGES = \
docs/python_binding.rst \
docs/tuning.html \
docs/tuning.rst \
docs/settings.rst \
docs/stats_counters.rst \
docs/troubleshooting.html \
docs/udp_tracker_protocol.html \
docs/udp_tracker_protocol.rst \

View File

@ -1,114 +0,0 @@
#!/usr/bin/env python
from distutils import sysconfig
from distutils.core import setup, Extension
import os
import platform
import sys
import shutil
import multiprocessing
import subprocess
def parse_cmd(cmdline, prefix, keep_prefix = False):
ret = []
for token in cmdline.split():
if token[:len(prefix)] == prefix:
if keep_prefix:
ret.append(token)
else:
ret.append(token[len(prefix):])
return ret
def arch():
if platform.system() != 'Darwin': return []
a = os.uname()[4]
if a == 'Power Macintosh': a = 'ppc'
return ['-arch', a]
def target_specific():
if platform.system() != 'Darwin': return []
# on mavericks, clang will fail when unknown arguments are
# passed in. python distutils will pass in arguments it doesn't
# know about
return ['-Wno-error=unused-command-line-argument-hard-error-in-future']
try:
extra_cmd = open('compile_flags').read()
except:
extra_cmd = None
try:
ldflags = open('link_flags').read()
except:
ldflags = None
ext = None
packages = None
if '--bjam' in sys.argv or ldflags == None or extra_cmd == None:
del sys.argv[sys.argv.index('--bjam')]
if not '--help' in sys.argv \
and not '--help-commands' in sys.argv:
toolset = ''
file_ext = '.so'
if platform.system() == 'Windows':
# msvc 9.0 (2008) is the official windows compiler for python 2.6
# http://docs.python.org/whatsnew/2.6.html#build-and-c-api-changes
toolset = ' msvc-9.0'
file_ext = '.pyd'
parallell_builds = ' -j%d' % multiprocessing.cpu_count()
# build libtorrent using bjam and build the installer with distutils
cmdline = 'bjam boost=source link=static geoip=static boost-link=static release optimization=space stage_module --abbreviate-paths' + toolset + parallell_builds
print cmdline
if os.system(cmdline) != 0:
print('build failed')
sys.exit(1)
try: os.mkdir('build')
except: pass
try: shutil.rmtree('build/lib')
except: pass
try: os.mkdir('build/lib')
except: pass
try: os.mkdir('libtorrent')
except: pass
shutil.copyfile('libtorrent' + file_ext, 'build/lib/libtorrent' + file_ext)
packages = ['libtorrent']
else:
source_list = os.listdir(os.path.join(os.path.dirname(__file__), "src"))
source_list = [os.path.join("src", s) for s in source_list if s.endswith(".cpp")]
ext = [Extension('libtorrent',
sources = source_list,
language='c++',
include_dirs = ['../../include'] + parse_cmd(extra_cmd, '-I'),
library_dirs = ['../../src/.libs'] + parse_cmd(extra_cmd, '-L'),
extra_link_args = ldflags.split() + arch(),
extra_compile_args = parse_cmd(extra_cmd, '-D', True) + arch() \
+ target_specific(),
libraries = ['torrent-rasterbar'] + parse_cmd(extra_cmd, '-l'))]
setup(name = 'python-libtorrent',
version = '1.0.0',
author = 'Arvid Norberg',
author_email = 'arvid@rasterbar.com',
description = 'Python bindings for libtorrent-rasterbar',
long_description = 'Python bindings for libtorrent-rasterbar',
url = 'http://libtorrent.org',
platforms = [platform.system() + '-' + platform.machine()],
license = 'BSD',
packages = packages,
ext_modules = ext
)

View File

@ -285,8 +285,10 @@ void bind_alert()
class_<listen_failed_alert, bases<alert>, noncopyable>(
"listen_failed_alert", no_init)
.def_readonly("endpoint", &listen_failed_alert::endpoint)
.def_readonly("interface", &listen_failed_alert::interface)
.def_readonly("error", &listen_failed_alert::error)
.def_readonly("operation", &listen_failed_alert::operation)
.def_readonly("sock_type", &listen_failed_alert::sock_type)
;
class_<listen_succeeded_alert, bases<alert>, noncopyable>(

View File

@ -5,7 +5,7 @@
#include <boost/python.hpp>
#include <libtorrent/create_torrent.hpp>
#include <libtorrent/file_storage.hpp>
#include "libtorrent/intrusive_ptr_base.hpp"
#include "libtorrent/torrent_info.hpp"
using namespace boost::python;
using namespace libtorrent;

View File

@ -10,13 +10,14 @@
using namespace boost::python;
using namespace libtorrent;
namespace lt = libtorrent;
extern void dict_to_add_torrent_params(dict params, add_torrent_params& p);
namespace {
#ifndef TORRENT_NO_DEPRECATE
torrent_handle _add_magnet_uri(session& s, std::string uri, dict params)
torrent_handle _add_magnet_uri(lt::session& s, std::string uri, dict params)
{
add_torrent_params p;

View File

@ -39,12 +39,12 @@ BOOST_PYTHON_MODULE(libtorrent)
bind_fingerprint();
bind_sha1_hash();
bind_entry();
bind_torrent_handle();
bind_session();
bind_torrent_info();
#if TORRENT_USE_WSTRING
bind_unicode_string_conversion();
#endif
bind_torrent_handle();
bind_torrent_status();
bind_session_settings();
bind_version();

View File

@ -70,8 +70,11 @@ void bind_peer_info()
.def_readonly("total_upload", &peer_info::total_upload)
.def_readonly("pid", &peer_info::pid)
.add_property("pieces", get_pieces)
#ifndef TORRENT_NO_DEPRECATE
.def_readonly("upload_limit", &peer_info::upload_limit)
.def_readonly("download_limit", &peer_info::download_limit)
.def_readonly("load_balancing", &peer_info::load_balancing)
#endif
.add_property("last_request", get_last_request)
.add_property("last_active", get_last_active)
.add_property("download_queue_time", get_download_queue_time)

View File

@ -10,6 +10,7 @@
#include <libtorrent/storage.hpp>
#include <libtorrent/ip_filter.hpp>
#include <libtorrent/disk_io_thread.hpp>
#include <libtorrent/aux_/session_settings.hpp>
#include <libtorrent/extensions.hpp>
#include <libtorrent/lazy_entry.hpp>
#include <libtorrent/bencode.hpp>
@ -25,41 +26,45 @@
using namespace boost::python;
using namespace libtorrent;
namespace lt = libtorrent;
namespace
{
void listen_on(session& s, int min_, int max_, char const* interface, int flags)
#ifndef TORRENT_NO_DEPRECATE
void listen_on(lt::session& s, int min_, int max_, char const* interface, int flags)
{
allow_threading_guard guard;
error_code ec;
s.listen_on(std::make_pair(min_, max_), ec, interface, flags);
if (ec) throw libtorrent_exception(ec);
}
#endif
void outgoing_ports(session& s, int _min, int _max)
void outgoing_ports(lt::session& s, int _min, int _max)
{
allow_threading_guard guard;
session_settings settings = s.settings();
settings.outgoing_ports = std::make_pair(_min, _max);
s.set_settings(settings);
settings_pack p;
p.set_int(settings_pack::outgoing_port, _min);
p.set_int(settings_pack::num_outgoing_ports, _max - _min);
s.apply_settings(p);
return;
}
#ifndef TORRENT_DISABLE_DHT
void add_dht_node(session& s, tuple n)
void add_dht_node(lt::session& s, tuple n)
{
std::string ip = extract<std::string>(n[0]);
int port = extract<int>(n[1]);
s.add_dht_node(std::make_pair(ip, port));
}
void add_dht_router(session& s, std::string router_, int port_)
void add_dht_router(lt::session& s, std::string router_, int port_)
{
allow_threading_guard guard;
return s.add_dht_router(std::make_pair(router_, port_));
}
#endif
void add_extension(session& s, object const& e)
void add_extension(lt::session& s, object const& e)
{
#ifndef TORRENT_DISABLE_EXTENSIONS
if (!extract<std::string>(e).check()) return;
@ -81,89 +86,72 @@ namespace
#endif // TORRENT_DISABLE_EXTENSIONS
}
void session_set_settings(session& ses, dict const& sett_dict)
void session_set_settings(lt::session& ses, dict const& sett_dict)
{
bencode_map_entry* map;
int len;
boost::tie(map, len) = aux::settings_map();
settings_pack p;
list iterkeys = (list)sett_dict.iterkeys();
for (int i = 0; i < boost::python::len(iterkeys); i++)
{
std::string key = extract<std::string>(iterkeys[i]);
session_settings sett;
for (int i = 0; i < len; ++i)
{
if (!sett_dict.has_key(map[i].name)) continue;
int sett = setting_by_name(key);
if (sett == 0) continue;
void* dest = ((char*)&sett) + map[i].offset;
char const* name = map[i].name;
switch (map[i].type)
TORRENT_TRY
{
case std_string:
*((std::string*)dest) = extract<std::string>(sett_dict[name]);
object value = sett_dict[key];
switch (sett & settings_pack::type_mask)
{
case settings_pack::string_type_base:
p.set_str(sett, extract<std::string>(value));
break;
case character:
*((char*)dest) = extract<char>(sett_dict[name]);
case settings_pack::int_type_base:
p.set_int(sett, extract<int>(value));
break;
case boolean:
*((bool*)dest) = extract<bool>(sett_dict[name]);
break;
case integer:
*((int*)dest) = extract<int>(sett_dict[name]);
break;
case floating_point:
*((float*)dest) = extract<float>(sett_dict[name]);
case settings_pack::bool_type_base:
p.set_bool(sett, extract<bool>(value));
break;
}
}
if (!sett_dict.has_key("outgoing_port"))
sett.outgoing_ports.first = extract<int>(sett_dict["outgoing_port"]);
if (!sett_dict.has_key("num_outgoing_ports"))
sett.outgoing_ports.second = sett.outgoing_ports.first + extract<int>(sett_dict["num_outgoing_ports"]);
ses.set_settings(sett);
TORRENT_CATCH(...) {}
}
dict session_get_settings(session const& ses)
allow_threading_guard guard;
ses.apply_settings(p);
}
dict session_get_settings(lt::session const& ses)
{
session_settings sett;
aux::session_settings sett;
{
allow_threading_guard guard;
sett = ses.settings();
sett = ses.get_settings();
}
dict sett_dict;
bencode_map_entry* map;
int len;
boost::tie(map, len) = aux::settings_map();
for (int i = 0; i < len; ++i)
dict ret;
for (int i = settings_pack::string_type_base;
i < settings_pack::max_string_setting_internal; ++i)
{
void const* dest = ((char const*)&sett) + map[i].offset;
char const* name = map[i].name;
switch (map[i].type)
ret[name_for_setting(i)] = sett.get_str(i);
}
for (int i = settings_pack::int_type_base;
i < settings_pack::max_int_setting_internal; ++i)
{
case std_string:
sett_dict[name] = *((std::string const*)dest);
break;
case character:
sett_dict[name] = *((char const*)dest);
break;
case boolean:
sett_dict[name] = *((bool const*)dest);
break;
case integer:
sett_dict[name] = *((int const*)dest);
break;
case floating_point:
sett_dict[name] = *((float const*)dest);
break;
ret[name_for_setting(i)] = sett.get_int(i);
}
for (int i = settings_pack::bool_type_base;
i < settings_pack::max_bool_setting_internal; ++i)
{
ret[name_for_setting(i)] = sett.get_bool(i);
}
sett_dict["outgoing_port"] = sett.outgoing_ports.first;
sett_dict["num_outgoing_ports"] = sett.outgoing_ports.second - sett.outgoing_ports.first + 1;
return sett_dict;
return ret;
}
#ifndef BOOST_NO_EXCEPTIONS
#ifndef TORRENT_NO_DEPRECATE
torrent_handle add_torrent_depr(session& s, torrent_info const& ti
torrent_handle add_torrent_depr(lt::session& s, torrent_info const& ti
, std::string const& save, entry const& resume
, storage_mode_t storage_mode, bool paused)
{
@ -176,9 +164,9 @@ namespace
void dict_to_add_torrent_params(dict params, add_torrent_params& p)
{
// torrent_info objects are always held by an intrusive_ptr in the python binding
// torrent_info objects are always held by a shared_ptr in the python binding
if (params.has_key("ti") && params.get("ti") != boost::python::object())
p.ti = extract<boost::intrusive_ptr<torrent_info> >(params["ti"]);
p.ti = extract<boost::shared_ptr<torrent_info> >(params["ti"]);
if (params.has_key("info_hash"))
p.info_hash = extract<sha1_hash>(params["info_hash"]);
@ -257,7 +245,7 @@ namespace
namespace
{
torrent_handle add_torrent(session& s, dict params)
torrent_handle add_torrent(lt::session& s, dict params)
{
add_torrent_params p;
dict_to_add_torrent_params(params, p);
@ -272,7 +260,7 @@ namespace
#endif
}
void async_add_torrent(session& s, dict params)
void async_add_torrent(lt::session& s, dict params)
{
add_torrent_params p;
dict_to_add_torrent_params(params, p);
@ -299,7 +287,7 @@ namespace
dict_to_add_torrent_params(dict(params["add_args"]), feed.add_args);
}
feed_handle add_feed(session& s, dict params)
feed_handle add_feed(lt::session& s, dict params)
{
feed_settings feed;
// this static here is a bit of a hack. It will
@ -368,25 +356,27 @@ namespace
return ret;
}
void start_natpmp(session& s)
#ifndef TORRENT_NO_DEPRECATE
void start_natpmp(lt::session& s)
{
allow_threading_guard guard;
s.start_natpmp();
}
void start_upnp(session& s)
void start_upnp(lt::session& s)
{
allow_threading_guard guard;
s.start_upnp();
}
#endif
alert const* wait_for_alert(session& s, int ms)
alert const* wait_for_alert(lt::session& s, int ms)
{
allow_threading_guard guard;
return s.wait_for_alert(milliseconds(ms));
}
list get_torrents(session& s)
list get_torrents(lt::session& s)
{
list ret;
std::vector<torrent_handle> torrents;
@ -402,6 +392,22 @@ namespace
return ret;
}
cache_status get_cache_info1(lt::session& s, torrent_handle h, int flags)
{
cache_status ret;
s.get_cache_info(&ret, h, flags);
return ret;
}
#ifndef TORRENT_NO_DEPRECATE
cache_status get_cache_status(lt::session& s)
{
cache_status ret;
s.get_cache_info(&ret);
return ret;
}
#endif
dict get_utp_stats(session_status const& st)
{
dict ret;
@ -413,7 +419,8 @@ namespace
return ret;
}
list get_cache_info(session& ses, sha1_hash ih)
#ifndef TORRENT_NO_DEPRECATE
list get_cache_info2(lt::session& ses, sha1_hash ih)
{
std::vector<cached_piece_info> ret;
@ -436,22 +443,23 @@ namespace
}
return pieces;
}
#endif
#ifndef TORRENT_DISABLE_GEO_IP
void load_asnum_db(session& s, std::string file)
void load_asnum_db(lt::session& s, std::string file)
{
allow_threading_guard guard;
s.load_asnum_db(file.c_str());
}
void load_country_db(session& s, std::string file)
void load_country_db(lt::session& s, std::string file)
{
allow_threading_guard guard;
s.load_country_db(file.c_str());
}
#endif
entry save_state(session const& s, boost::uint32_t flags)
entry save_state(lt::session const& s, boost::uint32_t flags)
{
allow_threading_guard guard;
entry e;
@ -459,7 +467,7 @@ namespace
return e;
}
object pop_alert(session& ses)
object pop_alert(lt::session& ses)
{
std::auto_ptr<alert> a;
{
@ -470,7 +478,7 @@ namespace
return object(boost::shared_ptr<alert>(a.release()));
}
list pop_alerts(session& ses)
list pop_alerts(lt::session& ses)
{
std::deque<alert*> alerts;
{
@ -487,7 +495,7 @@ namespace
return ret;
}
void load_state(session& ses, entry const& st)
void load_state(lt::session& ses, entry const& st)
{
allow_threading_guard guard;
@ -504,10 +512,10 @@ namespace
void bind_session()
{
#ifndef TORRENT_DISABLE_DHT
void (session::*start_dht0)() = &session::start_dht;
#ifndef TORRENT_NO_DEPRECATE
void (session::*start_dht1)(entry const&) = &session::start_dht;
#ifndef TORRENT_DISABLE_DHT
void (lt::session::*start_dht0)() = &lt::session::start_dht;
void (lt::session::*start_dht1)(entry const&) = &lt::session::start_dht;
#endif
#endif
@ -584,13 +592,13 @@ void bind_session()
#endif
;
enum_<session::options_t>("options_t")
.value("delete_files", session::delete_files)
enum_<lt::session::options_t>("options_t")
.value("delete_files", lt::session::delete_files)
;
enum_<session::session_flags_t>("session_flags_t")
.value("add_default_plugins", session::add_default_plugins)
.value("start_default_features", session::start_default_features)
enum_<lt::session::session_flags_t>("session_flags_t")
.value("add_default_plugins", lt::session::add_default_plugins)
.value("start_default_features", lt::session::start_default_features)
;
enum_<add_torrent_params::flags_t>("add_torrent_params_flags_t")
@ -614,56 +622,76 @@ void bind_session()
.def_readonly("blocks_read", &cache_status::blocks_read)
.def_readonly("blocks_read_hit", &cache_status::blocks_read_hit)
.def_readonly("reads", &cache_status::reads)
#ifndef TORRENT_NO_DEPRECATE
.def_readonly("queued_bytes", &cache_status::queued_bytes)
.def_readonly("cache_size", &cache_status::cache_size)
#endif
.def_readonly("write_cache_size", &cache_status::write_cache_size)
.def_readonly("read_cache_size", &cache_status::read_cache_size)
.def_readonly("pinned_blocks", &cache_status::pinned_blocks)
.def_readonly("total_used_buffers", &cache_status::total_used_buffers)
.def_readonly("average_queue_time", &cache_status::average_queue_time)
.def_readonly("average_read_time", &cache_status::average_read_time)
.def_readonly("average_write_time", &cache_status::average_write_time)
.def_readonly("average_hash_time", &cache_status::average_hash_time)
.def_readonly("average_job_time", &cache_status::average_job_time)
.def_readonly("average_sort_time", &cache_status::average_sort_time)
.def_readonly("job_queue_length", &cache_status::job_queue_length)
.def_readonly("cumulative_job_time", &cache_status::cumulative_job_time)
.def_readonly("cumulative_read_time", &cache_status::cumulative_read_time)
.def_readonly("cumulative_write_time", &cache_status::cumulative_write_time)
.def_readonly("cumulative_hash_time", &cache_status::cumulative_hash_time)
.def_readonly("cumulative_sort_time", &cache_status::cumulative_sort_time)
.def_readonly("total_read_back", &cache_status::total_read_back)
.def_readonly("read_queue_size", &cache_status::read_queue_size)
.def_readonly("blocked_jobs", &cache_status::blocked_jobs)
.def_readonly("queued_jobs", &cache_status::queued_jobs)
.def_readonly("peak_queued", &cache_status::peak_queued)
.def_readonly("pending_jobs", &cache_status::pending_jobs)
.def_readonly("num_jobs", &cache_status::num_jobs)
.def_readonly("num_read_jobs", &cache_status::num_read_jobs)
.def_readonly("num_write_jobs", &cache_status::num_write_jobs)
.def_readonly("arc_mru_size", &cache_status::arc_mru_size)
.def_readonly("arc_mru_ghost_size", &cache_status::arc_mru_ghost_size)
.def_readonly("arc_mfu_size", &cache_status::arc_mfu_size)
.def_readonly("arc_mfu_ghost_size", &cache_status::arc_mfu_ghost_size)
;
class_<session, boost::noncopyable>("session", no_init)
class_<lt::session, boost::noncopyable>("session", no_init)
.def(
init<fingerprint, int>((
arg("fingerprint")=fingerprint("LT",0,1,0,0)
, arg("flags")=session::start_default_features | session::add_default_plugins))
init<settings_pack const&, fingerprint, int>((
arg("settings")
, arg("fingerprint")=fingerprint("LT",0,1,0,0)
, arg("flags")=lt::session::start_default_features | lt::session::add_default_plugins))
)
.def("post_torrent_updates", allow_threads(&session::post_torrent_updates))
.def(
init<fingerprint, int, boost::uint32_t>((
arg("fingerprint")=fingerprint("LT",0,1,0,0)
, arg("flags")=lt::session::start_default_features | lt::session::add_default_plugins
, arg("alert_mask")=alert::error_notification))
)
.def("post_torrent_updates", allow_threads(&lt::session::post_torrent_updates))
#ifndef TORRENT_NO_DEPRECATE
.def(
"listen_on", &listen_on
, (arg("min"), "max", arg("interface") = (char const*)0, arg("flags") = 0)
)
#endif
.def("outgoing_ports", &outgoing_ports)
.def("is_listening", allow_threads(&session::is_listening))
.def("listen_port", allow_threads(&session::listen_port))
.def("status", allow_threads(&session::status))
.def("is_listening", allow_threads(&lt::session::is_listening))
.def("listen_port", allow_threads(&lt::session::listen_port))
.def("status", allow_threads(&lt::session::status))
#ifndef TORRENT_DISABLE_DHT
.def("add_dht_node", add_dht_node)
.def(
"add_dht_router", &add_dht_router
, (arg("router"), "port")
)
.def("is_dht_running", allow_threads(&session::is_dht_running))
.def("set_dht_settings", allow_threads(&session::set_dht_settings))
.def("start_dht", allow_threads(start_dht0))
.def("stop_dht", allow_threads(&session::stop_dht))
.def("is_dht_running", allow_threads(&lt::session::is_dht_running))
.def("set_dht_settings", allow_threads(&lt::session::set_dht_settings))
#ifndef TORRENT_NO_DEPRECATE
.def("start_dht", allow_threads(start_dht0))
.def("stop_dht", allow_threads(&lt::session::stop_dht))
.def("start_dht", allow_threads(start_dht1))
.def("dht_state", allow_threads(&session::dht_state))
.def("set_dht_proxy", allow_threads(&session::set_dht_proxy))
.def("dht_proxy", allow_threads(&session::dht_proxy))
.def("dht_state", allow_threads(&lt::session::dht_state))
.def("set_dht_proxy", allow_threads(&lt::session::set_dht_proxy))
.def("dht_proxy", allow_threads(&lt::session::dht_proxy))
#endif
#endif
.def("add_torrent", &add_torrent)
@ -681,27 +709,27 @@ void bind_session()
#endif
#endif
.def("add_feed", &add_feed)
.def("remove_torrent", allow_threads(&session::remove_torrent), arg("option") = 0)
.def("remove_torrent", allow_threads(&lt::session::remove_torrent), arg("option") = 0)
#ifndef TORRENT_NO_DEPRECATE
.def("set_local_download_rate_limit", allow_threads(&session::set_local_download_rate_limit))
.def("local_download_rate_limit", allow_threads(&session::local_download_rate_limit))
.def("set_local_download_rate_limit", allow_threads(&lt::session::set_local_download_rate_limit))
.def("local_download_rate_limit", allow_threads(&lt::session::local_download_rate_limit))
.def("set_local_upload_rate_limit", allow_threads(&session::set_local_upload_rate_limit))
.def("local_upload_rate_limit", allow_threads(&session::local_upload_rate_limit))
.def("set_local_upload_rate_limit", allow_threads(&lt::session::set_local_upload_rate_limit))
.def("local_upload_rate_limit", allow_threads(&lt::session::local_upload_rate_limit))
.def("set_download_rate_limit", allow_threads(&session::set_download_rate_limit))
.def("download_rate_limit", allow_threads(&session::download_rate_limit))
.def("set_download_rate_limit", allow_threads(&lt::session::set_download_rate_limit))
.def("download_rate_limit", allow_threads(&lt::session::download_rate_limit))
.def("set_upload_rate_limit", allow_threads(&session::set_upload_rate_limit))
.def("upload_rate_limit", allow_threads(&session::upload_rate_limit))
.def("set_upload_rate_limit", allow_threads(&lt::session::set_upload_rate_limit))
.def("upload_rate_limit", allow_threads(&lt::session::upload_rate_limit))
.def("set_max_uploads", allow_threads(&session::set_max_uploads))
.def("set_max_connections", allow_threads(&session::set_max_connections))
.def("max_connections", allow_threads(&session::max_connections))
.def("set_max_half_open_connections", allow_threads(&session::set_max_half_open_connections))
.def("num_connections", allow_threads(&session::num_connections))
.def("set_settings", &session::set_settings)
.def("settings", &session::settings)
.def("set_max_uploads", allow_threads(&lt::session::set_max_uploads))
.def("set_max_connections", allow_threads(&lt::session::set_max_connections))
.def("max_connections", allow_threads(&lt::session::max_connections))
.def("set_max_half_open_connections", allow_threads(&lt::session::set_max_half_open_connections))
.def("num_connections", allow_threads(&lt::session::num_connections))
.def("set_settings", &lt::session::set_settings)
.def("settings", &lt::session::settings)
.def("get_settings", &session_get_settings)
#else
.def("settings", &session_get_settings)
@ -709,8 +737,8 @@ void bind_session()
#endif
.def("set_settings", &session_set_settings)
#ifndef TORRENT_DISABLE_ENCRYPTION
.def("set_pe_settings", allow_threads(&session::set_pe_settings))
.def("get_pe_settings", allow_threads(&session::get_pe_settings))
.def("set_pe_settings", allow_threads(&lt::session::set_pe_settings))
.def("get_pe_settings", allow_threads(&lt::session::get_pe_settings))
#endif
#ifndef TORRENT_DISABLE_GEO_IP
.def("load_asnum_db", &load_asnum_db)
@ -719,69 +747,72 @@ void bind_session()
.def("load_state", &load_state)
.def("save_state", &save_state, (arg("entry"), arg("flags") = 0xffffffff))
#ifndef TORRENT_NO_DEPRECATE
.def("set_severity_level", allow_threads(&session::set_severity_level))
.def("set_alert_queue_size_limit", allow_threads(&session::set_alert_queue_size_limit))
.def("set_severity_level", allow_threads(&lt::session::set_severity_level))
.def("set_alert_queue_size_limit", allow_threads(&lt::session::set_alert_queue_size_limit))
.def("set_alert_mask", allow_threads(&lt::session::set_alert_mask))
#endif
.def("set_alert_mask", allow_threads(&session::set_alert_mask))
.def("pop_alert", &pop_alert)
.def("pop_alerts", &pop_alerts)
.def("wait_for_alert", &wait_for_alert, return_internal_reference<>())
.def("add_extension", &add_extension)
#ifndef TORRENT_NO_DEPRECATE
.def("set_peer_proxy", allow_threads(&session::set_peer_proxy))
.def("set_tracker_proxy", allow_threads(&session::set_tracker_proxy))
.def("set_web_seed_proxy", allow_threads(&session::set_web_seed_proxy))
.def("peer_proxy", allow_threads(&session::peer_proxy))
.def("tracker_proxy", allow_threads(&session::tracker_proxy))
.def("web_seed_proxy", allow_threads(&session::web_seed_proxy))
.def("set_peer_proxy", allow_threads(&lt::session::set_peer_proxy))
.def("set_tracker_proxy", allow_threads(&lt::session::set_tracker_proxy))
.def("set_web_seed_proxy", allow_threads(&lt::session::set_web_seed_proxy))
.def("peer_proxy", allow_threads(&lt::session::peer_proxy))
.def("tracker_proxy", allow_threads(&lt::session::tracker_proxy))
.def("web_seed_proxy", allow_threads(&lt::session::web_seed_proxy))
#endif
#if TORRENT_USE_I2P
.def("set_i2p_proxy", allow_threads(&session::set_i2p_proxy))
.def("i2p_proxy", allow_threads(&session::i2p_proxy))
.def("set_i2p_proxy", allow_threads(&lt::session::set_i2p_proxy))
.def("i2p_proxy", allow_threads(&lt::session::i2p_proxy))
#endif
.def("set_proxy", allow_threads(&session::set_proxy))
.def("proxy", allow_threads(&session::proxy))
.def("start_upnp", &start_upnp)
.def("stop_upnp", allow_threads(&session::stop_upnp))
.def("start_lsd", allow_threads(&session::start_lsd))
.def("stop_lsd", allow_threads(&session::stop_lsd))
.def("start_natpmp", &start_natpmp)
.def("stop_natpmp", allow_threads(&session::stop_natpmp))
.def("set_ip_filter", allow_threads(&session::set_ip_filter))
.def("get_ip_filter", allow_threads(&session::get_ip_filter))
.def("find_torrent", allow_threads(&session::find_torrent))
.def("set_proxy", allow_threads(&lt::session::set_proxy))
.def("proxy", allow_threads(&lt::session::proxy))
.def("set_ip_filter", allow_threads(&lt::session::set_ip_filter))
.def("get_ip_filter", allow_threads(&lt::session::get_ip_filter))
.def("find_torrent", allow_threads(&lt::session::find_torrent))
.def("get_torrents", &get_torrents)
.def("pause", allow_threads(&session::pause))
.def("resume", allow_threads(&session::resume))
.def("is_paused", allow_threads(&session::is_paused))
.def("id", allow_threads(&session::id))
.def("get_cache_status", allow_threads(&session::get_cache_status))
.def("get_cache_info", get_cache_info)
.def("set_peer_id", allow_threads(&session::set_peer_id))
.def("pause", allow_threads(&lt::session::pause))
.def("resume", allow_threads(&lt::session::resume))
.def("is_paused", allow_threads(&lt::session::is_paused))
.def("id", allow_threads(&lt::session::id))
.def("get_cache_info", &get_cache_info1, (arg("handle") = torrent_handle(), arg("flags") = 0))
#ifndef TORRENT_NO_DEPRECATE
.def("start_upnp", &start_upnp)
.def("stop_upnp", allow_threads(&lt::session::stop_upnp))
.def("start_lsd", allow_threads(&lt::session::start_lsd))
.def("stop_lsd", allow_threads(&lt::session::stop_lsd))
.def("start_natpmp", &start_natpmp)
.def("stop_natpmp", allow_threads(&lt::session::stop_natpmp))
.def("get_cache_status", &get_cache_status)
.def("get_cache_info", &get_cache_info2)
#endif
.def("set_peer_id", allow_threads(&lt::session::set_peer_id))
;
enum_<session::save_state_flags_t>("save_state_flags_t")
.value("save_settings", session::save_settings)
.value("save_dht_settings", session::save_dht_settings)
.value("save_dht_state", session::save_dht_state)
.value("save_i2p_proxy", session::save_i2p_proxy)
.value("save_encryption_settings", session:: save_encryption_settings)
.value("save_as_map", session::save_as_map)
.value("save_proxy", session::save_proxy)
enum_<lt::session::save_state_flags_t>("save_state_flags_t")
.value("save_settings", lt::session::save_settings)
.value("save_dht_settings", lt::session::save_dht_settings)
.value("save_dht_state", lt::session::save_dht_state)
.value("save_i2p_proxy", lt::session::save_i2p_proxy)
.value("save_encryption_settings", lt::session:: save_encryption_settings)
.value("save_as_map", lt::session::save_as_map)
.value("save_proxy", lt::session::save_proxy)
#ifndef TORRENT_NO_DEPRECATE
.value("save_dht_proxy", session::save_dht_proxy)
.value("save_peer_proxy", session::save_peer_proxy)
.value("save_web_proxy", session::save_web_proxy)
.value("save_tracker_proxy", session::save_tracker_proxy)
.value("save_dht_proxy", lt::session::save_dht_proxy)
.value("save_peer_proxy", lt::session::save_peer_proxy)
.value("save_web_proxy", lt::session::save_web_proxy)
.value("save_tracker_proxy", lt::session::save_tracker_proxy)
#endif
;
enum_<session::listen_on_flags_t>("listen_on_flags_t")
#ifndef TORRENT_NO_DEPRECATE
.value("listen_reuse_address", session::listen_reuse_address)
#endif
.value("listen_no_system_port", session::listen_no_system_port)
enum_<lt::session::listen_on_flags_t>("listen_on_flags_t")
.value("listen_reuse_address", lt::session::listen_reuse_address)
.value("listen_no_system_port", lt::session::listen_no_system_port)
;
#endif
class_<feed_handle>("feed_handle")
.def("update_feed", &feed_handle::update_feed)
@ -792,11 +823,23 @@ void bind_session()
register_ptr_to_python<std::auto_ptr<alert> >();
def("high_performance_seed", high_performance_seed);
def("min_memory_usage", min_memory_usage);
typedef void (*mem_preset2)(settings_pack& s);
typedef void (*perf_preset2)(settings_pack& s);
#ifndef TORRENT_NO_DEPRECATE
typedef session_settings (*mem_preset1)();
typedef session_settings (*perf_preset1)();
def("high_performance_seed", (perf_preset1)high_performance_seed);
def("min_memory_usage", (mem_preset1)min_memory_usage);
scope().attr("create_metadata_plugin") = "metadata_transfer";
#endif
def("high_performance_seed", (perf_preset2)high_performance_seed);
def("min_memory_usage", (mem_preset2)min_memory_usage);
scope().attr("create_ut_metadata_plugin") = "ut_metadata";
scope().attr("create_ut_pex_plugin") = "ut_pex";
scope().attr("create_smart_ban_plugin") = "smart_ban";
}

View File

@ -10,6 +10,7 @@ using namespace libtorrent;
void bind_session_settings()
{
#ifndef TORRENT_NO_DEPRECATE
class_<session_settings>("session_settings")
.def_readwrite("user_agent", &session_settings::user_agent)
.def_readwrite("tracker_completion_timeout", &session_settings::tracker_completion_timeout)
@ -42,7 +43,7 @@ void bind_session_settings()
.def_readwrite("num_want", &session_settings::num_want)
.def_readwrite("initial_picker_threshold", &session_settings::initial_picker_threshold)
.def_readwrite("allowed_fast_set_size", &session_settings::allowed_fast_set_size)
.def_readwrite("suggest_mode", &session_settings::suggest_mode)
// this is no longer used
.def_readwrite("max_queued_disk_bytes", &session_settings::max_queued_disk_bytes)
.def_readwrite("max_queued_disk_bytes_low_watermark", &session_settings::max_queued_disk_bytes_low_watermark)
.def_readwrite("handshake_timeout", &session_settings::handshake_timeout)
@ -54,10 +55,6 @@ void bind_session_settings()
.def_readwrite("send_buffer_low_watermark", &session_settings::send_buffer_low_watermark)
.def_readwrite("send_buffer_watermark", &session_settings::send_buffer_watermark)
.def_readwrite("send_buffer_watermark_factor", &session_settings::send_buffer_watermark_factor)
#ifndef TORRENT_NO_DEPRECATE
.def_readwrite("auto_upload_slots", &session_settings::auto_upload_slots)
.def_readwrite("auto_upload_slots_rate_based", &session_settings::auto_upload_slots_rate_based)
#endif
.def_readwrite("choking_algorithm", &session_settings::choking_algorithm)
.def_readwrite("seed_choking_algorithm", &session_settings::seed_choking_algorithm)
.def_readwrite("use_parole_mode", &session_settings::use_parole_mode)
@ -71,7 +68,6 @@ void bind_session_settings()
.def_readwrite("disk_io_read_mode", &session_settings::disk_io_read_mode)
.def_readwrite("coalesce_reads", &session_settings::coalesce_reads)
.def_readwrite("coalesce_writes", &session_settings::coalesce_writes)
.def_readwrite("outgoing_ports", &session_settings::outgoing_ports)
.def_readwrite("peer_tos", &session_settings::peer_tos)
.def_readwrite("active_downloads", &session_settings::active_downloads)
.def_readwrite("active_seeds", &session_settings::active_seeds)
@ -193,16 +189,6 @@ void bind_session_settings()
.def_readwrite("use_disk_cache_pool", &session_settings::use_disk_cache_pool)
;
enum_<proxy_settings::proxy_type>("proxy_type")
.value("none", proxy_settings::none)
.value("socks4", proxy_settings::socks4)
.value("socks5", proxy_settings::socks5)
.value("socks5_pw", proxy_settings::socks5_pw)
.value("http", proxy_settings::http)
.value("http_pw", proxy_settings::http_pw)
.value("i2p_proxy", proxy_settings::i2p_proxy)
;
enum_<session_settings::disk_cache_algo_t>("disk_cache_algo_t")
.value("lru", session_settings::lru)
.value("largest_contiguous", session_settings::largest_contiguous)
@ -238,6 +224,18 @@ void bind_session_settings()
.value("peer_proportional", session_settings::peer_proportional)
;
#endif
enum_<proxy_settings::proxy_type>("proxy_type")
.value("none", proxy_settings::none)
.value("socks4", proxy_settings::socks4)
.value("socks5", proxy_settings::socks5)
.value("socks5_pw", proxy_settings::socks5_pw)
.value("http", proxy_settings::http)
.value("http_pw", proxy_settings::http_pw)
.value("i2p_proxy", proxy_settings::i2p_proxy)
;
class_<proxy_settings>("proxy_settings")
.def_readwrite("hostname", &proxy_settings::hostname)
.def_readwrite("port", &proxy_settings::port)

View File

@ -115,19 +115,34 @@ list get_peer_info(torrent_handle const& handle)
void prioritize_pieces(torrent_handle& info, object o)
{
std::vector<int> result;
std::vector<std::pair<int, int> > piece_list;
try
{
object iter_obj = object( handle<>( PyObject_GetIter( o.ptr() ) ));
while( 1 )
{
object obj = extract<object>( iter_obj.attr( "next" )() );
result.push_back(extract<int const>( obj ));
extract<int const> val1(obj);
if (val1.check())
{
result.push_back(val1);
continue;
}
extract<std::pair<int, int> > val2(obj);
if (val2.check())
{
piece_list.push_back(val2);
continue;
}
}
}
catch( error_already_set )
{
PyErr_Clear();
if (result.size())
info.prioritize_pieces(result);
else
info.prioritize_pieces(piece_list);
return;
}
}
@ -308,19 +323,21 @@ void connect_peer(torrent_handle& th, tuple ip, int source)
#ifndef TORRENT_NO_DEPRECATE
#if BOOST_VERSION > 104200
boost::intrusive_ptr<const torrent_info> get_torrent_info(torrent_handle const& h)
boost::shared_ptr<const torrent_info> get_torrent_info(torrent_handle const& h)
{
return boost::intrusive_ptr<const torrent_info>(&h.get_torrent_info());
allow_threading_guard guard;
return h.torrent_file();
}
#else
boost::intrusive_ptr<torrent_info> get_torrent_info(torrent_handle const& h)
boost::shared_ptr<torrent_info> get_torrent_info(torrent_handle const& h)
{
// I can't figure out how to expose intrusive_ptr<const torrent_info>
// I can't figure out how to expose shared_ptr<const torrent_info>
// as well as supporting mutable instances. So, this hack is better
// than compilation errors. It seems to work on newer versions of boost though
return boost::intrusive_ptr<torrent_info>(const_cast<torrent_info*>(&h.get_torrent_info()));
allow_threading_guard guard;
return boost::const_pointer_cast<torrent_info>(h.torrent_file());
}
#endif
@ -334,7 +351,8 @@ void set_peer_download_limit(torrent_handle& th, tuple const& ip, int limit)
{
th.set_peer_download_limit(tuple_to_endpoint(ip), limit);
}
#endif
#endif // TORRENT_NO_DEPRECAE
void add_piece(torrent_handle& th, int piece, char const *data, int flags)
{
@ -408,7 +426,7 @@ void bind_torrent_handle()
#endif
// deprecated
#ifndef TORRENT_NO_DEPRECATE
.def("get_torrent_info", get_torrent_info)
.def("get_torrent_info", &get_torrent_info)
.def("super_seeding", super_seeding0)
.def("filter_piece", _(&torrent_handle::filter_piece))
.def("is_piece_filtered", _(&torrent_handle::is_piece_filtered))

View File

@ -3,9 +3,10 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python.hpp>
#include <boost/shared_ptr.hpp>
#include <libtorrent/torrent_info.hpp>
#include "libtorrent/intrusive_ptr_base.hpp"
#include "libtorrent/session_settings.hpp"
#include "libtorrent/time.hpp"
using namespace boost::python;
using namespace libtorrent;
@ -186,14 +187,14 @@ void bind_torrent_info()
.def_readwrite("size", &file_slice::size)
;
class_<torrent_info, boost::intrusive_ptr<torrent_info> >("torrent_info", no_init)
class_<torrent_info, boost::shared_ptr<torrent_info> >("torrent_info", no_init)
#ifndef TORRENT_NO_DEPRECATE
.def(init<entry const&>(arg("e")))
#endif
.def(init<sha1_hash const&, int>((arg("info_hash"), arg("flags") = 0)))
.def(init<char const*, int, int>((arg("buffer"), arg("length"), arg("flags") = 0)))
.def(init<std::string, int>((arg("file"), arg("flags") = 0)))
.def(init<torrent_info const&, int>((arg("ti"), arg("flags") = 0)))
.def(init<torrent_info const&>((arg("ti"))))
#if TORRENT_USE_WSTRING && !defined TORRENT_NO_DEPRECATE
.def(init<std::wstring, int>((arg("file"), arg("flags") = 0)))
#endif
@ -268,7 +269,6 @@ void bind_torrent_info()
.add_property("send_stats", &get_send_stats)
.def("reset", &announce_entry::reset)
.def("failed", &announce_entry::failed, arg("retry_interval") = 0)
.def("can_announce", &announce_entry::can_announce)
.def("is_working", &announce_entry::is_working)
.def("trim", &announce_entry::trim)
@ -282,8 +282,8 @@ void bind_torrent_info()
;
#if BOOST_VERSION > 104200
implicitly_convertible<boost::intrusive_ptr<torrent_info>, boost::intrusive_ptr<const torrent_info> >();
boost::python::register_ptr_to_python<boost::intrusive_ptr<const torrent_info> >();
implicitly_convertible<boost::shared_ptr<torrent_info>, boost::shared_ptr<const torrent_info> >();
boost::python::register_ptr_to_python<boost::shared_ptr<const torrent_info> >();
#endif
}

View File

@ -107,7 +107,9 @@ void bind_torrent_status()
;
enum_<torrent_status::state_t>("states")
#ifndef TORRENT_NO_DEPRECATE
.value("queued_for_checking", torrent_status::queued_for_checking)
#endif
.value("checking_files", torrent_status::checking_files)
.value("downloading_metadata", torrent_status::downloading_metadata)
.value("downloading", torrent_status::downloading)

View File

@ -5,7 +5,7 @@
AC_PREREQ([2.63])
AC_INIT([libtorrent-rasterbar],[1.0.0],[arvid@rasterbar.com],
AC_INIT([libtorrent-rasterbar],[1.1.0],[arvid@rasterbar.com],
[libtorrent-rasterbar],[http://www.libtorrent.org])
AC_CONFIG_SRCDIR([src/torrent.cpp])
AC_CONFIG_AUX_DIR([build-aux])
@ -41,7 +41,7 @@ dnl increment AGE, Otherwise AGE is reset to 0. If CURRENT has changed,
dnl REVISION is set to 0, otherwise REVISION is incremented.
dnl ---------------------------------------------------------------------------
m4_define([VERSION_INFO_CURRENT],[8])
m4_define([VERSION_INFO_CURRENT],[9])
m4_define([VERSION_INFO_REVISION],[0])
m4_define([VERSION_INFO_AGE],[0])
INTERFACE_VERSION_INFO=VERSION_INFO_CURRENT:VERSION_INFO_REVISION:VERSION_INFO_AGE
@ -555,15 +555,6 @@ AS_CASE(["$ARG_ENABLE_PYTHON_BINDING"],
AS_ECHO
AS_ECHO "Checking for external libraries:"
AC_MSG_CHECKING([for FIEMAP support])
AC_CHECK_HEADERS([linux/types.h])
AC_CHECK_HEADERS([linux/fiemap.h], [], [],
[#ifdef HAVE_LINUX_TYPES_H
# include <linux/types.h>
#endif
])
AC_MSG_CHECKING([whether to link against system libgeoip]) #depends: $ac_arg_enable_geoip
AS_CASE(["$ARG_WITH_LIBGEOIP"],
["yes"|"system"], [
@ -641,6 +632,8 @@ AM_CONDITIONAL([WITH_OPENSSL], [test "x$ARG_ENABLE_ENCRYPTION" = "xyes" -o "x$AR
AC_DEFINE([BOOST_ASIO_HASH_MAP_BUCKETS],[1021],[Define to fix a wrong behavior in boost 1.39.])
COMPILETIME_OPTIONS="$COMPILETIME_OPTIONS -DBOOST_ASIO_HASH_MAP_BUCKETS=1021 "
COMPILETIME_OPTIONS="$COMPILETIME_OPTIONS -msse4.2 "
AC_DEFINE([BOOST_EXCEPTION_DISABLE],[1],[Define to disable the boost.exception features.])
COMPILETIME_OPTIONS="$COMPILETIME_OPTIONS -DBOOST_EXCEPTION_DISABLE "

View File

@ -49,7 +49,7 @@
<tr><th class="docinfo-name">Author:</th>
<td>Arvid Norberg, <a class="last reference external" href="mailto:arvid&#64;rasterbar.com">arvid&#64;rasterbar.com</a></td></tr>
<tr><th class="docinfo-name">Version:</th>
<td>1.0.0</td></tr>
<td>1.1.0</td></tr>
</tbody>
</table>
<div class="contents topic" id="table-of-contents">
@ -110,16 +110,16 @@ to step 3 (assuming you also have boost build installed).</p>
<h3>Step 1: Download boost</h3>
<p>You'll find boost <a class="reference external" href="http://sourceforge.net/project/showfiles.php?group_id=7586&amp;package_id=8041&amp;release_id=619445">here</a>.</p>
<p>Extract the archive to some directory where you want it. For the sake of this
guide, let's assume you extract the package to <tt class="docutils literal"><span class="pre">c:\boost_1_34_0</span></tt> (I'm using
guide, let's assume you extract the package to <tt class="docutils literal"><span class="pre">c:\boost_1_55_0</span></tt> (I'm using
a windows path in this example since if you're on linux/unix you're more likely
to use the autotools). You'll need at least version 1.34 of the boost library
to use the autotools). You'll need at least version 1.49 of the boost library
in order to build libtorrent.</p>
</div>
<div class="section" id="step-2-setup-bbv2">
<h3>Step 2: Setup BBv2</h3>
<p>First you need to build <tt class="docutils literal">bjam</tt>. You do this by opening a terminal (In
windows, run <tt class="docutils literal">cmd</tt>). Change directory to
<tt class="docutils literal"><span class="pre">c:\boost_1_34_0\tools\jam\src</span></tt>. Then run the script called
<tt class="docutils literal"><span class="pre">c:\boost_1_55_0\tools\jam\src</span></tt>. Then run the script called
<tt class="docutils literal">build.bat</tt> or <tt class="docutils literal">build.sh</tt> on a unix system. This will build <tt class="docutils literal">bjam</tt> and
place it in a directory starting with <tt class="docutils literal">bin.</tt> and then have the name of your
platform. Copy the <tt class="docutils literal">bjam.exe</tt> (or <tt class="docutils literal">bjam</tt> on a unix system) to a place
@ -133,20 +133,20 @@ set the environment variable <tt class="docutils literal">BOOST_BUILD_PATH</tt>.
<tt class="docutils literal">bjam</tt> where it can find boost-build, your configuration file and all the
toolsets (descriptions used by boost-build to know how to use different
compilers on different platforms). Assuming the boost install path above, set
it to <tt class="docutils literal"><span class="pre">c:\boost_1_34_0\tools\build\v2</span></tt>.</p>
it to <tt class="docutils literal"><span class="pre">c:\boost_1_55_0\tools\build\v2</span></tt>.</p>
<p>To set an environment variable in windows, type for example:</p>
<pre class="literal-block">
set BOOST_BUILD_PATH=c:\boost_1_34_0\tools\build\v2
set BOOST_BUILD_PATH=c:\boost_1_55_0\tools\build\v2
</pre>
<p>In a terminal window.</p>
<p>The last thing to do to complete the setup of BBv2 is to modify your
<tt class="docutils literal"><span class="pre">user-config.jam</span></tt> file. It is located in <tt class="docutils literal"><span class="pre">c:\boost_1_34_0\tools\build\v2</span></tt>.
<tt class="docutils literal"><span class="pre">user-config.jam</span></tt> file. It is located in <tt class="docutils literal"><span class="pre">c:\boost_1_55_0\tools\build\v2</span></tt>.
Depending on your platform and which compiler you're using, you should add a
line for each compiler and compiler version you have installed on your system
that you want to be able to use with BBv2. For example, if you're using
Microsoft Visual Studio 7.1 (2003), just add a line:</p>
Microsoft Visual Studio 12 (2013), just add a line:</p>
<pre class="literal-block">
using msvc : 7.1 ;
using msvc : 12.0 ;
</pre>
<p>If you use GCC, add the line:</p>
<pre class="literal-block">
@ -173,7 +173,7 @@ using darwin : 4.0 : g++-4.0 ;
<p>When building libtorrent, the <tt class="docutils literal">Jamfile</tt> expects the environment variable
<tt class="docutils literal">BOOST_ROOT</tt> to be set to the boost installation directory. It uses this to
find the boost libraries it depends on, so they can be built and their headers
files found. So, set this to <tt class="docutils literal"><span class="pre">c:\boost_1_34_0</span></tt>. You only need this if you're
files found. So, set this to <tt class="docutils literal"><span class="pre">c:\boost_1_55_0</span></tt>. You only need this if you're
building against a source distribution of boost.</p>
<p>Then the only thing left is simply to invoke <tt class="docutils literal">bjam</tt>. If you want to specify
a specific toolset to use (compiler) you can just add that to the commandline.
@ -239,8 +239,8 @@ from a cygwin terminal, you'll have to run it from a <tt class="docutils literal
cygwin, if you're building with gcc in cygwin you'll have to run it from a cygwin terminal.
Also, make sure the paths are correct in the different environments. In cygwin, the paths
(<tt class="docutils literal">BOOST_BUILD_PATH</tt> and <tt class="docutils literal">BOOST_ROOT</tt>) should be in the typical unix-format (e.g.
<tt class="docutils literal">/cygdrive/c/boost_1_34_0</tt>). In the windows environment, they should have the typical
windows format (<tt class="docutils literal"><span class="pre">c:/boost_1_34_0</span></tt>).</p>
<tt class="docutils literal">/cygdrive/c/boost_1_55_0</tt>). In the windows environment, they should have the typical
windows format (<tt class="docutils literal"><span class="pre">c:/boost_1_55_0</span></tt>).</p>
<div class="note">
<p class="first admonition-title">Note</p>
<p class="last">In Jamfiles, spaces are separators. It's typically easiest to avoid spaces
@ -468,7 +468,7 @@ awareness except on windows).</li>
<tr><td><tt class="docutils literal">asserts</tt></td>
<td><ul class="first last simple">
<li><tt class="docutils literal">off</tt> - disable all asserts</li>
<li><tt class="docutils literal">peoduction</tt> - enable asserts in release
<li><tt class="docutils literal">production</tt> - enable asserts in release
builds, but don't abort, just log them to
<tt class="docutils literal">extern char const* libtorrent_assert_log</tt>.</li>
<li><tt class="docutils literal">on</tt> - enable asserts in debug builds (this is
@ -507,6 +507,17 @@ parse_session_stats.py script (requires gnuplot)</li>
</ul>
</td>
</tr>
<tr><td><tt class="docutils literal"><span class="pre">profile-calls</span></tt></td>
<td><ul class="first last simple">
<li><tt class="docutils literal">off</tt> - default. No additional call profiling.</li>
<li><tt class="docutils literal">on</tt> - Enable logging of stack traces of
calls into libtorrent that are blocking. On
session shutdown, a file <tt class="docutils literal">blocking_calls.txt</tt>
is written with stack traces of blocking calls
ordered by the number of them.</li>
</ul>
</td>
</tr>
</tbody>
</table>
<p>The <tt class="docutils literal">variant</tt> feature is <em>implicit</em>, which means you don't need to specify

View File

@ -3,7 +3,7 @@ libtorrent manual
=================
:Author: Arvid Norberg, arvid@rasterbar.com
:Version: 1.0.0
:Version: 1.1.0
.. contents:: Table of contents
:depth: 2
@ -75,9 +75,9 @@ You'll find boost here__.
__ http://sourceforge.net/project/showfiles.php?group_id=7586&package_id=8041&release_id=619445
Extract the archive to some directory where you want it. For the sake of this
guide, let's assume you extract the package to ``c:\boost_1_34_0`` (I'm using
guide, let's assume you extract the package to ``c:\boost_1_55_0`` (I'm using
a windows path in this example since if you're on linux/unix you're more likely
to use the autotools). You'll need at least version 1.34 of the boost library
to use the autotools). You'll need at least version 1.49 of the boost library
in order to build libtorrent.
@ -86,7 +86,7 @@ Step 2: Setup BBv2
First you need to build ``bjam``. You do this by opening a terminal (In
windows, run ``cmd``). Change directory to
``c:\boost_1_34_0\tools\jam\src``. Then run the script called
``c:\boost_1_55_0\tools\jam\src``. Then run the script called
``build.bat`` or ``build.sh`` on a unix system. This will build ``bjam`` and
place it in a directory starting with ``bin.`` and then have the name of your
platform. Copy the ``bjam.exe`` (or ``bjam`` on a unix system) to a place
@ -101,22 +101,22 @@ set the environment variable ``BOOST_BUILD_PATH``. This is the path that tells
``bjam`` where it can find boost-build, your configuration file and all the
toolsets (descriptions used by boost-build to know how to use different
compilers on different platforms). Assuming the boost install path above, set
it to ``c:\boost_1_34_0\tools\build\v2``.
it to ``c:\boost_1_55_0\tools\build\v2``.
To set an environment variable in windows, type for example::
set BOOST_BUILD_PATH=c:\boost_1_34_0\tools\build\v2
set BOOST_BUILD_PATH=c:\boost_1_55_0\tools\build\v2
In a terminal window.
The last thing to do to complete the setup of BBv2 is to modify your
``user-config.jam`` file. It is located in ``c:\boost_1_34_0\tools\build\v2``.
``user-config.jam`` file. It is located in ``c:\boost_1_55_0\tools\build\v2``.
Depending on your platform and which compiler you're using, you should add a
line for each compiler and compiler version you have installed on your system
that you want to be able to use with BBv2. For example, if you're using
Microsoft Visual Studio 7.1 (2003), just add a line::
Microsoft Visual Studio 12 (2013), just add a line::
using msvc : 7.1 ;
using msvc : 12.0 ;
If you use GCC, add the line::
@ -148,7 +148,7 @@ Step 3: Building libtorrent
When building libtorrent, the ``Jamfile`` expects the environment variable
``BOOST_ROOT`` to be set to the boost installation directory. It uses this to
find the boost libraries it depends on, so they can be built and their headers
files found. So, set this to ``c:\boost_1_34_0``. You only need this if you're
files found. So, set this to ``c:\boost_1_55_0``. You only need this if you're
building against a source distribution of boost.
Then the only thing left is simply to invoke ``bjam``. If you want to specify
@ -220,8 +220,8 @@ from a cygwin terminal, you'll have to run it from a ``cmd`` terminal. The same
cygwin, if you're building with gcc in cygwin you'll have to run it from a cygwin terminal.
Also, make sure the paths are correct in the different environments. In cygwin, the paths
(``BOOST_BUILD_PATH`` and ``BOOST_ROOT``) should be in the typical unix-format (e.g.
``/cygdrive/c/boost_1_34_0``). In the windows environment, they should have the typical
windows format (``c:/boost_1_34_0``).
``/cygdrive/c/boost_1_55_0``). In the windows environment, they should have the typical
windows format (``c:/boost_1_55_0``).
.. note::
In Jamfiles, spaces are separators. It's typically easiest to avoid spaces
@ -367,7 +367,7 @@ Build features:
| | awareness except on windows). |
+--------------------------+----------------------------------------------------+
| ``asserts`` | * ``off`` - disable all asserts |
| | * ``peoduction`` - enable asserts in release |
| | * ``production`` - enable asserts in release |
| | builds, but don't abort, just log them to |
| | ``extern char const* libtorrent_assert_log``. |
| | * ``on`` - enable asserts in debug builds (this is |
@ -392,6 +392,13 @@ Build features:
| | is rotated every hour. It can be parsed by the |
| | parse_session_stats.py script (requires gnuplot) |
+--------------------------+----------------------------------------------------+
| ``profile-calls`` | * ``off`` - default. No additional call profiling. |
| | * ``on`` - Enable logging of stack traces of |
| | calls into libtorrent that are blocking. On |
| | session shutdown, a file ``blocking_calls.txt`` |
| | is written with stack traces of blocking calls |
| | ordered by the number of them. |
+--------------------------+----------------------------------------------------+
.. _MaxMind: http://www.maxmind.com/app/api

View File

@ -49,7 +49,7 @@
<tr><th class="docinfo-name">Author:</th>
<td>Arvid Norberg, <a class="last reference external" href="mailto:arvid&#64;rasterbar.com">arvid&#64;rasterbar.com</a></td></tr>
<tr><th class="docinfo-name">Version:</th>
<td>1.0.0</td></tr>
<td>1.1.0</td></tr>
</tbody>
</table>
<div class="contents topic" id="table-of-contents">

View File

@ -3,7 +3,7 @@ libtorrent manual
=================
:Author: Arvid Norberg, arvid@rasterbar.com
:Version: 1.0.0
:Version: 1.1.0
.. contents:: Table of contents
:depth: 2

View File

@ -49,7 +49,7 @@
<tr><th class="docinfo-name">Author:</th>
<td>Arvid Norberg, <a class="last reference external" href="mailto:arvid&#64;rasterbar.com">arvid&#64;rasterbar.com</a></td></tr>
<tr><th class="docinfo-name">Version:</th>
<td>1.0.0</td></tr>
<td>1.1.0</td></tr>
</tbody>
</table>
<div class="contents topic" id="table-of-contents">

View File

@ -3,7 +3,7 @@ BitTorrent extension for DHT RSS feeds
======================================
:Author: Arvid Norberg, arvid@rasterbar.com
:Version: 1.0.0
:Version: 1.1.0
.. contents:: Table of contents
:depth: 2

View File

@ -49,7 +49,7 @@
<tr><th class="docinfo-name">Author:</th>
<td>Arvid Norberg, <a class="last reference external" href="mailto:arvid&#64;rasterbar.com">arvid&#64;rasterbar.com</a></td></tr>
<tr><th class="docinfo-name">Version:</th>
<td>1.0.0</td></tr>
<td>1.1.0</td></tr>
</tbody>
</table>
<div class="contents topic" id="table-of-contents">

View File

@ -3,7 +3,7 @@ BitTorrent DHT security extension
=================================
:Author: Arvid Norberg, arvid@rasterbar.com
:Version: 1.0.0
:Version: 1.1.0
.. contents:: Table of contents
:depth: 2

View File

@ -49,7 +49,7 @@
<tr><th class="docinfo-name">Author:</th>
<td>Arvid Norberg, <a class="last reference external" href="mailto:arvid&#64;rasterbar.com">arvid&#64;rasterbar.com</a></td></tr>
<tr><th class="docinfo-name">Version:</th>
<td>1.0.0</td></tr>
<td>1.1.0</td></tr>
</tbody>
</table>
<div class="contents topic" id="table-of-contents">

View File

@ -3,7 +3,7 @@ BitTorrent extension for arbitrary DHT store
============================================
:Author: Arvid Norberg, arvid@rasterbar.com
:Version: 1.0.0
:Version: 1.1.0
.. contents:: Table of contents
:depth: 2

View File

@ -178,40 +178,40 @@ int main(int argc, char* argv[])
int main(int argc, char* argv[])
{
using namespace libtorrent;
#if BOOST_VERSION &lt; 103400
namespace fs = boost::filesystem;
fs::path::default_name_check(fs::no_check);
#endif
if (argc != 2)
{
std::cerr &lt;&lt; &quot;usage: ./simple_client torrent-file\n&quot;
&quot;to stop the client, press return.\n&quot;;
fputs(&quot;usage: ./simple_client torrent-file\n&quot;
&quot;to stop the client, press return.\n&quot;, stderr);
return 1;
}
#ifndef BOOST_NO_EXCEPTIONS
try
#endif
{
session s;
s.listen_on(std::make_pair(6881, 6889));
error_code ec;
s.listen_on(std::make_pair(6881, 6889), ec);
if (ec)
{
fprintf(stderr, &quot;failed to open listen socket: %s\n&quot;, ec.message().c_str());
return 1;
}
add_torrent_params p;
p.save_path = &quot;./&quot;;
p.ti = new torrent_info(argv[1]);
s.add_torrent(p);
p.ti = boost::make_shared&lt;torrent_info&gt;(argv[1], ec);
if (ec)
{
fprintf(stderr, &quot;%s\n&quot;, ec.message().c_str());
return 1;
}
s.add_torrent(p, ec);
if (ec)
{
fprintf(stderr, &quot;%s\n&quot;, ec.message().c_str());
return 1;
}
// wait for the user to end
char a;
std::cin.unsetf(std::ios_base::skipws);
std::cin &gt;&gt; a;
}
#ifndef BOOST_NO_EXCEPTIONS
catch (std::exception&amp; e)
{
std::cout &lt;&lt; e.what() &lt;&lt; &quot;\n&quot;;
}
#endif
scanf(&quot;%c\n&quot;, &amp;a);
return 0;
}
</pre>

View File

@ -130,40 +130,40 @@ This is a simple client. It doesn't have much output to keep it simple::
int main(int argc, char* argv[])
{
using namespace libtorrent;
#if BOOST_VERSION < 103400
namespace fs = boost::filesystem;
fs::path::default_name_check(fs::no_check);
#endif
if (argc != 2)
{
std::cerr << "usage: ./simple_client torrent-file\n"
"to stop the client, press return.\n";
fputs("usage: ./simple_client torrent-file\n"
"to stop the client, press return.\n", stderr);
return 1;
}
#ifndef BOOST_NO_EXCEPTIONS
try
#endif
{
session s;
s.listen_on(std::make_pair(6881, 6889));
error_code ec;
s.listen_on(std::make_pair(6881, 6889), ec);
if (ec)
{
fprintf(stderr, "failed to open listen socket: %s\n", ec.message().c_str());
return 1;
}
add_torrent_params p;
p.save_path = "./";
p.ti = new torrent_info(argv[1]);
s.add_torrent(p);
p.ti = boost::make_shared<torrent_info>(argv[1], ec);
if (ec)
{
fprintf(stderr, "%s\n", ec.message().c_str());
return 1;
}
s.add_torrent(p, ec);
if (ec)
{
fprintf(stderr, "%s\n", ec.message().c_str());
return 1;
}
// wait for the user to end
char a;
std::cin.unsetf(std::ios_base::skipws);
std::cin >> a;
}
#ifndef BOOST_NO_EXCEPTIONS
catch (std::exception& e)
{
std::cout << e.what() << "\n";
}
#endif
scanf("%c\n", &a);
return 0;
}

View File

@ -49,7 +49,7 @@
<tr><th class="docinfo-name">Author:</th>
<td>Arvid Norberg, <a class="last reference external" href="mailto:arvid&#64;rasterbar.com">arvid&#64;rasterbar.com</a></td></tr>
<tr><th class="docinfo-name">Version:</th>
<td>1.0.0</td></tr>
<td>1.1.0</td></tr>
</tbody>
</table>
<div class="contents topic" id="table-of-contents">
@ -122,6 +122,10 @@ ratio rather than downloading the torrent.</li>
<ul class="simple">
<li>uses a separate disk I/O thread to not have the disk ever block on network or
client interaction. (see <a class="reference external" href="manualref.html#threads">threads</a>).</li>
<li>uses asynchronous disk I/O when available (overlapped I/O, kaio, and posix-aio)
to make optimal use of disk bandwidth capacity</li>
<li>supports verifying the SHA-1 hash of pieces in multiple threads, to take full
advantage of multi core machines.</li>
<li>supports files &gt; 2 gigabytes.</li>
<li>fast resume support, a way to get rid of the costly piece check at the
start of a resumed torrent. Saves the storage state, piece_picker state

View File

@ -3,7 +3,7 @@ libtorrent manual
=================
:Author: Arvid Norberg, arvid@rasterbar.com
:Version: 1.0.0
:Version: 1.1.0
.. contents:: Table of contents
:depth: 2
@ -61,6 +61,10 @@ disk management
* uses a separate disk I/O thread to not have the disk ever block on network or
client interaction. (see threads_).
* uses asynchronous disk I/O when available (overlapped I/O, kaio, and posix-aio)
to make optimal use of disk bandwidth capacity
* supports verifying the SHA-1 hash of pieces in multiple threads, to take full
advantage of multi core machines.
* supports files > 2 gigabytes.
* fast resume support, a way to get rid of the costly piece check at the
start of a resumed torrent. Saves the storage state, piece_picker state

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View File

@ -31,6 +31,7 @@ symbols = {}
preprocess_rst = \
{
'manual.rst':'manual-ref.rst',
'settings.rst':'settings-ref.rst'
}
# some pre-defined sections from the main manual
@ -45,6 +46,9 @@ symbols = \
"metadata-from-peers_": "manual-ref.html#metadata-from-peers",
"magnet-links_": "manual-ref.html#magnet-links",
"ssl-torrents_": "manual-ref.html#ssl-torrents",
"dynamic-loading-of-torrent-files_": "manual-ref.html#dynamic-loading-of-torrent-files",
"session-statistics_": "manual-ref.html#session-statistics",
"peer-classes_": "manual-ref.html#peer-classes"
}
static_links = \
@ -95,6 +99,7 @@ category_mapping = {
'thread.hpp': 'Utility',
'ip_filter.hpp': 'Filter',
'session_settings.hpp': 'Settings',
'settings_pack.hpp': 'Settings',
}
category_fun_mapping = {
@ -747,7 +752,19 @@ def linkify_symbols(string):
lines = string.split('\n')
ret = []
in_literal = False
lno = 0
for l in lines:
lno += 1
# don't touch headlines, i.e. lines whose
# next line entirely contains one of =, - or .
if (lno < len(lines)-1): next_line = lines[lno]
else: next_line = ''
if len(next_line) > 0 and lines[lno].replace('=',''). \
replace('-','').replace('.', '') == '':
ret.append(l)
continue
if l.startswith('|'):
ret.append(l)
continue
@ -812,7 +829,7 @@ def print_link(name, target):
def dump_link_targets():
global link_targets
ret = ''
ret = '\n'
for l in link_targets:
ret += '__ %s\n' % l
link_targets = []

95
docs/gen_settings_doc.py Normal file
View File

@ -0,0 +1,95 @@
f = open('../include/libtorrent/settings_pack.hpp')
out = open('settings.rst', 'w+')
def print_field(str, width):
return '%s%s' % (str, ' ' * (width - len(str)))
def render_section(names, description, type, default_values):
max_name_len = max(len(max(names, key=len)), len('name'))
max_type_len = max(len(type), len('type'))
max_val_len = max(len(max(default_values, key=len)), len('default'))
# add link targets for the rest of the manual to reference
for n in names:
print >>out, '.. _%s:\n' % n
if len(names) > 0:
print >>out, '.. raw:: html\n'
for n in names:
print >>out, '\t<a name="%s"></a>' % n
print >>out, ''
separator = '+-' + ('-' * max_name_len) + '-+-' + ('-' * max_type_len) + '-+-' + ('-' * max_val_len) + '-+'
# build a table for the settings, their type and default value
print >>out, separator
print >>out, '| %s | %s | %s |' % (print_field('name', max_name_len), print_field('type', max_type_len), print_field('default', max_val_len))
print >>out, separator.replace('-', '=')
for i in range(len(names)):
print >>out, '| %s | %s | %s |' % (print_field(names[i], max_name_len), print_field(type, max_type_len), print_field(default_values[i], max_val_len))
print >>out, separator
print >>out
print >>out, description
mode = ''
# parse out default values for settings
f2 = open('../src/settings_pack.cpp')
def_map = {}
for l in f2:
l = l.strip()
if not l.startswith('SET(') \
and not l.startswith('SET_NOPREV(') \
and not l.startswith('DEPRECATED_SET('): continue
l = l.split('(')[1].split(',')
def_map[l[0]] = l[1].strip()
print '%s = %s' % (l[0], l[1].strip())
description = ''
names = []
for l in f:
if 'enum string_types' in l: mode = 'string'
if 'enum bool_types' in l: mode = 'bool'
if 'enum int_types' in l: mode = 'int'
if '#ifndef TORRENT_NO_DEPRECATE' in l: mode += 'skip'
if '#endif' in l: mode = mode[0:-4]
if mode == '': continue
if mode[-4:] == 'skip': continue
l = l.lstrip()
if l == '' and len(names) > 0:
if description == '':
for n in names:
print 'WARNING: no description for "%s"' % n
else:
default_values = []
for n in names:
default_values.append(def_map[n])
render_section(names, description, mode, default_values)
description = ''
names = []
if l.startswith('};'):
mode = ''
continue
if l.startswith('// '):
description += l[3:]
continue
l = l.strip()
if l.endswith(','):
l = l[:-1] # strip trailing comma
if '=' in l: l = l.split('=')[0].strip()
if l.endswith('_internal'): continue
names.append(l)
out.close()
f.close()

View File

@ -3,12 +3,12 @@ import os
paths = ['src/*.cpp', 'src/kademlia/*.cpp', 'include/libtorrent/*.hpp', 'include/libtorrent/kademlia/*.hpp', 'include/libtorrent/aux_/*.hpp', 'include/libtorrent/extensions/*.hpp']
os.system('(cd .. ; ctags %s 2>/dev/null)' % ' '.join(paths))
os.system('ctags %s 2>/dev/null' % ' '.join(paths))
files = []
for p in paths:
files.extend(glob.glob(os.path.join('..', p)))
files.extend(glob.glob(p))
items = []
@ -48,7 +48,7 @@ for f in files:
line = line[1:].strip()
items[-1]['todo'] = line
prio = items[-1]['priority']
if prio >= 0 and prio <= 3: priority_count[prio] += 1
if prio >= 0 and prio <= 4: priority_count[prio] += 1
continue
if state == '':
@ -112,14 +112,15 @@ out.write('''<html><head>
</head><body>
<h1>libtorrent todo-list</h1>
<span style="color: #f00">%d urgent</span>
<span style="color: #f77">%d important</span>
<span style="color: #3c3">%d relevant</span>
<span style="color: #77f">%d feasible</span>
<span style="color: #999">%d notes</span>
<table width="100%%" border="1" style="border-collapse: collapse;">''' % \
(priority_count[3], priority_count[2], priority_count[1], priority_count[0]))
(priority_count[4], priority_count[3], priority_count[2], priority_count[1], priority_count[0]))
prio_colors = [ '#ccc', '#ccf', '#cfc', '#fcc', '#fdd']
prio_colors = [ '#ccc', '#ccf', '#cfc', '#fcc', '#f44']
index = 0
for i in items:

View File

@ -1,210 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.11: http://docutils.sourceforge.net/" />
<title>libtorrent hacking</title>
<meta name="author" content="Arvid Norberg, arvid&#64;rasterbar.com" />
<link rel="stylesheet" type="text/css" href="../../css/base.css" />
<link rel="stylesheet" type="text/css" href="../../css/rst.css" />
<script type="text/javascript">
/* <![CDATA[ */
(function() {
var s = document.createElement('script'), t = document.getElementsByTagName('script')[0];
s.type = 'text/javascript';
s.async = true;
s.src = 'http://api.flattr.com/js/0.6/load.js?mode=auto';
t.parentNode.insertBefore(s, t);
})();
/* ]]> */
</script>
<link rel="stylesheet" href="style.css" type="text/css" />
<style type="text/css">
/* Hides from IE-mac \*/
* html pre { height: 1%; }
/* End hide from IE-mac */
</style>
</head>
<body>
<div class="document" id="libtorrent-hacking">
<div id="container">
<div id="headerNav">
<ul>
<li class="first"><a href="/">Home</a></li>
<li><a href="../../products.html">Products</a></li>
<li><a href="../../contact.html">Contact</a></li>
</ul>
</div>
<div id="header">
<div id="orange"></div>
<div id="logo"></div>
</div>
<div id="main">
<h1 class="title">libtorrent hacking</h1>
<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<tr><th class="docinfo-name">Author:</th>
<td>Arvid Norberg, <a class="last reference external" href="mailto:arvid&#64;rasterbar.com">arvid&#64;rasterbar.com</a></td></tr>
<tr><th class="docinfo-name">Version:</th>
<td>1.0.0</td></tr>
</tbody>
</table>
<div class="contents topic" id="table-of-contents">
<p class="topic-title first">Table of contents</p>
<ul class="simple">
<li><a class="reference internal" href="#terminology" id="id1">terminology</a></li>
<li><a class="reference internal" href="#structure" id="id2">structure</a><ul>
<li><a class="reference internal" href="#session-impl" id="id3">session_impl</a></li>
<li><a class="reference internal" href="#session" id="id4">session</a></li>
<li><a class="reference internal" href="#torrent-handle" id="id5">torrent_handle</a></li>
<li><a class="reference internal" href="#torrent" id="id6">torrent</a></li>
<li><a class="reference internal" href="#peer-connection" id="id7">peer_connection</a></li>
<li><a class="reference internal" href="#policy" id="id8">policy</a></li>
<li><a class="reference internal" href="#piece-picker" id="id9">piece_picker</a></li>
<li><a class="reference internal" href="#torrent-info" id="id10">torrent_info</a></li>
</ul>
</li>
<li><a class="reference internal" href="#threads" id="id11">threads</a></li>
</ul>
</div>
<p>This describe some of the internals of libtorrent. If you're looking for
something to contribute, please take a look at the <a class="reference external" href="todo.html">todo list</a>.</p>
<div class="section" id="terminology">
<h1>terminology</h1>
<p>This section describes some of the terminology used throughout the
libtorrent source. Having a good understanding of some of these keywords
helps understanding what's going on.</p>
<p>A <em>piece</em> is a part of the data of a torrent that has a SHA-1 hash in
the .torrent file. Pieces are almost always a power of two in size, but not
necessarily. Each piece is plit up in <em>blocks</em>, which is a 16 kiB. A block
never spans two pieces. If a piece is smaller than 16 kiB or not divisible
by 16 kiB, there are blocks smaller than that.</p>
<p>16 kiB is a de-facto standard of the largest transfer unit in the bittorrent
protocol. Clients typically reject any request for larger pieces than this.</p>
<p>The <em>piece picker</em> is the part of a bittorrent client that is responsible for
the logic to determine which requests to send to peers. It doesn't actually
pick full pieces, but blocks (from pieces).</p>
<p>The file layout of a torrent is represented by <em>file storage</em> objects. This
class contains a list of all files in the torrent (in a well defined order),
the size of the pieces and implicitly the total size of the whole torrent and
number of pieces. The file storage determines the mapping from <em>pieces</em>
to <em>files</em>. This representation may be quite complex in order to keep it extremely
compact. This is useful to load very large torrents without exploding in memory
usage.</p>
<p>A <em>torrent</em> object represents all the state of swarm download. This includes
a piece picker, a list of peer connections, file storage (torrent file). One
important distiction is between a connected peer (<em>peer_connection</em>) and a peer
we just know about, and may have been connected to, and may connect to in the
future (<em>policy::peer</em>). The list of (not connected) peers may grow very large
if not limited (through tracker responses, DHT and peer exchange). This list
is typically limited to a few thousand peers.</p>
<p>The <em>policy</em> in libtorrent is somewhat poorly named. It was initially intended
to be a customization point where a client could define peer selection behavior
and unchoke logic. It didn't end up being though, and a more accurate name would
be peer_list. It really just maintains a potentially large list of known peers
for a swarm (not necessarily connected).</p>
</div>
<div class="section" id="structure">
<h1>structure</h1>
<p>This is the high level structure of libtorrent. Bold types are part of the public
interface:</p>
<pre class="literal-block">
+=========+ pimpl +-------------------+
| <strong>session</strong> | ---------&gt; | aux::session_impl |
+=========+ +-------------------+
m_torrents[] | |
+================+ | |
| <strong>torrent_handle</strong> | ------+ | |
+================+ | | |
| | | m_connections[]
| | |
| | +---------------------+
m_picker v v |
+--------------+ +---------+---------+-- . . |
| piece_picker | &lt;--+-| torrent | torrent | to |
+--------------+ | +---------+---------+-- . . |
m_torrent_file | | m_connections[] |
+==============+ | | |
| <strong>torrent_info</strong> | &lt;--+ v v
+==============+ | +-----------------+-----------------+-- . .
m_policy | | peer_connection | peer_connection | pe
+--------+ | +-----------------+-----------------+-- . .
| policy | &lt;--------+ | | m_socket
+--------+ | |
| m_peers[] | v
| | +-----------------------+
| | | socket_type (variant) |
v | +-----------------------+
+--------------+ |
| policy::peer | |
+--------------+ |
| policy::peer | |
+--------------+ m_peer_info|
| policy::peer | &lt;----------+
+--------------+
. .
+ - - - - - - -+
</pre>
<div class="section" id="session-impl">
<h2>session_impl</h2>
<p>This is the session state object, containing all session global information, such as:</p>
<blockquote>
<ul class="simple">
<li>the list of all torrents <tt class="docutils literal">m_torrent</tt>.</li>
<li>the list of all peer connections <tt class="docutils literal">m_connections</tt>.</li>
<li>the global rate limits <tt class="docutils literal">m_settings</tt>.</li>
<li>the DHT state <tt class="docutils literal">m_dht</tt>.</li>
<li>the port mapping state, <tt class="docutils literal">m_upnp</tt> and <tt class="docutils literal">m_natpmp</tt>.</li>
</ul>
</blockquote>
</div>
<div class="section" id="session">
<h2>session</h2>
<p>This is the public interface to the session. It implements pimpl (pointer to implementation)
in order to hide the internal representation of the <tt class="docutils literal">session_impl</tt> object from the user and
make binary compatibility simpler to maintain.</p>
</div>
<div class="section" id="torrent-handle">
<h2>torrent_handle</h2>
<p>This is the public interface to a <tt class="docutils literal">torrent</tt>. It holds a weak reference to the internal
<tt class="docutils literal">torrent</tt> object and manipulates it by sending messages to the network thread.</p>
</div>
<div class="section" id="torrent">
<h2>torrent</h2>
</div>
<div class="section" id="peer-connection">
<h2>peer_connection</h2>
</div>
<div class="section" id="policy">
<h2>policy</h2>
</div>
<div class="section" id="piece-picker">
<h2>piece_picker</h2>
</div>
<div class="section" id="torrent-info">
<h2>torrent_info</h2>
</div>
</div>
<div class="section" id="threads">
<h1>threads</h1>
<p>libtorrent starts 2 or 3 threads.</p>
<blockquote>
<ul class="simple">
<li>The first thread is the main thread that will sit
idle in a <tt class="docutils literal">kqueue()</tt> or <tt class="docutils literal">epoll</tt> call most of the time.
This thread runs the main loop that will send and receive
data on all connections.</li>
<li>The second thread is the disk I/O thread. All disk read and write operations
are passed to this thread and messages are passed back to the main thread when
the operation completes. The disk thread also verifies the piece hashes.</li>
<li>The third and forth threads are spawned by asio on systems that don't support
non-blocking host name resolution to simulate non-blocking getaddrinfo().</li>
</ul>
</blockquote>
</div>
</div>
</body>
</html>

View File

@ -3,7 +3,7 @@ libtorrent hacking
==================
:Author: Arvid Norberg, arvid@rasterbar.com
:Version: 1.0.0
:Version: 1.1.0
.. contents:: Table of contents
:depth: 2
@ -142,19 +142,85 @@ torrent_info
threads
=======
libtorrent starts 2 or 3 threads.
libtorrent starts 3 to 5 threads.
* The first thread is the main thread that will sit
idle in a ``kqueue()`` or ``epoll`` call most of the time.
This thread runs the main loop that will send and receive
data on all connections.
idle in a ``select()`` call most of the time. This thread runs the main loop
that will send and receive data on all connections. In reality it's typically
not actually in ``select()``, but in ``kqueue()``, ``epoll_wait()`` or ``poll``,
depending on operating system.
* The second thread is the disk I/O thread. All disk read and write operations
are passed to this thread and messages are passed back to the main thread when
the operation completes. The disk thread also verifies the piece hashes.
the operation completes.
* The third and forth threads are spawned by asio on systems that don't support
non-blocking host name resolution to simulate non-blocking getaddrinfo().
* The third thread is the SHA-1 hash thread. By default there's only one hash thread,
but on multi-core machines downloading at very high rates, libtorrent can be configured
to start any number of hashing threads, to take full use of multi core systems.
(see ``session_settings::hashing_threads``).
* The fourth and fifth threads are spawned by asio on systems that don't support
asynchronous host name resolution, in order to simulate non-blocking ``getaddrinfo()``.
disk cache
==========
The disk cache implements *ARC*, Adaptive Replacement Cache. This consists of a number of LRUs:
1. lru L1 (recently used)
2. lru L1 ghost (recently evicted)
3. lru L2 (frequently used)
4. lru L2 ghost (recently evicted)
5. volatile read blocks
6. write cache (blocks waiting to be flushed to disk)
.. parsed-literal::
<--- recently used frequently used --->
+--------------+--------------+ +--------------+--------------+
| L1 **ghost** | L1 | | L2 | L2 **ghost** |
+--------------+--------------+ +--------------+--------------+
<---------- cache_size ---------->
<---------------------- 2 x cache_size ------------------------>
These LRUs are stored in ``block_cache`` in an array ``m_lru``.
The cache algorithm works like this::
if (L1->is_hit(piece)) {
L1->erase(piece);
L2->push_back(piece);
} else if (L2->is_hit(piece)) {
L2->erase(piece);
L2->push_back(page);
} else if (L1->size() == cache_size) {
L1->pop_front();
L1->push_back(piece);
} else {
if (L1->size() + L2->size() == 2*chache_size) {
L2->pop_front();
}
L1->push_back(piece);
}
It's a bit more complicated since within L1 and L2 in this pseudo code
have to separate the ghost entries and the in-cache entries.
Note that the most recently used and more frequently used pieces are at
the *back* of the lists. Iterating over a list gives you low priority pieces
first.
In libtorrent pieces are cached, not individual blocks, a single peer would
typically trigger many cache hits when downloading a piece. Since ARC is
sensitive to extra cache hits (a piece is moved to L2 the second time it's
hit) libtorrent only move the cache entry on cache hits when it's hit by
another peer than the last peer that hit it.
Another difference compared to the ARC paper is that libtorrent caches pieces,
which aren't necessarily fully allocated. This means the real cache size is
specified in number of blocks, not pieces, so there's not clear number of pieces
to keep in the ghost lists. There's an ``m_num_arc_pieces`` member in ``block_cache``
that defines the *arc cache size*, in pieces, rather than blocks.

View File

@ -52,6 +52,15 @@ epub: $(TARGETS:=.epub) $(FIGURES:=.png)
all: html
settings.rst: ../include/libtorrent/settings_pack.hpp
python gen_settings_doc.py
#stats_counters.rst: ../src/session_stats.cpp
# python gen_stats_doc.py
manual.rst: settings.rst stats_counters.rst
touch manual.rst
troubleshooting_thumb.png: troubleshooting.png
convert troubleshooting.png -resize 800x800 troubleshooting_thumb.png
@ -61,7 +70,7 @@ troubleshooting.png: troubleshooting.dot
todo.html:gen_todo.py ../src/*.cpp ../include/libtorrent/*.hpp
python gen_todo.py
$(REFERENCE_TARGETS:=.rst):gen_reference_doc.py ../include/libtorrent/*.hpp ../include/libtorrent/kademlia/*.hpp manual.rst
$(REFERENCE_TARGETS:=.rst):gen_reference_doc.py ../include/libtorrent/*.hpp ../include/libtorrent/kademlia/*.hpp manual.rst settings.rst
python gen_reference_doc.py
%.epub:%.rst
@ -83,5 +92,5 @@ $(REFERENCE_TARGETS:=.rst):gen_reference_doc.py ../include/libtorrent/*.hpp ../i
cp $@ $(WEB_PATH)/$@
clean:
rm -f $(TARGETS:=.html) $(TARGETS:=.pdf) todo.html reference*.html reference*.rst
rm -f $(TARGETS:=.html) $(TARGETS:=.pdf) settings.rst todo.html reference*.html reference*.rst

View File

@ -1,960 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.11: http://docutils.sourceforge.net/" />
<title>libtorrent API Documentation</title>
<meta name="author" content="Arvid Norberg, arvid&#64;rasterbar.com" />
<link rel="stylesheet" type="text/css" href="../../css/base.css" />
<link rel="stylesheet" type="text/css" href="../../css/rst.css" />
<script type="text/javascript">
/* <![CDATA[ */
(function() {
var s = document.createElement('script'), t = document.getElementsByTagName('script')[0];
s.type = 'text/javascript';
s.async = true;
s.src = 'http://api.flattr.com/js/0.6/load.js?mode=auto';
t.parentNode.insertBefore(s, t);
})();
/* ]]> */
</script>
<link rel="stylesheet" href="style.css" type="text/css" />
<style type="text/css">
/* Hides from IE-mac \*/
* html pre { height: 1%; }
/* End hide from IE-mac */
</style>
</head>
<body>
<div class="document" id="libtorrent-api-documentation">
<div id="container">
<div id="headerNav">
<ul>
<li class="first"><a href="/">Home</a></li>
<li><a href="../../products.html">Products</a></li>
<li><a href="../../contact.html">Contact</a></li>
</ul>
</div>
<div id="header">
<div id="orange"></div>
<div id="logo"></div>
</div>
<div id="main">
<h1 class="title">libtorrent API Documentation</h1>
<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<tr><th class="docinfo-name">Author:</th>
<td>Arvid Norberg, <a class="last reference external" href="mailto:arvid&#64;rasterbar.com">arvid&#64;rasterbar.com</a></td></tr>
<tr><th class="docinfo-name">Version:</th>
<td>1.0.0</td></tr>
</tbody>
</table>
<div class="contents topic" id="table-of-contents">
<p class="topic-title first">Table of contents</p>
<ul class="simple">
<li><a class="reference internal" href="#overview" id="id55">overview</a></li>
<li><a class="reference internal" href="#things-to-keep-in-mind" id="id56">things to keep in mind</a></li>
<li><a class="reference internal" href="#network-primitives" id="id57">network primitives</a></li>
<li><a class="reference internal" href="#exceptions" id="id58">exceptions</a></li>
<li><a class="reference internal" href="#magnet-links" id="id59">magnet links</a></li>
<li><a class="reference internal" href="#queuing" id="id60">queuing</a></li>
<li><a class="reference internal" href="#fast-resume" id="id61">fast resume</a></li>
<li><a class="reference internal" href="#storage-allocation" id="id62">storage allocation</a></li>
<li><a class="reference internal" href="#extensions" id="id63">extensions</a></li>
<li><a class="reference internal" href="#piece-picker" id="id64">piece picker</a></li>
<li><a class="reference internal" href="#ssl-torrents" id="id65">SSL torrents</a></li>
</ul>
</div>
<div class="section" id="overview">
<h1>overview</h1>
<p>The interface of libtorrent consists of a few classes. The main class is
the <tt class="docutils literal">session</tt>, it contains the main loop that serves all torrents.</p>
<p>The basic usage is as follows:</p>
<ul>
<li><p class="first">construct a <a class="reference external" href="reference-Session.html#session">session</a></p>
</li>
<li><p class="first">load <a class="reference external" href="reference-Session.html#session">session</a> state from settings file (see <a class="reference external" href="reference-Session.html#load_state()">load_state()</a>)</p>
</li>
<li><p class="first">start extensions (see <a class="reference external" href="reference-Core.html#add_extension()">add_extension()</a>).</p>
</li>
<li><p class="first">start DHT, LSD, UPnP, NAT-PMP etc (see <a class="reference external" href="reference-Session.html#start_dht()">start_dht()</a>, <a class="reference external" href="reference-Session.html#start_lsd()">start_lsd()</a>, <a class="reference external" href="reference-Session.html#start_upnp()">start_upnp()</a>
and <a class="reference external" href="reference-Session.html#start_natpmp()">start_natpmp()</a>).</p>
</li>
<li><p class="first">parse .torrent-files and add them to the <a class="reference external" href="reference-Session.html#session">session</a> (see <a class="reference external" href="reference-Core.html#torrent_info">torrent_info</a>,
<a class="reference external" href="reference-Session.html#async_add_torrent()">async_add_torrent()</a> and <a class="reference external" href="reference-Session.html#add_torrent()">add_torrent()</a>)</p>
</li>
<li><p class="first">main loop (see <a class="reference external" href="reference-Session.html#session">session</a>)</p>
<blockquote>
<ul class="simple">
<li>poll for alerts (see <a class="reference external" href="reference-Session.html#wait_for_alert()">wait_for_alert()</a>, <a class="reference external" href="reference-Session.html#pop_alerts()">pop_alerts()</a>)</li>
<li>handle updates to torrents, (see <a class="reference external" href="reference-Alerts.html#state_update_alert">state_update_alert</a>).</li>
<li>handle other alerts, (see <a class="reference external" href="reference-Alerts.html#alert">alert</a>).</li>
<li>query the <a class="reference external" href="reference-Session.html#session">session</a> for information (see <a class="reference external" href="reference-Session.html#status()">session::status()</a>).</li>
<li>add and remove torrents from the <a class="reference external" href="reference-Session.html#session">session</a> (<a class="reference external" href="reference-Session.html#remove_torrent()">remove_torrent()</a>)</li>
</ul>
</blockquote>
</li>
<li><p class="first">save resume data for all torrent_handles (optional, see
<a class="reference external" href="reference-Core.html#save_resume_data()">save_resume_data()</a>)</p>
</li>
<li><p class="first">save <a class="reference external" href="reference-Session.html#session">session</a> state (see <a class="reference external" href="reference-Session.html#save_state()">save_state()</a>)</p>
</li>
<li><p class="first">destruct <a class="reference external" href="reference-Session.html#session">session</a> object</p>
</li>
</ul>
<p>Each class and function is described in this manual.</p>
<p>For a description on how to create torrent files, see <a class="reference external" href="reference-Create_Torrents.html#create_torrent">create_torrent</a>.</p>
</div>
<div class="section" id="things-to-keep-in-mind">
<h1>things to keep in mind</h1>
<p>A common problem developers are facing is torrents stopping without explanation.
Here is a description on which conditions libtorrent will stop your torrents,
how to find out about it and what to do about it.</p>
<p>Make sure to keep track of the paused state, the error state and the upload
mode of your torrents. By default, torrents are auto-managed, which means
libtorrent will pause them, unpause them, scrape them and take them out
of upload-mode automatically.</p>
<p>Whenever a torrent encounters a fatal error, it will be stopped, and the
<tt class="docutils literal"><span class="pre">torrent_status::error</span></tt> will describe the error that caused it. If a torrent
is auto managed, it is scraped periodically and paused or resumed based on
the number of downloaders per seed. This will effectively seed torrents that
are in the greatest need of seeds.</p>
<p>If a torrent hits a disk write error, it will be put into upload mode. This
means it will not download anything, but only upload. The assumption is that
the write error is caused by a full disk or write permission errors. If the
torrent is auto-managed, it will periodically be taken out of the upload
mode, trying to write things to the disk again. This means torrent will recover
from certain disk errors if the problem is resolved. If the torrent is not
auto managed, you have to call <a class="reference external" href="reference-Core.html#set_upload_mode()">set_upload_mode()</a> to turn
downloading back on again.</p>
</div>
<div class="section" id="network-primitives">
<h1>network primitives</h1>
<p>There are a few typedefs in the <tt class="docutils literal">libtorrent</tt> namespace which pulls
in network types from the <tt class="docutils literal">asio</tt> namespace. These are:</p>
<pre class="literal-block">
typedef asio::ip::address address;
typedef asio::ip::address_v4 address_v4;
typedef asio::ip::address_v6 address_v6;
using asio::ip::tcp;
using asio::ip::udp;
</pre>
<p>These are declared in the <tt class="docutils literal">&lt;libtorrent/socket.hpp&gt;</tt> header.</p>
<p>The <tt class="docutils literal">using</tt> statements will give easy access to:</p>
<pre class="literal-block">
tcp::endpoint
udp::endpoint
</pre>
<p>Which are the endpoint types used in libtorrent. An endpoint is an address
with an associated port.</p>
<p>For documentation on these types, please refer to the <a class="reference external" href="http://asio.sourceforge.net/asio-0.3.8/doc/asio/reference.html">asio documentation</a>.</p>
</div>
<div class="section" id="exceptions">
<h1>exceptions</h1>
<p>Many functions in libtorrent have two versions, one that throws exceptions on
errors and one that takes an <tt class="docutils literal">error_code</tt> reference which is filled with the
error code on errors.</p>
<p>There is one exception class that is used for errors in libtorrent, it is based
on boost.system's <tt class="docutils literal">error_code</tt> class to carry the error code.</p>
<p>For more information, see <a class="reference external" href="reference-Error_Codes.html#libtorrent_exception">libtorrent_exception</a> and <a class="reference external" href="reference-Error_Codes.html#error_code_enum">error_code_enum</a>.</p>
<div class="section" id="translating-error-codes">
<h2>translating error codes</h2>
<p>The error_code::message() function will typically return a localized error string,
for system errors. That is, errors that belong to the generic or system category.</p>
<p>Errors that belong to the libtorrent error category are not localized however, they
are only available in english. In order to translate libtorrent errors, compare the
error category of the <tt class="docutils literal">error_code</tt> object against <tt class="docutils literal"><span class="pre">libtorrent::get_libtorrent_category()</span></tt>,
and if matches, you know the error code refers to the list above. You can provide
your own mapping from error code to string, which is localized. In this case, you
cannot rely on <tt class="docutils literal"><span class="pre">error_code::message()</span></tt> to generate your strings.</p>
<p>The numeric values of the errors are part of the API and will stay the same, although
new error codes may be appended at the end.</p>
<p>Here's a simple example of how to translate error codes:</p>
<pre class="literal-block">
std::string error_code_to_string(boost::system::error_code const&amp; ec)
{
if (ec.category() != libtorrent::get_libtorrent_category())
{
return ec.message();
}
// the error is a libtorrent error
int code = ec.value();
static const char const* swedish[] =
{
&quot;inget fel&quot;,
&quot;en fil i torrenten kolliderar med en fil fran en annan torrent&quot;,
&quot;hash check misslyckades&quot;,
&quot;torrentfilen ar inte en dictionary&quot;,
&quot;'info'-nyckeln saknas eller ar korrupt i torrentfilen&quot;,
&quot;'info'-faltet ar inte en dictionary&quot;,
&quot;'piece length' faltet saknas eller ar korrupt i torrentfilen&quot;,
&quot;torrentfilen saknar namnfaltet&quot;,
&quot;ogiltigt namn i torrentfilen (kan vara en attack)&quot;,
// ... more strings here
};
// use the default error string in case we don't have it
// in our translated list
if (code &lt; 0 || code &gt;= sizeof(swedish)/sizeof(swedish[0]))
return ec.message();
return swedish[code];
}
</pre>
</div>
</div>
<div class="section" id="magnet-links">
<h1>magnet links</h1>
<p>Magnet links are URIs that includes an info-hash, a display name and optionally
a tracker url. The idea behind magnet links is that an end user can click on a
link in a browser and have it handled by a bittorrent application, to start a
download, without any .torrent file.</p>
<p>The format of the magnet URI is:</p>
<p><strong>magnet:?xt=urn:btih:</strong> <em>Base16 encoded info-hash</em> [ <strong>&amp;dn=</strong> <em>name of download</em> ] [ <strong>&amp;tr=</strong> <em>tracker URL</em> ]*</p>
</div>
<div class="section" id="queuing">
<h1>queuing</h1>
<p>libtorrent supports <em>queuing</em>. Which means it makes sure that a limited number of
torrents are being downloaded at any given time, and once a torrent is completely
downloaded, the next in line is started.</p>
<p>Torrents that are <em>auto managed</em> are subject to the queuing and the active
torrents limits. To make a torrent auto managed, set <tt class="docutils literal">auto_managed</tt> to true
when adding the torrent (see <a class="reference external" href="reference-Session.html#async_add_torrent()">async_add_torrent()</a> and <a class="reference external" href="reference-Session.html#add_torrent()">add_torrent()</a>).</p>
<p>The limits of the number of downloading and seeding torrents are controlled via
<tt class="docutils literal">active_downloads</tt>, <tt class="docutils literal">active_seeds</tt> and <tt class="docutils literal">active_limit</tt> in
<a class="reference external" href="reference-Settings.html#session_settings">session_settings</a>. These limits takes non auto managed torrents into account as
well. If there are more non-auto managed torrents being downloaded than the
<tt class="docutils literal">active_downloads</tt> setting, any auto managed torrents will be queued until
torrents are removed so that the number drops below the limit.</p>
<p>The default values are 8 active downloads and 5 active seeds.</p>
<p>At a regular interval, torrents are checked if there needs to be any
re-ordering of which torrents are active and which are queued. This interval
can be controlled via <tt class="docutils literal">auto_manage_interval</tt> in <a class="reference external" href="reference-Settings.html#session_settings">session_settings</a>. It defaults
to every 30 seconds.</p>
<p>For queuing to work, resume data needs to be saved and restored for all
torrents. See <a class="reference external" href="reference-Core.html#save_resume_data()">save_resume_data()</a>.</p>
<div class="section" id="downloading">
<h2>downloading</h2>
<p>Torrents that are currently being downloaded or incomplete (with bytes still to
download) are queued. The torrents in the front of the queue are started to be
actively downloaded and the rest are ordered with regards to their queue
position. Any newly added torrent is placed at the end of the queue. Once a
torrent is removed or turns into a seed, its queue position is -1 and all
torrents that used to be after it in the queue, decreases their position in
order to fill the gap.</p>
<p>The queue positions are always in a sequence without any gaps.</p>
<p>Lower queue position means closer to the front of the queue, and will be
started sooner than torrents with higher queue positions.</p>
<p>To query a torrent for its position in the queue, or change its position, see:
<a class="reference external" href="reference-Core.html#queue_position()">queue_position()</a>, <a class="reference external" href="reference-Core.html#queue_position_up()">queue_position_up()</a>, <a class="reference external" href="reference-Core.html#queue_position_down()">queue_position_down()</a>,
<a class="reference external" href="reference-Core.html#queue_position_top()">queue_position_top()</a> and <a class="reference external" href="reference-Core.html#queue_position_bottom()">queue_position_bottom()</a>.</p>
</div>
<div class="section" id="seeding">
<h2>seeding</h2>
<p>Auto managed seeding torrents are rotated, so that all of them are allocated a
fair amount of seeding. Torrents with fewer completed <em>seed cycles</em> are
prioritized for seeding. A seed cycle is completed when a torrent meets either
the share ratio limit (uploaded bytes / downloaded bytes), the share time ratio
(time seeding / time downloaing) or seed time limit (time seeded).</p>
<p>The relevant settings to control these limits are <tt class="docutils literal">share_ratio_limit</tt>,
<tt class="docutils literal">seed_time_ratio_limit</tt> and <tt class="docutils literal">seed_time_limit</tt> in <a class="reference external" href="reference-Settings.html#session_settings">session_settings</a>.</p>
</div>
</div>
<div class="section" id="fast-resume">
<h1>fast resume</h1>
<p>The fast resume mechanism is a way to remember which pieces are downloaded
and where they are put between sessions. You can generate fast resume data by
calling <a class="reference external" href="reference-Core.html#save_resume_data()">save_resume_data()</a> on <a class="reference external" href="reference-Core.html#torrent_handle">torrent_handle</a>. You can
then save this data to disk and use it when resuming the torrent. libtorrent
will not check the piece hashes then, and rely on the information given in the
fast-resume data. The fast-resume data also contains information about which
blocks, in the unfinished pieces, were downloaded, so it will not have to
start from scratch on the partially downloaded pieces.</p>
<p>To use the fast-resume data you simply give it to <a class="reference external" href="reference-Session.html#async_add_torrent()">async_add_torrent()</a> and
<a class="reference external" href="reference-Session.html#add_torrent()">add_torrent()</a>, and it will skip the time consuming checks. It may have to do
the checking anyway, if the fast-resume data is corrupt or doesn't fit the
storage for that torrent, then it will not trust the fast-resume data and just
do the checking.</p>
<div class="section" id="file-format">
<h2>file format</h2>
<p>The file format is a bencoded dictionary containing the following fields:</p>
<table border="1" class="docutils">
<colgroup>
<col width="30%" />
<col width="70%" />
</colgroup>
<tbody valign="top">
<tr><td><tt class="docutils literal"><span class="pre">file-format</span></tt></td>
<td>string: &quot;libtorrent resume file&quot;</td>
</tr>
<tr><td><tt class="docutils literal"><span class="pre">file-version</span></tt></td>
<td>integer: 1</td>
</tr>
<tr><td><tt class="docutils literal"><span class="pre">info-hash</span></tt></td>
<td>string, the info hash of the torrent this data is saved for.</td>
</tr>
<tr><td><tt class="docutils literal">blocks per piece</tt></td>
<td>integer, the number of blocks per piece. Must be: piece_size
/ (16 * 1024). Clamped to be within the range [1, 256]. It
is the number of blocks per (normal sized) piece. Usually
each block is 16 * 1024 bytes in size. But if piece size is
greater than 4 megabytes, the block size will increase.</td>
</tr>
<tr><td><tt class="docutils literal">pieces</tt></td>
<td>A string with piece flags, one character per piece.
Bit 1 means we have that piece.
Bit 2 means we have verified that this piece is correct.
This only applies when the torrent is in seed_mode.</td>
</tr>
<tr><td><tt class="docutils literal">slots</tt></td>
<td><p class="first">list of integers. The list maps slots to piece indices. It
tells which piece is on which slot. If piece index is -2 it
means it is free, that there's no piece there. If it is -1,
means the slot isn't allocated on disk yet. The pieces have
to meet the following requirement:</p>
<p class="last">If there's a slot at the position of the piece index,
the piece must be located in that slot.</p>
</td>
</tr>
<tr><td><tt class="docutils literal">total_uploaded</tt></td>
<td>integer. The number of bytes that have been uploaded in
total for this torrent.</td>
</tr>
<tr><td><tt class="docutils literal">total_downloaded</tt></td>
<td>integer. The number of bytes that have been downloaded in
total for this torrent.</td>
</tr>
<tr><td><tt class="docutils literal">active_time</tt></td>
<td>integer. The number of seconds this torrent has been active.
i.e. not paused.</td>
</tr>
<tr><td><tt class="docutils literal">seeding_time</tt></td>
<td>integer. The number of seconds this torrent has been active
and seeding.</td>
</tr>
<tr><td><tt class="docutils literal">num_seeds</tt></td>
<td>integer. An estimate of the number of seeds on this torrent
when the resume data was saved. This is scrape data or based
on the peer list if scrape data is unavailable.</td>
</tr>
<tr><td><tt class="docutils literal">num_downloaders</tt></td>
<td>integer. An estimate of the number of downloaders on this
torrent when the resume data was last saved. This is used as
an initial estimate until we acquire up-to-date scrape info.</td>
</tr>
<tr><td><tt class="docutils literal">upload_rate_limit</tt></td>
<td>integer. In case this torrent has a per-torrent upload rate
limit, this is that limit. In bytes per second.</td>
</tr>
<tr><td><tt class="docutils literal">download_rate_limit</tt></td>
<td>integer. The download rate limit for this torrent in case
one is set, in bytes per second.</td>
</tr>
<tr><td><tt class="docutils literal">max_connections</tt></td>
<td>integer. The max number of peer connections this torrent
may have, if a limit is set.</td>
</tr>
<tr><td><tt class="docutils literal">max_uploads</tt></td>
<td>integer. The max number of unchoked peers this torrent may
have, if a limit is set.</td>
</tr>
<tr><td><tt class="docutils literal">seed_mode</tt></td>
<td>integer. 1 if the torrent is in seed mode, 0 otherwise.</td>
</tr>
<tr><td><tt class="docutils literal">file_priority</tt></td>
<td>list of integers. One entry per file in the torrent. Each
entry is the priority of the file with the same index.</td>
</tr>
<tr><td><tt class="docutils literal">piece_priority</tt></td>
<td>string of bytes. Each byte is interpreted as an integer and
is the priority of that piece.</td>
</tr>
<tr><td><tt class="docutils literal">auto_managed</tt></td>
<td>integer. 1 if the torrent is auto managed, otherwise 0.</td>
</tr>
<tr><td><tt class="docutils literal">sequential_download</tt></td>
<td>integer. 1 if the torrent is in sequential download mode,
0 otherwise.</td>
</tr>
<tr><td><tt class="docutils literal">paused</tt></td>
<td>integer. 1 if the torrent is paused, 0 otherwise.</td>
</tr>
<tr><td><tt class="docutils literal">trackers</tt></td>
<td>list of lists of strings. The top level list lists all
tracker tiers. Each second level list is one tier of
trackers.</td>
</tr>
<tr><td><tt class="docutils literal">mapped_files</tt></td>
<td>list of strings. If any file in the torrent has been
renamed, this entry contains a list of all the filenames.
In the same order as in the torrent file.</td>
</tr>
<tr><td><tt class="docutils literal"><span class="pre">url-list</span></tt></td>
<td>list of strings. List of url-seed URLs used by this torrent.
The urls are expected to be properly encoded and not contain
any illegal url characters.</td>
</tr>
<tr><td><tt class="docutils literal">httpseeds</tt></td>
<td>list of strings. List of httpseed URLs used by this torrent.
The urls are expected to be properly encoded and not contain
any illegal url characters.</td>
</tr>
<tr><td><tt class="docutils literal">merkle tree</tt></td>
<td>string. In case this torrent is a merkle torrent, this is a
string containing the entire merkle tree, all nodes,
including the root and all leaves. The tree is not
necessarily complete, but complete enough to be able to send
any piece that we have, indicated by the have bitmask.</td>
</tr>
<tr><td><tt class="docutils literal">save_path</tt></td>
<td>string. The save path where this torrent was saved. This is
especially useful when moving torrents with move_storage()
since this will be updated.</td>
</tr>
<tr><td><tt class="docutils literal">peers</tt></td>
<td><p class="first">list of dictionaries. Each dictionary has the following
layout:</p>
<table border="1" class="docutils">
<colgroup>
<col width="18%" />
<col width="82%" />
</colgroup>
<tbody valign="top">
<tr><td><tt class="docutils literal">ip</tt></td>
<td>string, the ip address of the peer. This is
not a binary representation of the ip
address, but the string representation. It
may be an IPv6 string or an IPv4 string.</td>
</tr>
<tr><td><tt class="docutils literal">port</tt></td>
<td>integer, the listen port of the peer</td>
</tr>
</tbody>
</table>
<p class="last">These are the local peers we were connected to when this
fast-resume data was saved.</p>
</td>
</tr>
<tr><td><tt class="docutils literal">unfinished</tt></td>
<td><p class="first">list of dictionaries. Each dictionary represents an
piece, and has the following layout:</p>
<table border="1" class="last docutils">
<colgroup>
<col width="23%" />
<col width="77%" />
</colgroup>
<tbody valign="top">
<tr><td><tt class="docutils literal">piece</tt></td>
<td>integer, the index of the piece this entry
refers to.</td>
</tr>
<tr><td><tt class="docutils literal">bitmask</tt></td>
<td>string, a binary bitmask representing the
blocks that have been downloaded in this
piece.</td>
</tr>
<tr><td><tt class="docutils literal">adler32</tt></td>
<td>The adler32 checksum of the data in the
blocks specified by <tt class="docutils literal">bitmask</tt>.</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr><td><tt class="docutils literal">file sizes</tt></td>
<td>list where each entry corresponds to a file in the file list
in the metadata. Each entry has a list of two values, the
first value is the size of the file in bytes, the second
is the time stamp when the last time someone wrote to it.
This information is used to compare with the files on disk.
All the files must match exactly this information in order
to consider the resume data as current. Otherwise a full
re-check is issued.</td>
</tr>
<tr><td><tt class="docutils literal">allocation</tt></td>
<td>The allocation mode for the storage. Can be either <tt class="docutils literal">full</tt>
or <tt class="docutils literal">compact</tt>. If this is full, the file sizes and
timestamps are disregarded. Pieces are assumed not to have
moved around even if the files have been modified after the
last resume data checkpoint.</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="section" id="storage-allocation">
<h1>storage allocation</h1>
<p>There are two modes in which storage (files on disk) are allocated in libtorrent.</p>
<ol class="arabic simple">
<li>The traditional <em>full allocation</em> mode, where the entire files are filled up
with zeros before anything is downloaded. Files are allocated on demand, the
first time anything is written to them. The main benefit of this mode is that
it avoids creating heavily fragmented files.</li>
<li>The <em>sparse allocation</em>, sparse files are used, and pieces are downloaded
directly to where they belong. This is the recommended (and default) mode.</li>
</ol>
<p>In previous versions of libtorrent, a 3rd mode was supported, <em>compact
allocation</em>. Support for this is deprecated and will be removed in future
versions of libtorrent. It's still described in here for completeness.</p>
<p>The allocation mode is selected when a torrent is started. It is passed as an
argument to <a class="reference external" href="reference-Session.html#add_torrent()">session::add_torrent()</a> or <a class="reference external" href="reference-Session.html#async_add_torrent()">session::async_add_torrent()</a>.</p>
<p>The decision to use full allocation or compact allocation typically depends on
whether any files have priority 0 and if the filesystem supports sparse files.</p>
<div class="section" id="sparse-allocation">
<h2>sparse allocation</h2>
<p>On filesystems that supports sparse files, this allocation mode will only use
as much space as has been downloaded.</p>
<p>The main drawback of this mode is that it may create heavily fragmented files.</p>
<blockquote>
<ul class="simple">
<li>It does not require an allocation pass on startup.</li>
</ul>
</blockquote>
</div>
<div class="section" id="full-allocation">
<h2>full allocation</h2>
<p>When a torrent is started in full allocation mode, the disk-io thread
will make sure that the entire storage is allocated, and fill any gaps with zeros.
It will of course still check for existing pieces and fast resume data. The main
drawbacks of this mode are:</p>
<blockquote>
<ul class="simple">
<li>It may take longer to start the torrent, since it will need to fill the files
with zeroes. This delay is linear to the size of the download.</li>
<li>The download may occupy unnecessary disk space between download sessions.</li>
<li>Disk caches usually perform poorly with random access to large files
and may slow down the download some.</li>
</ul>
</blockquote>
<p>The benefits of this mode are:</p>
<blockquote>
<ul class="simple">
<li>Downloaded pieces are written directly to their final place in the files and
the total number of disk operations will be fewer and may also play nicer to
filesystems' file allocation, and reduce fragmentation.</li>
<li>No risk of a download failing because of a full disk during download, once
all files have been created.</li>
</ul>
</blockquote>
</div>
<div class="section" id="compact-allocation">
<h2>compact allocation</h2>
<div class="note">
<p class="first admonition-title">Note</p>
<p class="last">Note that support for compact allocation is deprecated in libttorrent, and will
be removed in future versions.</p>
</div>
<p>The compact allocation will only allocate as much storage as it needs to keep
the pieces downloaded so far. This means that pieces will be moved around to be
placed at their final position in the files while downloading (to make sure the
completed download has all its pieces in the correct place). So, the main
drawbacks are:</p>
<blockquote>
<ul class="simple">
<li>More disk operations while downloading since pieces are moved around.</li>
<li>Potentially more fragmentation in the filesystem.</li>
<li>Cannot be used while having files with priority 0.</li>
</ul>
</blockquote>
<p>The benefits though, are:</p>
<blockquote>
<ul class="simple">
<li>No startup delay, since the files don't need allocating.</li>
<li>The download will not use unnecessary disk space.</li>
<li>Disk caches perform much better than in full allocation and raises the
download speed limit imposed by the disk.</li>
<li>Works well on filesystems that don't support sparse files.</li>
</ul>
</blockquote>
<p>The algorithm that is used when allocating pieces and slots isn't very
complicated. For the interested, a description follows.</p>
<p>storing a piece:</p>
<ol class="arabic simple">
<li>let <strong>A</strong> be a newly downloaded piece, with index <strong>n</strong>.</li>
<li>let <strong>s</strong> be the number of slots allocated in the file we're
downloading to. (the number of pieces it has room for).</li>
<li>if <strong>n</strong> &gt;= <strong>s</strong> then allocate a new slot and put the piece there.</li>
<li>if <strong>n</strong> &lt; <strong>s</strong> then allocate a new slot, move the data at
slot <strong>n</strong> to the new slot and put <strong>A</strong> in slot <strong>n</strong>.</li>
</ol>
<p>allocating a new slot:</p>
<ol class="arabic simple">
<li>if there's an unassigned slot (a slot that doesn't
contain any piece), return that slot index.</li>
<li>append the new slot at the end of the file (or find an unused slot).</li>
<li>let <strong>i</strong> be the index of newly allocated slot</li>
<li>if we have downloaded piece index <strong>i</strong> already (to slot <strong>j</strong>) then<ol class="arabic">
<li>move the data at slot <strong>j</strong> to slot <strong>i</strong>.</li>
<li>return slot index <strong>j</strong> as the newly allocated free slot.</li>
</ol>
</li>
<li>return <strong>i</strong> as the newly allocated slot.</li>
</ol>
</div>
</div>
<div class="section" id="extensions">
<h1>extensions</h1>
<p>These extensions all operates within the <a class="reference external" href="extension_protocol.html">extension protocol</a>. The name of the
extension is the name used in the extension-list packets, and the payload is
the data in the extended message (not counting the length-prefix, message-id
nor extension-id).</p>
<p>Note that since this protocol relies on one of the reserved bits in the
handshake, it may be incompatible with future versions of the mainline
bittorrent client.</p>
<p>These are the extensions that are currently implemented.</p>
<div class="section" id="metadata-from-peers">
<h2>metadata from peers</h2>
<p>Extension name: &quot;LT_metadata&quot;</p>
<p>This extension is deprecated in favor of the more widely supported
<tt class="docutils literal">ut_metadata</tt> extension, see <a class="reference external" href="http://bittorrent.org/beps/bep_0009.html">BEP 9</a>. The point with this extension is that
you don't have to distribute the metadata (.torrent-file) separately. The
metadata can be distributed through the bittorrent swarm. The only thing you
need to download such a torrent is the tracker url and the info-hash of the
torrent.</p>
<p>It works by assuming that the initial seeder has the metadata and that the
metadata will propagate through the network as more peers join.</p>
<p>There are three kinds of messages in the metadata extension. These packets are
put as payload to the extension message. The three packets are:</p>
<blockquote>
<ul class="simple">
<li>request metadata</li>
<li>metadata</li>
<li>don't have metadata</li>
</ul>
</blockquote>
<p>request metadata:</p>
<table border="1" class="docutils">
<colgroup>
<col width="17%" />
<col width="23%" />
<col width="61%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">size</th>
<th class="head">name</th>
<th class="head">description</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>uint8_t</td>
<td>msg_type</td>
<td>Determines the kind of message this is
0 means 'request metadata'</td>
</tr>
<tr><td>uint8_t</td>
<td>start</td>
<td>The start of the metadata block that
is requested. It is given in 256:ths
of the total size of the metadata,
since the requesting client don't know
the size of the metadata.</td>
</tr>
<tr><td>uint8_t</td>
<td>size</td>
<td>The size of the metadata block that is
requested. This is also given in
256:ths of the total size of the
metadata. The size is given as size-1.
That means that if this field is set
0, the request wants one 256:th of the
metadata.</td>
</tr>
</tbody>
</table>
<p>metadata:</p>
<table border="1" class="docutils">
<colgroup>
<col width="17%" />
<col width="23%" />
<col width="61%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">size</th>
<th class="head">name</th>
<th class="head">description</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>uint8_t</td>
<td>msg_type</td>
<td>1 means 'metadata'</td>
</tr>
<tr><td>int32_t</td>
<td>total_size</td>
<td>The total size of the metadata, given
in number of bytes.</td>
</tr>
<tr><td>int32_t</td>
<td>offset</td>
<td>The offset of where the metadata block
in this message belongs in the final
metadata. This is given in bytes.</td>
</tr>
<tr><td>uint8_t[]</td>
<td>metadata</td>
<td>The actual metadata block. The size of
this part is given implicit by the
length prefix in the bittorrent
protocol packet.</td>
</tr>
</tbody>
</table>
<p>Don't have metadata:</p>
<table border="1" class="docutils">
<colgroup>
<col width="17%" />
<col width="23%" />
<col width="61%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">size</th>
<th class="head">name</th>
<th class="head">description</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>uint8_t</td>
<td>msg_type</td>
<td>2 means 'I don't have metadata'.
This message is sent as a reply to a
metadata request if the the client
doesn't have any metadata.</td>
</tr>
</tbody>
</table>
</div>
<div class="section" id="dont-have">
<h2>dont_have</h2>
<p>Extension name: &quot;lt_dont_have&quot;</p>
<p>The <tt class="docutils literal">dont_have</tt> extension message is used to tell peers that the client no
longer has a specific piece. The extension message should be advertised in the
<tt class="docutils literal">m</tt> dictionary as <tt class="docutils literal">lt_dont_have</tt>. The message format mimics the regular
<tt class="docutils literal">HAVE</tt> bittorrent message.</p>
<p>Just like all extension messages, the first 2 bytes in the mssage itself are 20
(the bittorrent extension message) and the message ID assigned to this
extension in the <tt class="docutils literal">m</tt> dictionary in the handshake.</p>
<table border="1" class="docutils">
<colgroup>
<col width="17%" />
<col width="23%" />
<col width="61%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">size</th>
<th class="head">name</th>
<th class="head">description</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>uint32_t</td>
<td>piece</td>
<td>index of the piece the peer no longer
has.</td>
</tr>
</tbody>
</table>
<p>The length of this message (including the extension message prefix) is 6 bytes,
i.e. one byte longer than the normal <tt class="docutils literal">HAVE</tt> message, because of the extension
message wrapping.</p>
</div>
<div class="section" id="http-seeding">
<h2>HTTP seeding</h2>
<p>There are two kinds of HTTP seeding. One with that assumes a smart (and polite)
client and one that assumes a smart server. These are specified in <a class="reference external" href="http://bittorrent.org/beps/bep_0019.html">BEP 19</a>
and <a class="reference external" href="http://bittorrent.org/beps/bep_0017.html">BEP 17</a> respectively.</p>
<p>libtorrent supports both. In the libtorrent source code and API, BEP 19 urls
are typically referred to as <em>url seeds</em> and BEP 17 urls are typically referred
to as <em>HTTP seeds</em>.</p>
<p>The libtorrent implementation of <a class="reference external" href="http://bittorrent.org/beps/bep_0019.html">BEP 19</a> assumes that, if the URL ends with a
slash ('/'), the filename should be appended to it in order to request pieces
from that file. The way this works is that if the torrent is a single-file
torrent, only that filename is appended. If the torrent is a multi-file
torrent, the torrent's name '/' the file name is appended. This is the same
directory structure that libtorrent will download torrents into.</p>
</div>
</div>
<div class="section" id="piece-picker">
<h1>piece picker</h1>
<p>The piece picker in libtorrent has the following features:</p>
<ul class="simple">
<li>rarest first</li>
<li>sequential download</li>
<li>random pick</li>
<li>reverse order picking</li>
<li>parole mode</li>
<li>prioritize partial pieces</li>
<li>prefer whole pieces</li>
<li>piece affinity by speed category</li>
<li>piece priorities</li>
</ul>
<div class="section" id="internal-representation">
<h2>internal representation</h2>
<p>It is optimized by, at all times, keeping a list of pieces ordered by rarity,
randomly shuffled within each rarity class. This list is organized as a single
vector of contigous memory in RAM, for optimal memory locality and to eliminate
heap allocations and frees when updating rarity of pieces.</p>
<p>Expensive events, like a peer joining or leaving, are evaluated lazily, since
it's cheaper to rebuild the whole list rather than updating every single piece
in it. This means as long as no blocks are picked, peers joining and leaving is
no more costly than a single peer joining or leaving. Of course the special
cases of peers that have all or no pieces are optimized to not require
rebuilding the list.</p>
</div>
<div class="section" id="picker-strategy">
<h2>picker strategy</h2>
<p>The normal mode of the picker is of course <em>rarest first</em>, meaning pieces that
few peers have are preferred to be downloaded over pieces that more peers have.
This is a fundamental algorithm that is the basis of the performance of
bittorrent. However, the user may set the piece picker into sequential download
mode. This mode simply picks pieces sequentially, always preferring lower piece
indices.</p>
<p>When a torrent starts out, picking the rarest pieces means increased risk that
pieces won't be completed early (since there are only a few peers they can be
downloaded from), leading to a delay of having any piece to offer to other
peers. This lack of pieces to trade, delays the client from getting started
into the normal tit-for-tat mode of bittorrent, and will result in a long
ramp-up time. The heuristic to mitigate this problem is to, for the first few
pieces, pick random pieces rather than rare pieces. The threshold for when to
leave this initial picker mode is determined by
<a class="reference external" href="reference-Settings.html#initial_picker_threshold">session_settings::initial_picker_threshold</a>.</p>
</div>
<div class="section" id="reverse-order">
<h2>reverse order</h2>
<p>An orthogonal setting is <em>reverse order</em>, which is used for <em>snubbed</em> peers.
Snubbed peers are peers that appear very slow, and might have timed out a piece
request. The idea behind this is to make all snubbed peers more likely to be
able to do download blocks from the same piece, concentrating slow peers on as
few pieces as possible. The reverse order means that the most common pieces are
picked, instead of the rarest pieces (or in the case of sequential download,
the last pieces, intead of the first).</p>
</div>
<div class="section" id="parole-mode">
<h2>parole mode</h2>
<p>Peers that have participated in a piece that failed the hash check, may be put
in <em>parole mode</em>. This means we prefer downloading a full piece from this
peer, in order to distinguish which peer is sending corrupt data. Whether to do
this is or not is controlled by <a class="reference external" href="reference-Settings.html#use_parole_mode">session_settings::use_parole_mode</a>.</p>
<p>In parole mode, the piece picker prefers picking one whole piece at a time for
a given peer, avoiding picking any blocks from a piece any other peer has
contributed to (since that would defeat the purpose of parole mode).</p>
</div>
<div class="section" id="prioritize-partial-pieces">
<h2>prioritize partial pieces</h2>
<p>This setting determines if partially downloaded or requested pieces should
always be preferred over other pieces. The benefit of doing this is that the
number of partial pieces is minimized (and hence the turn-around time for
downloading a block until it can be uploaded to others is minimized). It also
puts less stress on the disk cache, since fewer partial pieces need to be kept
in the cache. Whether or not to enable this is controlled by
<a class="reference external" href="reference-Settings.html#prioritize_partial_pieces">session_settings::prioritize_partial_pieces</a>.</p>
<p>The main benefit of not prioritizing partial pieces is that the rarest first
algorithm gets to have more influence on which pieces are picked. The picker is
more likely to truly pick the rarest piece, and hence improving the performance
of the swarm.</p>
<p>This setting is turned on automatically whenever the number of partial pieces
in the piece picker exceeds the number of peers we're connected to times 1.5.
This is in order to keep the waste of partial pieces to a minimum, but still
prefer rarest pieces.</p>
</div>
<div class="section" id="prefer-whole-pieces">
<h2>prefer whole pieces</h2>
<p>The <em>prefer whole pieces</em> setting makes the piece picker prefer picking entire
pieces at a time. This is used by web connections (both http seeding
standards), in order to be able to coalesce the small bittorrent requests to
larger HTTP requests. This significantly improves performance when downloading
over HTTP.</p>
<p>It is also used by peers that are downloading faster than a certain threshold.
The main advantage is that these peers will better utilize the other peer's
disk cache, by requesting all blocks in a single piece, from the same peer.</p>
<p>This threshold is controlled by <a class="reference external" href="reference-Settings.html#whole_pieces_threshold">session_settings::whole_pieces_threshold</a>.</p>
<p><em>TODO: piece affinity by speed category</em>
<em>TODO: piece priorities</em></p>
</div>
</div>
<div class="section" id="ssl-torrents">
<h1>SSL torrents</h1>
<p>Torrents may have an SSL root (CA) certificate embedded in them. Such torrents
are called <em>SSL torrents</em>. An SSL torrent talks to all bittorrent peers over
SSL. The protocols are layered like this:</p>
<pre class="literal-block">
+-----------------------+
| BitTorrent protocol |
+-----------------------+
| SSL |
+-----------+-----------+
| TCP | uTP |
| +-----------+
| | UDP |
+-----------+-----------+
</pre>
<p>During the SSL handshake, both peers need to authenticate by providing a
certificate that is signed by the CA certificate found in the .torrent file.
These peer certificates are expected to be privided to peers through some other
means than bittorrent. Typically by a peer generating a certificate request
which is sent to the publisher of the torrent, and the publisher returning a
signed certificate.</p>
<p>In libtorrent, <a class="reference external" href="reference-Core.html#set_ssl_certificate()">set_ssl_certificate()</a> in <a class="reference external" href="reference-Core.html#torrent_handle">torrent_handle</a> is used to tell
libtorrent where to find the peer certificate and the private key for it. When
an SSL torrent is loaded, the <a class="reference external" href="reference-Alerts.html#torrent_need_cert_alert">torrent_need_cert_alert</a> is posted to remind the
user to provide a certificate.</p>
<p>A peer connecting to an SSL torrent MUST provide the <em>SNI</em> TLS extension
(server name indication). The server name is the hex encoded info-hash of the
torrent to connect to. This is required for the client accepting the connection
to know which certificate to present.</p>
<p>SSL connections are accepted on a separate socket from normal bittorrent
connections. To pick which port the SSL socket should bind to, set
<a class="reference external" href="reference-Settings.html#ssl_listen">session_settings::ssl_listen</a> to a different port. It defaults to port 4433.
This setting is only taken into account when the normal listen socket is opened
(i.e. just changing this setting won't necessarily close and re-open the SSL
socket). To not listen on an SSL socket at all, set <tt class="docutils literal">ssl_listen</tt> to 0.</p>
<p>This feature is only available if libtorrent is build with openssl support
(<tt class="docutils literal">TORRENT_USE_OPENSSL</tt>) and requires at least openSSL version 1.0, since it
needs SNI support.</p>
<p>Peer certificates must have at least one <em>SubjectAltName</em> field of type
dNSName. At least one of the fields must <em>exactly</em> match the name of the
torrent. This is a byte-by-byte comparison, the UTF-8 encoding must be
identical (i.e. there's no unicode normalization going on). This is the
recommended way of verifying certificates for HTTPS servers according to <a class="reference external" href="http://www.ietf.org/rfc/rfc2818.txt">RFC
2818</a>. Note the difference that for torrents only <em>dNSName</em> fields are taken
into account (not IP address fields). The most specific (i.e. last) <em>Common
Name</em> field is also taken into account if no <em>SubjectAltName</em> did not match.</p>
<p>If any of these fields contain a single asterisk (&quot;*&quot;), the certificate is
considered covering any torrent, allowing it to be reused for any torrent.</p>
<p>The purpose of matching the torrent name with the fields in the peer
certificate is to allow a publisher to have a single root certificate for all
torrents it distributes, and issue separate peer certificates for each torrent.
A peer receiving a certificate will not necessarily be able to access all
torrents published by this root certificate (only if it has a &quot;star cert&quot;).</p>
<div class="section" id="testing">
<h2>testing</h2>
<p>To test incoming SSL connections to an SSL torrent, one can use the following
<em>openssl</em> command:</p>
<pre class="literal-block">
openssl s_client -cert &lt;peer-certificate&gt;.pem -key &lt;peer-private-key&gt;.pem -CAfile \
&lt;torrent-cert&gt;.pem -debug -connect 127.0.0.1:4433 -tls1 -servername &lt;info-hash&gt;
</pre>
<p>To create a root certificate, the Distinguished Name (<em>DN</em>) is not taken into
account by bittorrent peers. You still need to specify something, but from
libtorrent's point of view, it doesn't matter what it is. libtorrent only makes
sure the peer certificates are signed by the correct root certificate.</p>
<p>One way to create the certificates is to use the <tt class="docutils literal">CA.sh</tt> script that comes
with openssl, like thisi (don't forget to enter a common Name for the
certificate):</p>
<pre class="literal-block">
CA.sh -newca
CA.sh -newreq
CA.sh -sign
</pre>
<p>The torrent certificate is located in <tt class="docutils literal">./demoCA/private/demoCA/cacert.pem</tt>,
this is the pem file to include in the .torrent file.</p>
<p>The peer's certificate is located in <tt class="docutils literal">./newcert.pem</tt> and the certificate's
private key in <tt class="docutils literal">./newkey.pem</tt>.</p>
</div>
</div>
</div>
</body>
</html>

12943
docs/manual.html Normal file

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@ libtorrent API Documentation
============================
:Author: Arvid Norberg, arvid@rasterbar.com
:Version: 1.0.0
:Version: 1.1.0
.. contents:: Table of contents
:depth: 1
@ -177,22 +177,19 @@ torrents are being downloaded at any given time, and once a torrent is completel
downloaded, the next in line is started.
Torrents that are *auto managed* are subject to the queuing and the active
torrents limits. To make a torrent auto managed, set ``auto_managed`` to true
torrents limits. To make a torrent auto managed, set add_torrent_params::flag_auto_managed
when adding the torrent (see async_add_torrent() and add_torrent()).
The limits of the number of downloading and seeding torrents are controlled via
``active_downloads``, ``active_seeds`` and ``active_limit`` in
session_settings. These limits takes non auto managed torrents into account as
settings_pack::active_downloads, settings_pack::active_seeds and settings_pack::active_limit in
settings_pack. These limits takes non auto managed torrents into account as
well. If there are more non-auto managed torrents being downloaded than the
``active_downloads`` setting, any auto managed torrents will be queued until
settings_pack::active_downloads setting, any auto managed torrents will be queued until
torrents are removed so that the number drops below the limit.
The default values are 8 active downloads and 5 active seeds.
At a regular interval, torrents are checked if there needs to be any
re-ordering of which torrents are active and which are queued. This interval
can be controlled via ``auto_manage_interval`` in session_settings. It defaults
to every 30 seconds.
can be controlled via settings_pack::auto_manage_interval.
For queuing to work, resume data needs to be saved and restored for all
torrents. See save_resume_data().
@ -226,9 +223,9 @@ prioritized for seeding. A seed cycle is completed when a torrent meets either
the share ratio limit (uploaded bytes / downloaded bytes), the share time ratio
(time seeding / time downloaing) or seed time limit (time seeded).
The relevant settings to control these limits are ``share_ratio_limit``,
``seed_time_ratio_limit`` and ``seed_time_limit`` in session_settings.
The relevant settings to control these limits are
settings_pack::share_ratio_limit, settings_pack::seed_time_ratio_limit and
settings_pack::seed_time_limit.
fast resume
===========
@ -469,8 +466,7 @@ compact allocation
------------------
.. note::
Note that support for compact allocation is deprecated in libttorrent, and will
be removed in future versions.
Support for compact allocation has been removed from libttorrent
The compact allocation will only allocate as much storage as it needs to keep
the pieces downloaded so far. This means that pieces will be moved around to be
@ -541,12 +537,14 @@ metadata from peers
Extension name: "LT_metadata"
.. note::
This extension is deprecated in favor of the more widely supported
``ut_metadata`` extension, see `BEP 9`_. The point with this extension is that
you don't have to distribute the metadata (.torrent-file) separately. The
metadata can be distributed through the bittorrent swarm. The only thing you
need to download such a torrent is the tracker url and the info-hash of the
torrent.
``ut_metadata`` extension, see `BEP 9`_.
The point with this extension is that you don't have to distribute the
metadata (.torrent-file) separately. The metadata can be distributed
through the bittorrent swarm. The only thing you need to download such
a torrent is the tracker url and the info-hash of the torrent.
It works by assuming that the initial seeder has the metadata and that the
metadata will propagate through the network as more peers join.
@ -660,6 +658,43 @@ directory structure that libtorrent will download torrents into.
.. _`BEP 17`: http://bittorrent.org/beps/bep_0017.html
.. _`BEP 19`: http://bittorrent.org/beps/bep_0019.html
dynamic loading of torrent files
================================
libtorrent has a feature that can unload idle torrents from memory. The purpose
of this is to support being active on many more torrents than the RAM permits.
This is useful for both embedded devices that have limited RAM and servers
seeding tens of thousands of torrents.
The most significant parts of loaded torrents that use RAM are the piece
hashes (20 bytes per piece) and the file list. The entire info-dictionary
of the .torrent file is kept in RAM.
In order to activate the dynamic loading of torrent files, set the load
function on the session. See set_load_function().
When a load function is set on the session, the dynamic load/unload
feature is enabled. Torrents are kept in an LRU. Every time an operation
is performed, on a torrent or from a peer, that requires the metadata of
the torrent to be loaded, the torrent is bumped up in the LRU. When a torrent
is paused or queued, it is demoted to the least recently used torrent in
the LRU, since it's a good candidate for eviction.
To configure how many torrents are allowed to be loaded at the same time,
set settings_pack::active_loaded_limit on the session.
Torrents can be exempt from being unloaded by being *pinned*. Pinned torrents
still count against the limit, but are never considered for eviction.
You can either pin a torrent when adding it, in ``add_torrent_params``
(see async_add_torrent() and add_torrent()), or after ading it with the
set_pinned() function on torrent_handle.
Torrents that start out without metadata (e.g. magnet links or http downloads)
are automatically pinned. This is important in order to give the client a
chance to save the metadata to disk once it's received (see metadata_received_alert).
Once the metadata is saved to disk, it might make sense to unpin the torrent.
piece picker
============
@ -708,7 +743,7 @@ into the normal tit-for-tat mode of bittorrent, and will result in a long
ramp-up time. The heuristic to mitigate this problem is to, for the first few
pieces, pick random pieces rather than rare pieces. The threshold for when to
leave this initial picker mode is determined by
session_settings::initial_picker_threshold.
settings_pack::initial_picker_threshold.
reverse order
-------------
@ -727,7 +762,7 @@ parole mode
Peers that have participated in a piece that failed the hash check, may be put
in *parole mode*. This means we prefer downloading a full piece from this
peer, in order to distinguish which peer is sending corrupt data. Whether to do
this is or not is controlled by session_settings::use_parole_mode.
this is or not is controlled by settings_pack::use_parole_mode.
In parole mode, the piece picker prefers picking one whole piece at a time for
a given peer, avoiding picking any blocks from a piece any other peer has
@ -742,7 +777,7 @@ number of partial pieces is minimized (and hence the turn-around time for
downloading a block until it can be uploaded to others is minimized). It also
puts less stress on the disk cache, since fewer partial pieces need to be kept
in the cache. Whether or not to enable this is controlled by
session_settings::prioritize_partial_pieces.
setting_pack::prioritize_partial_pieces.
The main benefit of not prioritizing partial pieces is that the rarest first
algorithm gets to have more influence on which pieces are picked. The picker is
@ -767,11 +802,81 @@ It is also used by peers that are downloading faster than a certain threshold.
The main advantage is that these peers will better utilize the other peer's
disk cache, by requesting all blocks in a single piece, from the same peer.
This threshold is controlled by session_settings::whole_pieces_threshold.
This threshold is controlled by the settings_pack::whole_pieces_threshold
setting.
*TODO: piece affinity by speed category*
*TODO: piece priorities*
predictive piece announce
=========================
In order to improve performance, libtorrent supports a feature called
``predictive piece announce``. When enabled, it will make libtorrent announce
that we have pieces to peers, before we truly have them. The most important
case is to announce a piece as soon as it has been downloaded and passed the
hash check, but not yet been written to disk. In this case, there is a risk the
piece will fail to be written to disk, in which case we won't have the piece
anymore, even though we announced it to peers.
The other case is when we're very close to completing the download of a piece
and assume it will pass the hash check, we can announce it to peers to make it
available one round-trip sooner than otherwise. This lets libtorrent start
uploading the piece to interested peers immediately when the piece complete,
instead of waiting one round-trip for the peers to request it.
This makes for the implementation slightly more complicated, since piece will
have more states and more complicated transitions. For instance, a piece could
be:
1. hashed but not fully written to disk
2. fully written to disk but not hashed
3. not fully downloaded
4. downloaded and hash checked
Once a piece is fully downloaded, the hash check could complete before any of
the write operations or it could complete after all write operations are
complete.
peer classes
============
The peer classes feature in libtorrent allows a client to define custom groups
of peers and rate limit them individually. Each such group is called a *peer
class*. There are a few default peer classes that are always created:
* global - all peers belong to this class, except peers on the local network
* local peers - all peers on the local network belongs to this class TCP peers
* - all peers connected over TCP belong to this class
The TCP peers class is used by the uTP/TCP balancing logic, if it's enabled, to
throttle TCP peers. The global and local classes are used to adjust the global
rate limits.
When the rate limits are adjusted for a specific torrent, a class is created
implicitly for that torrent.
The default peer class IDs are defined as enums in the ``session`` class::
enum {
global_peer_class_id,
tcp_peer_class_id,
local_peer_class_id
};
A peer class can be considered a more general form of *lables* that some
clients have. Peer classes however are not just applied to torrents, but
ultimately the peers.
Peer classes can be created with the create_peer_class() call (on the session
object), and deleted with the delete_peer_class() call.
Peer classes are configured with the set_peer_class() get_peer_class() calls.
Custom peer classes can be assigned to torrents, with the ??? call, in which
case all its peers will belong to the class. They can also be assigned based on
the peer's IP address. See set_peer_class_filter() for more information.
SSL torrents
============
@ -808,7 +913,7 @@ to know which certificate to present.
SSL connections are accepted on a separate socket from normal bittorrent
connections. To pick which port the SSL socket should bind to, set
session_settings::ssl_listen to a different port. It defaults to port 4433.
settings_pack::ssl_listen to a different port. It defaults to port 4433.
This setting is only taken into account when the normal listen socket is opened
(i.e. just changing this setting won't necessarily close and re-open the SSL
socket). To not listen on an SSL socket at all, set ``ssl_listen`` to 0.
@ -865,3 +970,53 @@ this is the pem file to include in the .torrent file.
The peer's certificate is located in ``./newcert.pem`` and the certificate's
private key in ``./newkey.pem``.
session statistics
==================
libtorrent provides a mechanism to query performance and statistics counters
from its internals. This is primarily useful for troubleshooting of production
systems and performance tuning.
The statistics consists of two fundamental types. *counters* and *gauges*. A
counter is a monotonically increasing value, incremented every time some event
occurs. For example, every time the network thread wakes up because a socket
became readable will increment a counter. Another example is every time a
socket receives *n* bytes, a counter is incremented by *n*.
*Counters* are the most flexible of metrics. It allows the program to sample
the counter at any interval, and calculate average rates of increments to the
counter. Some events may be rare and need to be sampled over a longer period in
order to get userful rates, where other events may be more frequent and evenly
distributed that sampling it frequently yields useful values. Counters also
provides accurate overall counts. For example, converting samples of a download
rate into a total transfer count is not accurate and takes more samples.
Converting an increasing counter into a rate is easy and flexible.
*Gauges* measure the instantaneous state of some kind. This is used for metrics
that are not counting events or flows, but states that can fluctuate. For
example, the number of torrents that are currenly being downloaded.
It's important to know whether a value is a counter or a gauge in order to
interpret it correctly. In order to query libtorrent for which counters and
gauges are available, call session_stats_metrics(). This will return metadata
about the values available for inspection in libtorrent. It will include
whether a value is a counter or a gauge. The key information it includes is the
index used to extract the actual measurements for a specific counter or gauge.
In order to take a sample, call post_session_stats() in the session object.
This will result in a session_stats_alert being posted. In this alert object,
there is an array of values, these values make up the sample. The value index
in the stats metric indicates which index the metric's value is stored in.
The mapping between metric and value is not stable across versions of
libtorrent. Always query the metrics first, to find out the index at which the
value is stored, before interpreting the values array in the
session_stats_alert. The mapping will *not* change during the runtime of your
process though, it's tied to a specific libtorrent version. You only have to
query the mapping once on startup (or every time ``libtorrent.so`` is loaded,
if it's done dynamically).
The available stats metrics are:
.. include:: stats_counters.rst

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 14 KiB

File diff suppressed because it is too large Load Diff

View File

@ -1,785 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.11: http://docutils.sourceforge.net/" />
<title>Bencoding</title>
<meta name="author" content="Arvid Norberg, arvid&#64;rasterbar.com" />
<link rel="stylesheet" type="text/css" href="../../css/base.css" />
<link rel="stylesheet" type="text/css" href="../../css/rst.css" />
<script type="text/javascript">
/* <![CDATA[ */
(function() {
var s = document.createElement('script'), t = document.getElementsByTagName('script')[0];
s.type = 'text/javascript';
s.async = true;
s.src = 'http://api.flattr.com/js/0.6/load.js?mode=auto';
t.parentNode.insertBefore(s, t);
})();
/* ]]> */
</script>
<link rel="stylesheet" href="style.css" type="text/css" />
<style type="text/css">
/* Hides from IE-mac \*/
* html pre { height: 1%; }
/* End hide from IE-mac */
</style>
</head>
<body>
<div class="document" id="bencoding">
<div id="container">
<div id="headerNav">
<ul>
<li class="first"><a href="/">Home</a></li>
<li><a href="../../products.html">Products</a></li>
<li><a href="../../contact.html">Contact</a></li>
</ul>
</div>
<div id="header">
<div id="orange"></div>
<div id="logo"></div>
</div>
<div id="main">
<h1 class="title">Bencoding</h1>
<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<tr><th class="docinfo-name">Author:</th>
<td>Arvid Norberg, <a class="last reference external" href="mailto:arvid&#64;rasterbar.com">arvid&#64;rasterbar.com</a></td></tr>
<tr><th class="docinfo-name">Version:</th>
<td>1.0.0</td></tr>
</tbody>
</table>
<div class="contents topic" id="table-of-contents">
<p class="topic-title first">Table of contents</p>
<ul class="simple">
<li><a class="reference internal" href="#invalid-encoding" id="id55">invalid_encoding</a></li>
<li><a class="reference internal" href="#type-error" id="id56">type_error</a></li>
<li><a class="reference internal" href="#entry" id="id57">entry</a></li>
<li><a class="reference internal" href="#pascal-string" id="id58">pascal_string</a></li>
<li><a class="reference internal" href="#lazy-entry" id="id59">lazy_entry</a></li>
</ul>
</div>
<p>Bencoding is a common representation in bittorrent used for
for dictionary, list, int and string hierarchies. It's used
to encode .torrent files and some messages in the network
protocol. libtorrent also uses it to store settings, resume
data and other state between sessions.</p>
<p>Strings in bencoded structures are not necessarily representing
text. Strings are raw byte buffers of a certain length. If a
string is meant to be interpreted as text, it is required to
be UTF-8 encoded. See <a class="reference external" href="http://bittorrent.org/beps/bep_0003.html">BEP 3</a>.</p>
<p>There are two mechanims to <em>decode</em> bencoded buffers in libtorrent.</p>
<p>The most flexible one is <a class="reference external" href="reference-Bencoding.html#bdecode()">bdecode()</a>, which returns a structure
represented by <a class="reference external" href="reference-Bencoding.html#entry">entry</a>. When a buffer is decoded with this function,
it can be discarded. The <a class="reference external" href="reference-Bencoding.html#entry">entry</a> does not contain any references back
to it. This means that <a class="reference external" href="reference-Bencoding.html#bdecode()">bdecode()</a> actually copies all the data out
of the buffer and into its own hierarchy. This makes this
function potentially expensive, if you're parsing large amounts
of data.</p>
<p>Another consideration is that <a class="reference external" href="reference-Bencoding.html#bdecode()">bdecode()</a> is a recursive parser.
For this reason, in order to avoid DoS attacks by triggering
a stack overflow, there is a recursion limit. This limit is
a sanity check to make sure it doesn't run the risk of
busting the stack.</p>
<p>The second mechanism is <a class="reference external" href="reference-Bencoding.html#lazy_bdecode()">lazy_bdecode()</a>, which returns a
bencoded structure represented by <a class="reference external" href="reference-Bencoding.html#lazy_entry">lazy_entry</a>. This function
builds a tree that points back into the original buffer.
The returned <a class="reference external" href="reference-Bencoding.html#lazy_entry">lazy_entry</a> will not be valid once the buffer
it was parsed out of is discarded.</p>
<p>Not only is this function more efficient because of less
memory allocation and data copy, the parser is also not
recursive, which means it probably performs a little bit
better and can have a higher recursion limit on the structures
it's parsing.</p>
<a name="invalid_encoding"></a><div class="section" id="invalid-encoding">
<h1>invalid_encoding</h1>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/bencode.hpp">libtorrent/bencode.hpp</a>&quot;</p>
<p>thrown by <a class="reference external" href="reference-Bencoding.html#bdecode()">bdecode()</a> if the provided bencoded buffer does not contain
valid encoding.</p>
<pre class="literal-block">
struct invalid_encoding: std::exception
{
virtual const char* <strong>what</strong> () const throw();
};
</pre>
<a name="type_error"></a></div>
<div class="section" id="type-error">
<h1>type_error</h1>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/entry.hpp">libtorrent/entry.hpp</a>&quot;</p>
<p>thrown by any accessor function of <a class="reference external" href="reference-Bencoding.html#entry">entry</a> if the accessor
function requires a type different than the actual type
of the <a class="reference external" href="reference-Bencoding.html#entry">entry</a> object.</p>
<pre class="literal-block">
struct type_error: std::runtime_error
{
<strong>type_error</strong> (const char* error);
};
</pre>
<a name="entry"></a></div>
<div class="section" id="entry">
<h1>entry</h1>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/entry.hpp">libtorrent/entry.hpp</a>&quot;</p>
<p>The <tt class="docutils literal">entry</tt> class represents one node in a bencoded hierarchy. It works as a
variant type, it can be either a list, a dictionary (<tt class="docutils literal"><span class="pre">std::map</span></tt>), an integer
or a string.</p>
<pre class="literal-block">
class entry
{
data_type <strong>type</strong> () const;
<strong>entry</strong> (list_type const&amp;);
<strong>entry</strong> (integer_type const&amp;);
<strong>entry</strong> (dictionary_type const&amp;);
<strong>entry</strong> (string_type const&amp;);
<strong>entry</strong> (data_type t);
void <strong>operator=</strong> (string_type const&amp;);
void <strong>operator=</strong> (entry const&amp;);
void <strong>operator=</strong> (integer_type const&amp;);
void <strong>operator=</strong> (lazy_entry const&amp;);
void <strong>operator=</strong> (dictionary_type const&amp;);
void <strong>operator=</strong> (list_type const&amp;);
const integer_type&amp; <strong>integer</strong> () const;
const string_type&amp; <strong>string</strong> () const;
const dictionary_type&amp; <strong>dict</strong> () const;
string_type&amp; <strong>string</strong> ();
list_type&amp; <strong>list</strong> ();
dictionary_type&amp; <strong>dict</strong> ();
integer_type&amp; <strong>integer</strong> ();
const list_type&amp; <strong>list</strong> () const;
void <strong>swap</strong> (entry&amp; e);
entry&amp; <strong>operator[]</strong> (std::string const&amp; key);
const entry&amp; <strong>operator[]</strong> (std::string const&amp; key) const;
entry&amp; <strong>operator[]</strong> (char const* key);
const entry&amp; <strong>operator[]</strong> (char const* key) const;
entry const* <strong>find_key</strong> (char const* key) const;
entry* <strong>find_key</strong> (char const* key);
entry* <strong>find_key</strong> (std::string const&amp; key);
entry const* <strong>find_key</strong> (std::string const&amp; key) const;
std::string <strong>to_string</strong> () const;
enum data_type
{
int_t,
string_t,
list_t,
dictionary_t,
undefined_t,
};
mutable boost::uint8_t m_type_queried:1;
};
</pre>
<a name="type()"></a><div class="section" id="type">
<h2>type()</h2>
<pre class="literal-block">
data_type <strong>type</strong> () const;
</pre>
<p>returns the concrete type of the <a class="reference external" href="reference-Bencoding.html#entry">entry</a></p>
<a name="entry()"></a></div>
<div class="section" id="id16">
<h2>entry()</h2>
<pre class="literal-block">
<strong>entry</strong> (list_type const&amp;);
<strong>entry</strong> (integer_type const&amp;);
<strong>entry</strong> (dictionary_type const&amp;);
<strong>entry</strong> (string_type const&amp;);
</pre>
<p>constructors directly from a specific type.
The content of the argument is copied into the
newly constructed <a class="reference external" href="reference-Bencoding.html#entry">entry</a></p>
<a name="entry()"></a></div>
<div class="section" id="id18">
<h2>entry()</h2>
<pre class="literal-block">
<strong>entry</strong> (data_type t);
</pre>
<p>construct an empty <a class="reference external" href="reference-Bencoding.html#entry">entry</a> of the specified type.
see <a class="reference external" href="reference-Bencoding.html#data_type">data_type</a> enum.</p>
<a name="operator=()"></a></div>
<div class="section" id="operator">
<h2>operator=()</h2>
<pre class="literal-block">
void <strong>operator=</strong> (string_type const&amp;);
void <strong>operator=</strong> (entry const&amp;);
void <strong>operator=</strong> (integer_type const&amp;);
void <strong>operator=</strong> (lazy_entry const&amp;);
void <strong>operator=</strong> (dictionary_type const&amp;);
void <strong>operator=</strong> (list_type const&amp;);
</pre>
<p>copies the structure of the right hand side into this
<a class="reference external" href="reference-Bencoding.html#entry">entry</a>.</p>
<a name="string()"></a>
<a name="dict()"></a>
<a name="integer()"></a>
<a name="list()"></a></div>
<div class="section" id="string-dict-integer-list">
<h2>string() dict() integer() list()</h2>
<pre class="literal-block">
const integer_type&amp; <strong>integer</strong> () const;
const string_type&amp; <strong>string</strong> () const;
const dictionary_type&amp; <strong>dict</strong> () const;
string_type&amp; <strong>string</strong> ();
list_type&amp; <strong>list</strong> ();
dictionary_type&amp; <strong>dict</strong> ();
integer_type&amp; <strong>integer</strong> ();
const list_type&amp; <strong>list</strong> () const;
</pre>
<p>The <tt class="docutils literal">integer()</tt>, <tt class="docutils literal">string()</tt>, <tt class="docutils literal">list()</tt> and <tt class="docutils literal">dict()</tt> functions
are accessors that return the respective type. If the <tt class="docutils literal">entry</tt> object
isn't of the type you request, the accessor will throw
<a class="reference external" href="reference-Error_Codes.html#libtorrent_exception">libtorrent_exception</a> (which derives from <tt class="docutils literal"><span class="pre">std::runtime_error</span></tt>). You
can ask an <tt class="docutils literal">entry</tt> for its type through the <tt class="docutils literal">type()</tt> function.</p>
<p>If you want to create an <tt class="docutils literal">entry</tt> you give it the type you want it to
have in its constructor, and then use one of the non-const accessors
to get a reference which you then can assign the value you want it to
have.</p>
<p>The typical code to get info from a torrent file will then look like
this:</p>
<pre class="literal-block">
entry torrent_file;
// ...
// throws if this is not a dictionary
entry::dictionary_type const&amp; dict = torrent_file.dict();
entry::dictionary_type::const_iterator i;
i = dict.find(&quot;announce&quot;);
if (i != dict.end())
{
std::string tracker_url = i-&gt;second.string();
std::cout &lt;&lt; tracker_url &lt;&lt; &quot;\n&quot;;
}
</pre>
<p>The following code is equivalent, but a little bit shorter:</p>
<pre class="literal-block">
entry torrent_file;
// ...
// throws if this is not a dictionary
if (entry* i = torrent_file.find_key(&quot;announce&quot;))
{
std::string tracker_url = i-&gt;string();
std::cout &lt;&lt; tracker_url &lt;&lt; &quot;\n&quot;;
}
</pre>
<p>To make it easier to extract information from a torrent file, the
class <a class="reference external" href="reference-Core.html#torrent_info">torrent_info</a> exists.</p>
<a name="swap()"></a></div>
<div class="section" id="swap">
<h2>swap()</h2>
<pre class="literal-block">
void <strong>swap</strong> (entry&amp; e);
</pre>
<p>swaps the content of <em>this</em> with <tt class="docutils literal">e</tt>.</p>
<a name="operator[]()"></a></div>
<div class="section" id="id24">
<h2>operator[]()</h2>
<pre class="literal-block">
entry&amp; <strong>operator[]</strong> (std::string const&amp; key);
const entry&amp; <strong>operator[]</strong> (std::string const&amp; key) const;
entry&amp; <strong>operator[]</strong> (char const* key);
const entry&amp; <strong>operator[]</strong> (char const* key) const;
</pre>
<p>All of these functions requires the <a class="reference external" href="reference-Bencoding.html#entry">entry</a> to be a dictionary, if it
isn't they will throw <tt class="docutils literal"><span class="pre">libtorrent::type_error</span></tt>.</p>
<p>The non-const versions of the <tt class="docutils literal">operator[]</tt> will return a reference
to either the existing element at the given key or, if there is no
element with the given key, a reference to a newly inserted element at
that key.</p>
<p>The const version of <tt class="docutils literal">operator[]</tt> will only return a reference to an
existing element at the given key. If the key is not found, it will
throw <tt class="docutils literal"><span class="pre">libtorrent::type_error</span></tt>.</p>
<a name="find_key()"></a></div>
<div class="section" id="find-key">
<h2>find_key()</h2>
<pre class="literal-block">
entry const* <strong>find_key</strong> (char const* key) const;
entry* <strong>find_key</strong> (char const* key);
entry* <strong>find_key</strong> (std::string const&amp; key);
entry const* <strong>find_key</strong> (std::string const&amp; key) const;
</pre>
<p>These functions requires the <a class="reference external" href="reference-Bencoding.html#entry">entry</a> to be a dictionary, if it isn't
they will throw <tt class="docutils literal"><span class="pre">libtorrent::type_error</span></tt>.</p>
<p>They will look for an element at the given key in the dictionary, if
the element cannot be found, they will return 0. If an element with
the given key is found, the return a pointer to it.</p>
<a name="to_string()"></a></div>
<div class="section" id="to-string">
<h2>to_string()</h2>
<pre class="literal-block">
std::string <strong>to_string</strong> () const;
</pre>
<p>returns a pretty-printed string representation
of the bencoded structure, with JSON-style syntax</p>
<a name="data_type"></a></div>
<div class="section" id="enum-data-type">
<h2>enum data_type</h2>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/entry.hpp">libtorrent/entry.hpp</a>&quot;</p>
<table border="1" class="docutils">
<colgroup>
<col width="41%" />
<col width="21%" />
<col width="38%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">name</th>
<th class="head">value</th>
<th class="head">description</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>int_t</td>
<td>0</td>
<td>&nbsp;</td>
</tr>
<tr><td>string_t</td>
<td>1</td>
<td>&nbsp;</td>
</tr>
<tr><td>list_t</td>
<td>2</td>
<td>&nbsp;</td>
</tr>
<tr><td>dictionary_t</td>
<td>3</td>
<td>&nbsp;</td>
</tr>
<tr><td>undefined_t</td>
<td>4</td>
<td>&nbsp;</td>
</tr>
</tbody>
</table>
<a name="m_type_queried"></a><dl class="docutils">
<dt>m_type_queried</dt>
<dd>in debug mode this is set to false by bdecode to indicate that the
program has not yet queried the type of this <a class="reference external" href="reference-Bencoding.html#entry">entry</a>, and sould not
assume that it has a certain type. This is asserted in the accessor
functions. This does not apply if exceptions are used.</dd>
</dl>
<a name="pascal_string"></a></div>
</div>
<div class="section" id="pascal-string">
<h1>pascal_string</h1>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/lazy_entry.hpp">libtorrent/lazy_entry.hpp</a>&quot;</p>
<p>this is a string that is not NULL-terminated. Instead it
comes with a length, specified in bytes. This is particularly
useful when parsing bencoded structures, because strings are
not NULL-terminated internally, and requiring NULL termination
would require copying the string.</p>
<p>see <a class="reference external" href="reference-Bencoding.html#string_pstr()">lazy_entry::string_pstr()</a>.</p>
<pre class="literal-block">
struct pascal_string
{
<strong>pascal_string</strong> (char const* p, int l);
bool <strong>operator&lt;</strong> (pascal_string const&amp; rhs) const;
int len;
char const* ptr;
};
</pre>
<a name="pascal_string()"></a><div class="section" id="id31">
<h2>pascal_string()</h2>
<pre class="literal-block">
<strong>pascal_string</strong> (char const* p, int l);
</pre>
<p>construct a string pointing to the characters at <tt class="docutils literal">p</tt>
of length <tt class="docutils literal">l</tt> characters. No NULL termination is required.</p>
<a name="operator<()"></a></div>
<div class="section" id="id32">
<h2>operator&lt;()</h2>
<pre class="literal-block">
bool <strong>operator&lt;</strong> (pascal_string const&amp; rhs) const;
</pre>
<p>lexicographical comparison of strings. Order is consisten
with memcmp.</p>
<a name="len"></a><dl class="docutils">
<dt>len</dt>
<dd>the number of characters in the string.</dd>
</dl>
<a name="ptr"></a><dl class="docutils">
<dt>ptr</dt>
<dd>the pointer to the first character in the string. This is
not NULL terminated, but instead consult the <tt class="docutils literal">len</tt> field
to know how many characters follow.</dd>
</dl>
<a name="lazy_entry"></a></div>
</div>
<div class="section" id="lazy-entry">
<h1>lazy_entry</h1>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/lazy_entry.hpp">libtorrent/lazy_entry.hpp</a>&quot;</p>
<p>this object represent a node in a bencoded structure. It is a variant
type whose concrete type is one of:</p>
<ol class="arabic simple">
<li>dictionary (maps strings -&gt; <a class="reference external" href="reference-Bencoding.html#lazy_entry">lazy_entry</a>)</li>
<li>list (sequence of <a class="reference external" href="reference-Bencoding.html#lazy_entry">lazy_entry</a>, i.e. heterogenous)</li>
<li>integer</li>
<li>string</li>
</ol>
<p>There is also a <tt class="docutils literal">none</tt> type, which is used for uninitialized
lazy_entries.</p>
<pre class="literal-block">
struct lazy_entry
{
entry_type_t <strong>type</strong> () const;
void <strong>construct_int</strong> (char const* start, int length);
boost::int64_t <strong>int_value</strong> () const;
char const* <strong>string_ptr</strong> () const;
char const* <strong>string_cstr</strong> () const;
pascal_string <strong>string_pstr</strong> () const;
std::string <strong>string_value</strong> () const;
int <strong>string_length</strong> () const;
lazy_entry const* <strong>dict_find_string</strong> (char const* name) const;
lazy_entry* <strong>dict_find</strong> (char const* name);
lazy_entry const* <strong>dict_find</strong> (char const* name) const;
pascal_string <strong>dict_find_pstr</strong> (char const* name) const;
std::string <strong>dict_find_string_value</strong> (char const* name) const;
boost::int64_t <strong>dict_find_int_value</strong> (char const* name, boost::int64_t default_val = 0) const;
lazy_entry const* <strong>dict_find_int</strong> (char const* name) const;
lazy_entry const* <strong>dict_find_list</strong> (char const* name) const;
lazy_entry const* <strong>dict_find_dict</strong> (char const* name) const;
std::pair&lt;std::string, lazy_entry const*&gt; <strong>dict_at</strong> (int i) const;
int <strong>dict_size</strong> () const;
lazy_entry* <strong>list_at</strong> (int i);
lazy_entry const* <strong>list_at</strong> (int i) const;
std::string <strong>list_string_value_at</strong> (int i) const;
pascal_string <strong>list_pstr_at</strong> (int i) const;
boost::int64_t <strong>list_int_value_at</strong> (int i, boost::int64_t default_val = 0) const;
int <strong>list_size</strong> () const;
std::pair&lt;char const*, int&gt; <strong>data_section</strong> () const;
void <strong>swap</strong> (lazy_entry&amp; e);
enum entry_type_t
{
none_t,
dict_t,
list_t,
string_t,
int_t,
};
};
</pre>
<a name="type()"></a><div class="section" id="id36">
<h2>type()</h2>
<pre class="literal-block">
entry_type_t <strong>type</strong> () const;
</pre>
<p>tells you which specific type this lazy <a class="reference external" href="reference-Bencoding.html#entry">entry</a> has.
See <a class="reference external" href="reference-Bencoding.html#entry_type_t">entry_type_t</a>. The type determines which subset of
member functions are valid to use.</p>
<a name="construct_int()"></a></div>
<div class="section" id="construct-int">
<h2>construct_int()</h2>
<pre class="literal-block">
void <strong>construct_int</strong> (char const* start, int length);
</pre>
<p>start points to the first decimal digit
length is the number of digits</p>
<a name="int_value()"></a></div>
<div class="section" id="int-value">
<h2>int_value()</h2>
<pre class="literal-block">
boost::int64_t <strong>int_value</strong> () const;
</pre>
<p>requires the type to be an integer. return the integer value</p>
<a name="string_ptr()"></a></div>
<div class="section" id="string-ptr">
<h2>string_ptr()</h2>
<pre class="literal-block">
char const* <strong>string_ptr</strong> () const;
</pre>
<p>the string is not null-terminated!
use <a class="reference external" href="reference-Bencoding.html#string_length()">string_length()</a> to determine how many bytes
are part of the string.</p>
<a name="string_cstr()"></a></div>
<div class="section" id="string-cstr">
<h2>string_cstr()</h2>
<pre class="literal-block">
char const* <strong>string_cstr</strong> () const;
</pre>
<p>this will return a null terminated string
it will write to the source buffer!</p>
<a name="string_pstr()"></a></div>
<div class="section" id="string-pstr">
<h2>string_pstr()</h2>
<pre class="literal-block">
pascal_string <strong>string_pstr</strong> () const;
</pre>
<p>if this is a string, returns a <a class="reference external" href="reference-Bencoding.html#pascal_string">pascal_string</a>
representing the string value.</p>
<a name="string_value()"></a></div>
<div class="section" id="string-value">
<h2>string_value()</h2>
<pre class="literal-block">
std::string <strong>string_value</strong> () const;
</pre>
<p>if this is a string, returns the string as a std::string.
(which requires a copy)</p>
<a name="string_length()"></a></div>
<div class="section" id="string-length">
<h2>string_length()</h2>
<pre class="literal-block">
int <strong>string_length</strong> () const;
</pre>
<p>if the <a class="reference external" href="reference-Bencoding.html#lazy_entry">lazy_entry</a> is a string, returns the
length of the string, in bytes.</p>
<a name="dict_find()"></a>
<a name="dict_find_string()"></a></div>
<div class="section" id="dict-find-dict-find-string">
<h2>dict_find() dict_find_string()</h2>
<pre class="literal-block">
lazy_entry const* <strong>dict_find_string</strong> (char const* name) const;
lazy_entry* <strong>dict_find</strong> (char const* name);
lazy_entry const* <strong>dict_find</strong> (char const* name) const;
</pre>
<p>if this is a dictionary, look for a key <tt class="docutils literal">name</tt>, and return
a pointer to its value, or NULL if there is none.</p>
<a name="dict_find_pstr()"></a>
<a name="dict_find_string_value()"></a></div>
<div class="section" id="dict-find-pstr-dict-find-string-value">
<h2>dict_find_pstr() dict_find_string_value()</h2>
<pre class="literal-block">
pascal_string <strong>dict_find_pstr</strong> (char const* name) const;
std::string <strong>dict_find_string_value</strong> (char const* name) const;
</pre>
<p>if this is a dictionary, look for a key <tt class="docutils literal">name</tt> whose value
is a string. If such key exist, return a pointer to
its value, otherwise NULL.</p>
<a name="dict_find_int_value()"></a>
<a name="dict_find_int()"></a></div>
<div class="section" id="dict-find-int-value-dict-find-int">
<h2>dict_find_int_value() dict_find_int()</h2>
<pre class="literal-block">
boost::int64_t <strong>dict_find_int_value</strong> (char const* name, boost::int64_t default_val = 0) const;
lazy_entry const* <strong>dict_find_int</strong> (char const* name) const;
</pre>
<p>if this is a dictionary, look for a key <tt class="docutils literal">name</tt> whose value
is an int. If such key exist, return a pointer to its value,
otherwise NULL.</p>
<a name="dict_find_list()"></a>
<a name="dict_find_dict()"></a></div>
<div class="section" id="dict-find-list-dict-find-dict">
<h2>dict_find_list() dict_find_dict()</h2>
<pre class="literal-block">
lazy_entry const* <strong>dict_find_list</strong> (char const* name) const;
lazy_entry const* <strong>dict_find_dict</strong> (char const* name) const;
</pre>
<p>these functions require that <tt class="docutils literal">this</tt> is a dictionary.
(this-&gt;type() == dict_t). They look for an element with the
specified name in the dictionary. <tt class="docutils literal">dict_find_dict</tt> only
finds dictionaries and <tt class="docutils literal">dict_find_list</tt> only finds lists.
if no key with the corresponding value of the right type is
found, NULL is returned.</p>
<a name="dict_at()"></a></div>
<div class="section" id="dict-at">
<h2>dict_at()</h2>
<pre class="literal-block">
std::pair&lt;std::string, lazy_entry const*&gt; <strong>dict_at</strong> (int i) const;
</pre>
<p>if this is a dictionary, return the key value pair at
position <tt class="docutils literal">i</tt> from the dictionary.</p>
<a name="dict_size()"></a></div>
<div class="section" id="dict-size">
<h2>dict_size()</h2>
<pre class="literal-block">
int <strong>dict_size</strong> () const;
</pre>
<p>requires that <tt class="docutils literal">this</tt> is a dictionary. return the
number of items in it</p>
<a name="list_at()"></a></div>
<div class="section" id="list-at">
<h2>list_at()</h2>
<pre class="literal-block">
lazy_entry* <strong>list_at</strong> (int i);
lazy_entry const* <strong>list_at</strong> (int i) const;
</pre>
<p>requires that <tt class="docutils literal">this</tt> is a list. return
the item at index <tt class="docutils literal">i</tt>.</p>
<a name="list_string_value_at()"></a>
<a name="list_pstr_at()"></a></div>
<div class="section" id="list-string-value-at-list-pstr-at">
<h2>list_string_value_at() list_pstr_at()</h2>
<pre class="literal-block">
std::string <strong>list_string_value_at</strong> (int i) const;
pascal_string <strong>list_pstr_at</strong> (int i) const;
</pre>
<p>these functions require <tt class="docutils literal">this</tt> to have the type list.
(this-&gt;type() == list_t). <tt class="docutils literal">list_string_value_at</tt> returns
the string at index <tt class="docutils literal">i</tt>. <tt class="docutils literal">list_pstr_at</tt>
returns a <a class="reference external" href="reference-Bencoding.html#pascal_string">pascal_string</a> of the string value at index <tt class="docutils literal">i</tt>.
if the element at <tt class="docutils literal">i</tt> is not a string, an empty string
is returned.</p>
<a name="list_int_value_at()"></a></div>
<div class="section" id="list-int-value-at">
<h2>list_int_value_at()</h2>
<pre class="literal-block">
boost::int64_t <strong>list_int_value_at</strong> (int i, boost::int64_t default_val = 0) const;
</pre>
<p>this function require <tt class="docutils literal">this</tt> to have the type list.
(this-&gt;type() == list_t). returns the integer value at
index <tt class="docutils literal">i</tt>. If the element at <tt class="docutils literal">i</tt> is not an integer
<tt class="docutils literal">default_val</tt> is returned, which defaults to 0.</p>
<a name="list_size()"></a></div>
<div class="section" id="list-size">
<h2>list_size()</h2>
<pre class="literal-block">
int <strong>list_size</strong> () const;
</pre>
<p>if this is a list, return the number of items in it.</p>
<a name="data_section()"></a></div>
<div class="section" id="data-section">
<h2>data_section()</h2>
<pre class="literal-block">
std::pair&lt;char const*, int&gt; <strong>data_section</strong> () const;
</pre>
<p>returns pointers into the source buffer where
this <a class="reference external" href="reference-Bencoding.html#entry">entry</a> has its bencoded data</p>
<a name="swap()"></a></div>
<div class="section" id="id44">
<h2>swap()</h2>
<pre class="literal-block">
void <strong>swap</strong> (lazy_entry&amp; e);
</pre>
<p>swap values of <tt class="docutils literal">this</tt> and <tt class="docutils literal">e</tt>.</p>
<a name="entry_type_t"></a></div>
<div class="section" id="enum-entry-type-t">
<h2>enum entry_type_t</h2>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/lazy_entry.hpp">libtorrent/lazy_entry.hpp</a>&quot;</p>
<table border="1" class="docutils">
<colgroup>
<col width="33%" />
<col width="23%" />
<col width="43%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">name</th>
<th class="head">value</th>
<th class="head">description</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>none_t</td>
<td>0</td>
<td>&nbsp;</td>
</tr>
<tr><td>dict_t</td>
<td>1</td>
<td>&nbsp;</td>
</tr>
<tr><td>list_t</td>
<td>2</td>
<td>&nbsp;</td>
</tr>
<tr><td>string_t</td>
<td>3</td>
<td>&nbsp;</td>
</tr>
<tr><td>int_t</td>
<td>4</td>
<td>&nbsp;</td>
</tr>
</tbody>
</table>
<a name="bdecode()"></a>
<a name="bencode()"></a></div>
<div class="section" id="bdecode-bencode">
<h2>bdecode() bencode()</h2>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/bencode.hpp">libtorrent/bencode.hpp</a>&quot;</p>
<pre class="literal-block">
template&lt;class InIt&gt; entry <strong>bdecode</strong> (InIt start, InIt end);
template&lt;class OutIt&gt; int <strong>bencode</strong> (OutIt out, const entry&amp; e);
template&lt;class InIt&gt; entry <strong>bdecode</strong> (InIt start, InIt end, int&amp; len);
</pre>
<p>These functions will encode data to <a class="reference external" href="http://wiki.theory.org/index.php/BitTorrentSpecification">bencoded</a> or decode <a class="reference external" href="http://wiki.theory.org/index.php/BitTorrentSpecification">bencoded</a> data.</p>
<p>If possible, <a class="reference external" href="reference-Bencoding.html#lazy_bdecode()">lazy_bdecode()</a> should be preferred over <tt class="docutils literal">bdecode()</tt>.</p>
<p>The <a class="reference internal" href="#entry">entry</a> class is the internal representation of the bencoded data
and it can be used to retrieve information, an <a class="reference internal" href="#entry">entry</a> can also be build by
the program and given to <tt class="docutils literal">bencode()</tt> to encode it into the <tt class="docutils literal">OutIt</tt>
iterator.</p>
<p>The <tt class="docutils literal">OutIt</tt> and <tt class="docutils literal">InIt</tt> are iterators
(<a class="reference external" href="http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a> and <a class="reference external" href="http://www.sgi.com/tech/stl/OutputIterator.html">OutputIterator</a> respectively). They
are templates and are usually instantiated as <a class="reference external" href="http://www.sgi.com/tech/stl/ostream_iterator.html">ostream_iterator</a>,
<a class="reference external" href="http://www.sgi.com/tech/stl/back_insert_iterator.html">back_insert_iterator</a> or <a class="reference external" href="http://www.sgi.com/tech/stl/istream_iterator.html">istream_iterator</a>. These
functions will assume that the iterator refers to a character
(<tt class="docutils literal">char</tt>). So, if you want to encode <a class="reference external" href="reference-Bencoding.html#entry">entry</a> <tt class="docutils literal">e</tt> into a buffer
in memory, you can do it like this:</p>
<pre class="literal-block">
std::vector&lt;char&gt; buffer;
bencode(std::back_inserter(buf), e);
</pre>
<p>If you want to decode a torrent file from a buffer in memory, you can do it like this:</p>
<pre class="literal-block">
std::vector&lt;char&gt; buffer;
// ...
entry e = bdecode(buf.begin(), buf.end());
</pre>
<p>Or, if you have a raw char buffer:</p>
<pre class="literal-block">
const char* buf;
// ...
entry e = bdecode(buf, buf + data_size);
</pre>
<p>Now we just need to know how to retrieve information from the <a class="reference external" href="reference-Bencoding.html#entry">entry</a>.</p>
<p>If <tt class="docutils literal">bdecode()</tt> encounters invalid encoded data in the range given to it
it will throw <a class="reference external" href="reference-Error_Codes.html#libtorrent_exception">libtorrent_exception</a>.</p>
<a name="operator<<()"></a></div>
<div class="section" id="id51">
<h2>operator&lt;&lt;()</h2>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/entry.hpp">libtorrent/entry.hpp</a>&quot;</p>
<pre class="literal-block">
inline std::ostream&amp; <strong>operator&lt;&lt;</strong> (std::ostream&amp; os, const entry&amp; e);
</pre>
<p>prints the bencoded structure to the ostream as a JSON-style structure.</p>
<a name="lazy_bdecode()"></a></div>
<div class="section" id="lazy-bdecode">
<h2>lazy_bdecode()</h2>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/lazy_entry.hpp">libtorrent/lazy_entry.hpp</a>&quot;</p>
<pre class="literal-block">
int <strong>lazy_bdecode</strong> (char const* start, char const* end
, lazy_entry&amp; ret, error_code&amp; ec, int* error_pos = 0
, int depth_limit = 1000, int item_limit = 1000000);
</pre>
<p>This function decodes <a class="reference external" href="http://wiki.theory.org/index.php/BitTorrentSpecification">bencoded</a> data.</p>
<p>Whenever possible, <tt class="docutils literal">lazy_bdecode()</tt> should be preferred over <tt class="docutils literal">bdecode()</tt>.
It is more efficient and more secure. It supports having constraints on the
amount of memory is consumed by the parser.</p>
<p><em>lazy</em> refers to the fact that it doesn't copy any actual data out of the
bencoded buffer. It builds a tree of <tt class="docutils literal">lazy_entry</tt> which has pointers into
the bencoded buffer. This makes it very fast and efficient. On top of that,
it is not recursive, which saves a lot of stack space when parsing deeply
nested trees. However, in order to protect against potential attacks, the
<tt class="docutils literal">depth_limit</tt> and <tt class="docutils literal">item_limit</tt> control how many levels deep the tree is
allowed to get. With recursive parser, a few thousand levels would be enough
to exhaust the threads stack and terminate the process. The <tt class="docutils literal">item_limit</tt>
protects against very large structures, not necessarily deep. Each bencoded
item in the structure causes the parser to allocate some amount of memory,
this memory is constant regardless of how much data actually is stored in
the item. One potential attack is to create a bencoded list of hundreds of
thousands empty strings, which would cause the parser to allocate a significant
amount of memory, perhaps more than is available on the machine, and effectively
provide a denial of service. The default item limit is set as a reasonable
upper limit for desktop computers. Very few torrents have more items in them.
The limit corresponds to about 25 MB, which might be a bit much for embedded
systems.</p>
<p><tt class="docutils literal">start</tt> and <tt class="docutils literal">end</tt> defines the bencoded buffer to be decoded. <tt class="docutils literal">ret</tt> is
the <tt class="docutils literal">lazy_entry</tt> which is filled in with the whole decoded tree. <tt class="docutils literal">ec</tt>
is a reference to an <tt class="docutils literal">error_code</tt> which is set to describe the error encountered
in case the function fails. <tt class="docutils literal">error_pos</tt> is an optional pointer to an int,
which will be set to the byte offset into the buffer where an error occurred,
in case the function fails.</p>
<a name="print_entry()"></a></div>
<div class="section" id="print-entry">
<h2>print_entry()</h2>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/lazy_entry.hpp">libtorrent/lazy_entry.hpp</a>&quot;</p>
<pre class="literal-block">
std::string <strong>print_entry</strong> (lazy_entry const&amp; e
, bool single_line = false, int indent = 0);
</pre>
<p>print the bencoded structure in a human-readable format to a stting
that's returned.</p>
</div>
</div>
</div>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@ -1,426 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.11: http://docutils.sourceforge.net/" />
<title>Create Torrents</title>
<meta name="author" content="Arvid Norberg, arvid&#64;rasterbar.com" />
<link rel="stylesheet" type="text/css" href="../../css/base.css" />
<link rel="stylesheet" type="text/css" href="../../css/rst.css" />
<script type="text/javascript">
/* <![CDATA[ */
(function() {
var s = document.createElement('script'), t = document.getElementsByTagName('script')[0];
s.type = 'text/javascript';
s.async = true;
s.src = 'http://api.flattr.com/js/0.6/load.js?mode=auto';
t.parentNode.insertBefore(s, t);
})();
/* ]]> */
</script>
<link rel="stylesheet" href="style.css" type="text/css" />
<style type="text/css">
/* Hides from IE-mac \*/
* html pre { height: 1%; }
/* End hide from IE-mac */
</style>
</head>
<body>
<div class="document" id="create-torrents">
<div id="container">
<div id="headerNav">
<ul>
<li class="first"><a href="/">Home</a></li>
<li><a href="../../products.html">Products</a></li>
<li><a href="../../contact.html">Contact</a></li>
</ul>
</div>
<div id="header">
<div id="orange"></div>
<div id="logo"></div>
</div>
<div id="main">
<h1 class="title">Create Torrents</h1>
<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<tr><th class="docinfo-name">Author:</th>
<td>Arvid Norberg, <a class="last reference external" href="mailto:arvid&#64;rasterbar.com">arvid&#64;rasterbar.com</a></td></tr>
<tr><th class="docinfo-name">Version:</th>
<td>1.0.0</td></tr>
</tbody>
</table>
<div class="contents topic" id="table-of-contents">
<p class="topic-title first">Table of contents</p>
<ul class="simple">
<li><a class="reference internal" href="#create-torrent" id="id22">create_torrent</a></li>
</ul>
</div>
<p>This section describes the functions and classes that are used
to create torrent files. It is a layered API with low level classes
and higher level convenience functions. A torrent is created in 4
steps:</p>
<ol class="arabic simple">
<li>first the files that will be part of the torrent are determined.</li>
<li>the torrent properties are set, such as tracker url, web seeds,
DHT nodes etc.</li>
<li>Read through all the files in the torrent, SHA-1 all the data
and set the piece hashes.</li>
<li>The torrent is bencoded into a file or buffer.</li>
</ol>
<p>If there are a lot of files and or deep directoy hierarchies to
traverse, step one can be time consuming.</p>
<p>Typically step 3 is by far the most time consuming step, since it
requires to read all the bytes from all the files in the torrent.</p>
<p>All of these classes and functions are declared by including
<tt class="docutils literal">libtorrent/create_torrent.hpp</tt>.</p>
<p>example:</p>
<pre class="literal-block">
file_storage fs;
// recursively adds files in directories
add_files(fs, &quot;./my_torrent&quot;);
create_torrent t(fs);
t.add_tracker(&quot;http://my.tracker.com/announce&quot;);
t.set_creator(&quot;libtorrent example&quot;);
// reads the files and calculates the hashes
set_piece_hashes(t, &quot;.&quot;);
ofstream out(&quot;my_torrent.torrent&quot;, std::ios_base::binary);
bencode(std::ostream_iterator&lt;char&gt;(out), t.generate());
</pre>
<a name="create_torrent"></a><div class="section" id="create-torrent">
<h1>create_torrent</h1>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/create_torrent.hpp">libtorrent/create_torrent.hpp</a>&quot;</p>
<p>This class holds state for creating a torrent. After having added
all information to it, call <a class="reference external" href="reference-Create_Torrents.html#generate()">create_torrent::generate()</a> to generate
the torrent. The <a class="reference external" href="reference-Bencoding.html#entry">entry</a> that's returned can then be bencoded into a
.torrent file using <a class="reference external" href="reference-Bencoding.html#bencode()">bencode()</a>.</p>
<pre class="literal-block">
struct create_torrent
{
<strong>create_torrent</strong> (file_storage&amp; fs, int piece_size = 0
, int pad_file_limit = -1, int flags = optimize, int alignment = -1);
<strong>create_torrent</strong> (torrent_info const&amp; ti);
entry <strong>generate</strong> () const;
file_storage const&amp; <strong>files</strong> () const;
void <strong>set_comment</strong> (char const* str);
void <strong>set_creator</strong> (char const* str);
void <strong>set_hash</strong> (int index, sha1_hash const&amp; h);
void <strong>set_file_hash</strong> (int index, sha1_hash const&amp; h);
void <strong>add_url_seed</strong> (std::string const&amp; url);
void <strong>add_http_seed</strong> (std::string const&amp; url);
void <strong>add_node</strong> (std::pair&lt;std::string, int&gt; const&amp; node);
void <strong>add_tracker</strong> (std::string const&amp; url, int tier = 0);
void <strong>set_root_cert</strong> (std::string const&amp; pem);
bool <strong>priv</strong> () const;
void <strong>set_priv</strong> (bool p);
int <strong>num_pieces</strong> () const;
int <strong>piece_length</strong> () const;
int <strong>piece_size</strong> (int i) const;
std::vector&lt;sha1_hash&gt; const&amp; <strong>merkle_tree</strong> () const;
enum flags_t
{
optimize,
merkle,
modification_time,
symlinks,
calculate_file_hashes,
};
};
</pre>
<a name="create_torrent()"></a><div class="section" id="id5">
<h2>create_torrent()</h2>
<pre class="literal-block">
<strong>create_torrent</strong> (file_storage&amp; fs, int piece_size = 0
, int pad_file_limit = -1, int flags = optimize, int alignment = -1);
<strong>create_torrent</strong> (torrent_info const&amp; ti);
</pre>
<p>The <tt class="docutils literal">piece_size</tt> is the size of each piece in bytes. It must
be a multiple of 16 kiB. If a piece size of 0 is specified, a
piece_size will be calculated such that the torrent file is roughly 40 kB.</p>
<p>If a <tt class="docutils literal">pad_size_limit</tt> is specified (other than -1), any file larger than
the specified number of bytes will be preceeded by a pad file to align it
with the start of a piece. The pad_file_limit is ignored unless the
<tt class="docutils literal">optimize</tt> flag is passed. Typically it doesn't make sense to set this
any lower than 4kiB.</p>
<p>The overload that takes a <tt class="docutils literal">torrent_info</tt> object will make a verbatim
copy of its info dictionary (to preserve the info-hash). The copy of
the info dictionary will be used by <a class="reference external" href="reference-Create_Torrents.html#generate()">create_torrent::generate()</a>. This means
that none of the member functions of <a class="reference external" href="reference-Create_Torrents.html#create_torrent">create_torrent</a> that affects
the content of the info dictionary (such as <tt class="docutils literal">set_hash()</tt>), will
have any affect.</p>
<p>The <tt class="docutils literal">flags</tt> arguments specifies options for the torrent creation. It can
be any combination of the flags defined by <a class="reference external" href="reference-Create_Torrents.html#flags_t">create_torrent::flags_t</a>.</p>
<p><tt class="docutils literal">alignment</tt> is used when pad files are enabled. This is the size
eligible files are aligned to. The default is -1, which means the
piece size of the torrent.</p>
<a name="generate()"></a></div>
<div class="section" id="generate">
<h2>generate()</h2>
<pre class="literal-block">
entry <strong>generate</strong> () const;
</pre>
<p>This function will generate the .torrent file as a bencode tree. In order to
generate the flat file, use the <a class="reference external" href="reference-Bencoding.html#bencode()">bencode()</a> function.</p>
<p>It may be useful to add custom entries to the torrent file before bencoding it
and saving it to disk.</p>
<p>If anything goes wrong during torrent generation, this function will return
an empty <tt class="docutils literal">entry</tt> structure. You can test for this condition by querying the
type of the entry:</p>
<pre class="literal-block">
file_storage fs;
// add file ...
create_torrent t(fs);
// add trackers and piece hashes ...
e = t.generate();
if (e.type() == entry::undefined_t)
{
// something went wrong
}
</pre>
<p>For instance, you cannot generate a torrent with 0 files in it. If you don't add
any files to the <tt class="docutils literal">file_storage</tt>, torrent generation will fail.</p>
<a name="files()"></a></div>
<div class="section" id="files">
<h2>files()</h2>
<pre class="literal-block">
file_storage const&amp; <strong>files</strong> () const;
</pre>
<p>returns an immutable reference to the <a class="reference external" href="reference-Storage.html#file_storage">file_storage</a> used to create
the torrent from.</p>
<a name="set_comment()"></a></div>
<div class="section" id="set-comment">
<h2>set_comment()</h2>
<pre class="literal-block">
void <strong>set_comment</strong> (char const* str);
</pre>
<p>Sets the comment for the torrent. The string <tt class="docutils literal">str</tt> should be utf-8 encoded.
The comment in a torrent file is optional.</p>
<a name="set_creator()"></a></div>
<div class="section" id="set-creator">
<h2>set_creator()</h2>
<pre class="literal-block">
void <strong>set_creator</strong> (char const* str);
</pre>
<p>Sets the creator of the torrent. The string <tt class="docutils literal">str</tt> should be utf-8 encoded.
This is optional.</p>
<a name="set_hash()"></a></div>
<div class="section" id="set-hash">
<h2>set_hash()</h2>
<pre class="literal-block">
void <strong>set_hash</strong> (int index, sha1_hash const&amp; h);
</pre>
<p>This sets the SHA-1 hash for the specified piece (<tt class="docutils literal">index</tt>). You are required
to set the hash for every piece in the torrent before generating it. If you have
the files on disk, you can use the high level convenience function to do this.
See <a class="reference external" href="reference-Create_Torrents.html#set_piece_hashes()">set_piece_hashes()</a>.</p>
<a name="set_file_hash()"></a></div>
<div class="section" id="set-file-hash">
<h2>set_file_hash()</h2>
<pre class="literal-block">
void <strong>set_file_hash</strong> (int index, sha1_hash const&amp; h);
</pre>
<p>This sets the sha1 hash for this file. This hash will end up under the key <tt class="docutils literal">sha1</tt>
associated with this file (for multi-file torrents) or in the root info dictionary
for single-file torrents.</p>
<a name="add_url_seed()"></a>
<a name="add_http_seed()"></a></div>
<div class="section" id="add-url-seed-add-http-seed">
<h2>add_url_seed() add_http_seed()</h2>
<pre class="literal-block">
void <strong>add_url_seed</strong> (std::string const&amp; url);
void <strong>add_http_seed</strong> (std::string const&amp; url);
</pre>
<p>This adds a url seed to the torrent. You can have any number of url seeds. For a
single file torrent, this should be an HTTP url, pointing to a file with identical
content as the file of the torrent. For a multi-file torrent, it should point to
a directory containing a directory with the same name as this torrent, and all the
files of the torrent in it.</p>
<p>The second function, <tt class="docutils literal">add_http_seed()</tt> adds an HTTP seed instead.</p>
<a name="add_node()"></a></div>
<div class="section" id="add-node">
<h2>add_node()</h2>
<pre class="literal-block">
void <strong>add_node</strong> (std::pair&lt;std::string, int&gt; const&amp; node);
</pre>
<p>This adds a DHT node to the torrent. This especially useful if you're creating a
tracker less torrent. It can be used by clients to bootstrap their DHT node from.
The node is a hostname and a port number where there is a DHT node running.
You can have any number of DHT nodes in a torrent.</p>
<a name="add_tracker()"></a></div>
<div class="section" id="add-tracker">
<h2>add_tracker()</h2>
<pre class="literal-block">
void <strong>add_tracker</strong> (std::string const&amp; url, int tier = 0);
</pre>
<p>Adds a tracker to the torrent. This is not strictly required, but most torrents
use a tracker as their main source of peers. The url should be an <a class="reference external" href="http://">http://</a> or udp://
url to a machine running a bittorrent tracker that accepts announces for this torrent's
info-hash. The tier is the fallback priority of the tracker. All trackers with tier 0 are
tried first (in any order). If all fail, trackers with tier 1 are tried. If all of those
fail, trackers with tier 2 are tried, and so on.</p>
<a name="set_root_cert()"></a></div>
<div class="section" id="set-root-cert">
<h2>set_root_cert()</h2>
<pre class="literal-block">
void <strong>set_root_cert</strong> (std::string const&amp; pem);
</pre>
<p>This function sets an X.509 certificate in PEM format to the torrent. This makes the
torrent an <em>SSL torrent</em>. An SSL torrent requires that each peer has a valid certificate
signed by this root certificate. For SSL torrents, all peers are connecting over SSL
connections. For more information, see the section on <a class="reference external" href="manual-ref.html#ssl-torrents">ssl torrents</a>.</p>
<p>The string is not the path to the cert, it's the actual content of the certificate,
loaded into a std::string.</p>
<a name="priv()"></a>
<a name="set_priv()"></a></div>
<div class="section" id="priv-set-priv">
<h2>priv() set_priv()</h2>
<pre class="literal-block">
bool <strong>priv</strong> () const;
void <strong>set_priv</strong> (bool p);
</pre>
<p>Sets and queries the private flag of the torrent.
Torrents with the private flag set ask clients to not use any other
sources than the tracker for peers, and to not advertize itself publicly,
apart from the tracker.</p>
<a name="num_pieces()"></a></div>
<div class="section" id="num-pieces">
<h2>num_pieces()</h2>
<pre class="literal-block">
int <strong>num_pieces</strong> () const;
</pre>
<p>returns the number of pieces in the associated <a class="reference external" href="reference-Storage.html#file_storage">file_storage</a> object.</p>
<a name="piece_length()"></a>
<a name="piece_size()"></a></div>
<div class="section" id="piece-length-piece-size">
<h2>piece_length() piece_size()</h2>
<pre class="literal-block">
int <strong>piece_length</strong> () const;
int <strong>piece_size</strong> (int i) const;
</pre>
<p><tt class="docutils literal">piece_length()</tt> returns the piece size of all pieces but the
last one. <tt class="docutils literal">piece_size()</tt> returns the size of the specified piece.
these functions are just forwarding to the associated <a class="reference external" href="reference-Storage.html#file_storage">file_storage</a>.</p>
<a name="merkle_tree()"></a></div>
<div class="section" id="merkle-tree">
<h2>merkle_tree()</h2>
<pre class="literal-block">
std::vector&lt;sha1_hash&gt; const&amp; <strong>merkle_tree</strong> () const;
</pre>
<p>This function returns the merkle hash tree, if the torrent was created as a merkle
torrent. The tree is created by <tt class="docutils literal">generate()</tt> and won't be valid until that function
has been called. When creating a merkle tree torrent, the actual tree itself has to
be saved off separately and fed into libtorrent the first time you start seeding it,
through the <tt class="docutils literal"><span class="pre">torrent_info::set_merkle_tree()</span></tt> function. From that point onwards, the
tree will be saved in the resume data.</p>
<a name="flags_t"></a></div>
<div class="section" id="enum-flags-t">
<h2>enum flags_t</h2>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/create_torrent.hpp">libtorrent/create_torrent.hpp</a>&quot;</p>
<table border="1" class="docutils">
<colgroup>
<col width="21%" />
<col width="6%" />
<col width="72%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">name</th>
<th class="head">value</th>
<th class="head">description</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>optimize</td>
<td>1</td>
<td>This will insert pad files to align the files to piece boundaries, for
optimized disk-I/O.</td>
</tr>
<tr><td>merkle</td>
<td>2</td>
<td>This will create a merkle hash tree torrent. A merkle torrent cannot
be opened in clients that don't specifically support merkle torrents.
The benefit is that the resulting torrent file will be much smaller and
not grow with more pieces. When this option is specified, it is
recommended to have a fairly small piece size, say 64 kiB.
When creating merkle torrents, the full hash tree is also generated
and should be saved off separately. It is accessed through the
<a class="reference external" href="reference-Create_Torrents.html#merkle_tree()">create_torrent::merkle_tree()</a> function.</td>
</tr>
<tr><td>modification_time</td>
<td>4</td>
<td>This will include the file modification time as part of the torrent.
This is not enabled by default, as it might cause problems when you
create a torrent from separate files with the same content, hoping to
yield the same info-hash. If the files have different modification times,
with this option enabled, you would get different info-hashes for the
files.</td>
</tr>
<tr><td>symlinks</td>
<td>8</td>
<td>If this flag is set, files that are symlinks get a symlink attribute
set on them and their data will not be included in the torrent. This
is useful if you need to reconstruct a file hierarchy which contains
symlinks.</td>
</tr>
<tr><td>calculate_file_hashes</td>
<td>16</td>
<td>If this is set, the <a class="reference external" href="reference-Create_Torrents.html#set_piece_hashes()">set_piece_hashes()</a> function will, as it calculates
the piece hashes, also calculate the file hashes and add those associated
with each file. Note that unless you use the <a class="reference external" href="reference-Create_Torrents.html#set_piece_hashes()">set_piece_hashes()</a> function,
this flag will have no effect.</td>
</tr>
</tbody>
</table>
<a name="add_files()"></a></div>
<div class="section" id="add-files">
<h2>add_files()</h2>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/create_torrent.hpp">libtorrent/create_torrent.hpp</a>&quot;</p>
<pre class="literal-block">
template &lt;class Pred&gt; void <strong>add_files</strong> (file_storage&amp; fs, std::string const&amp; file, Pred p, boost::uint32_t flags = 0);
inline void <strong>add_files</strong> (file_storage&amp; fs, std::string const&amp; file, boost::uint32_t flags = 0);
</pre>
<p>Adds the file specified by <tt class="docutils literal">path</tt> to the <a class="reference external" href="reference-Storage.html#file_storage">file_storage</a> object. In case <tt class="docutils literal">path</tt>
refers to a diretory, files will be added recursively from the directory.</p>
<p>If specified, the predicate <tt class="docutils literal">p</tt> is called once for every file and directory that
is encountered. files for which <tt class="docutils literal">p</tt> returns true are added, and directories for
which <tt class="docutils literal">p</tt> returns true are traversed. <tt class="docutils literal">p</tt> must have the following signature:</p>
<pre class="literal-block">
bool Pred(std::string const&amp; p);
</pre>
<p>The path that is passed in to the predicate is the full path of the file or
directory. If no predicate is specified, all files are added, and all directories
are traveresed.</p>
<p>The &quot;..&quot; directory is never traversed.</p>
<p>The <tt class="docutils literal">flags</tt> argument should be the same as the flags passed to the <a class="reference internal" href="#create-torrent">create_torrent</a>
constructor.</p>
<a name="set_piece_hashes()"></a></div>
<div class="section" id="set-piece-hashes">
<h2>set_piece_hashes()</h2>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/create_torrent.hpp">libtorrent/create_torrent.hpp</a>&quot;</p>
<pre class="literal-block">
void <strong>set_piece_hashes</strong> (create_torrent&amp; t, std::string const&amp; p
, boost::function&lt;void(int)&gt; f, error_code&amp; ec);
inline void <strong>set_piece_hashes</strong> (create_torrent&amp; t, std::string const&amp; p);
inline void <strong>set_piece_hashes</strong> (create_torrent&amp; t, std::string const&amp; p, error_code&amp; ec);
</pre>
<p>This function will assume that the files added to the torrent file exists at path
<tt class="docutils literal">p</tt>, read those files and hash the content and set the hashes in the <tt class="docutils literal">create_torrent</tt>
object. The optional function <tt class="docutils literal">f</tt> is called in between every hash that is set. <tt class="docutils literal">f</tt>
must have the following signature:</p>
<pre class="literal-block">
void Fun(int);
</pre>
<p>The overloads that don't take an <tt class="docutils literal">error_code&amp;</tt> may throw an exception in case of a
file error, the other overloads sets the error code to reflect the error, if any.</p>
</div>
</div>
</div>
</body>
</html>

View File

@ -1,621 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.11: http://docutils.sourceforge.net/" />
<title>Custom Storage</title>
<meta name="author" content="Arvid Norberg, arvid&#64;rasterbar.com" />
<link rel="stylesheet" type="text/css" href="../../css/base.css" />
<link rel="stylesheet" type="text/css" href="../../css/rst.css" />
<script type="text/javascript">
/* <![CDATA[ */
(function() {
var s = document.createElement('script'), t = document.getElementsByTagName('script')[0];
s.type = 'text/javascript';
s.async = true;
s.src = 'http://api.flattr.com/js/0.6/load.js?mode=auto';
t.parentNode.insertBefore(s, t);
})();
/* ]]> */
</script>
<link rel="stylesheet" href="style.css" type="text/css" />
<style type="text/css">
/* Hides from IE-mac \*/
* html pre { height: 1%; }
/* End hide from IE-mac */
</style>
</head>
<body>
<div class="document" id="custom-storage">
<div id="container">
<div id="headerNav">
<ul>
<li class="first"><a href="/">Home</a></li>
<li><a href="../../products.html">Products</a></li>
<li><a href="../../contact.html">Contact</a></li>
</ul>
</div>
<div id="header">
<div id="orange"></div>
<div id="logo"></div>
</div>
<div id="main">
<h1 class="title">Custom Storage</h1>
<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<tr><th class="docinfo-name">Author:</th>
<td>Arvid Norberg, <a class="last reference external" href="mailto:arvid&#64;rasterbar.com">arvid&#64;rasterbar.com</a></td></tr>
<tr><th class="docinfo-name">Version:</th>
<td>1.0.0</td></tr>
</tbody>
</table>
<div class="contents topic" id="table-of-contents">
<p class="topic-title first">Table of contents</p>
<ul class="simple">
<li><a class="reference internal" href="#file-pool" id="id22">file_pool</a></li>
<li><a class="reference internal" href="#storage-interface" id="id23">storage_interface</a></li>
<li><a class="reference internal" href="#default-storage" id="id24">default_storage</a></li>
</ul>
</div>
<p>libtorrent provides a customization point for storage of data. By default,
(<tt class="docutils literal">default_storage</tt>) downloaded files are saved to disk according with the
general conventions of bittorrent clients, mimicing the original file layout
when the torrent was created. The libtorrent user may define a custom
storage to store piece data in a different way.</p>
<p>A custom storage implementation must derive from and implement the
<a class="reference external" href="reference-Custom_Storage.html#storage_interface">storage_interface</a>. You must also provide a function that constructs the
custom storage object and provide this function to the <a class="reference external" href="reference-Session.html#add_torrent()">add_torrent()</a> call
via <a class="reference external" href="reference-Session.html#add_torrent_params">add_torrent_params</a>. Either passed in to the constructor or by setting
the <a class="reference external" href="reference-Session.html#storage">add_torrent_params::storage</a> field.</p>
<p>This is an example storage implementation that stores all pieces in a
<tt class="docutils literal"><span class="pre">std::map</span></tt>, i.e. in RAM. It's not necessarily very useful in practice, but
illustrates the basics of implementing a custom storage.</p>
<pre class="literal-block">
struct temp_storage : storage_interface
{
temp_storage(file_storage const&amp; fs) : m_files(fs) {}
void set_file_priority(std::vector&lt;boost::uint8_t&gt; const&amp; prio) {}
virtual bool initialize(bool allocate_files) { return false; }
virtual bool has_any_file() { return false; }
virtual int read(char* buf, int slot, int offset, int size)
{
std::map&lt;int, std::vector&lt;char&gt; &gt;::const_iterator i = m_file_data.find(slot);
if (i == m_file_data.end()) return 0;
int available = i-&gt;second.size() - offset;
if (available &lt;= 0) return 0;
if (available &gt; size) available = size;
memcpy(buf, &amp;i-&gt;second[offset], available);
return available;
}
virtual int write(const char* buf, int slot, int offset, int size)
{
std::vector&lt;char&gt;&amp; data = m_file_data[slot];
if (data.size() &lt; offset + size) data.resize(offset + size);
std::memcpy(&amp;data[offset], buf, size);
return size;
}
virtual bool rename_file(int file, std::string const&amp; new_name)
{ assert(false); return false; }
virtual bool move_storage(std::string const&amp; save_path) { return false; }
virtual bool verify_resume_data(lazy_entry const&amp; rd, error_code&amp; error) { return false; }
virtual bool write_resume_data(entry&amp; rd) const { return false; }
virtual bool move_slot(int src_slot, int dst_slot) { assert(false); return false; }
virtual bool swap_slots(int slot1, int slot2) { assert(false); return false; }
virtual bool swap_slots3(int slot1, int slot2, int slot3) { assert(false); return false; }
virtual size_type physical_offset(int slot, int offset)
{ return slot * m_files.piece_length() + offset; };
virtual sha1_hash hash_for_slot(int slot, partial_hash&amp; ph, int piece_size)
{
int left = piece_size - ph.offset;
assert(left &gt;= 0);
if (left &gt; 0)
{
std::vector&lt;char&gt;&amp; data = m_file_data[slot];
// if there are padding files, those blocks will be considered
// completed even though they haven't been written to the storage.
// in this case, just extend the piece buffer to its full size
// and fill it with zeroes.
if (data.size() &lt; piece_size) data.resize(piece_size, 0);
ph.h.update(&amp;data[ph.offset], left);
}
return ph.h.final();
}
virtual bool release_files() { return false; }
virtual bool delete_files() { return false; }
std::map&lt;int, std::vector&lt;char&gt; &gt; m_file_data;
file_storage m_files;
};
storage_interface* temp_storage_constructor(
file_storage const&amp; fs, file_storage const* mapped
, std::string const&amp; path, file_pool&amp; fp
, std::vector&lt;boost::uint8_t&gt; const&amp; prio)
{
return new temp_storage(fs);
}
</pre>
<a name="file_pool"></a><div class="section" id="file-pool">
<h1>file_pool</h1>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/file_pool.hpp">libtorrent/file_pool.hpp</a>&quot;</p>
<p>this is an internal cache of open file handles. It's primarily used by
<a class="reference external" href="reference-Custom_Storage.html#storage_interface">storage_interface</a> implementations. It provides semi weak guarantees of
not opening more file handles than specified. Given multiple threads,
each with the ability to lock a file handle (via smart pointer), there
may be windows where more file handles are open.</p>
<pre class="literal-block">
struct file_pool : boost::noncopyable
{
<strong>~file_pool</strong> ();
<strong>file_pool</strong> (int size = 40);
boost::intrusive_ptr&lt;file&gt; <strong>open_file</strong> (void* st, std::string const&amp; p
, int file_index, file_storage const&amp; fs, int m, error_code&amp; ec);
void <strong>release</strong> (void* st);
void <strong>release</strong> (void* st, int file_index);
void <strong>resize</strong> (int size);
int <strong>size_limit</strong> () const;
};
</pre>
<a name="~file_pool()"></a>
<a name="file_pool()"></a><div class="section" id="file-pool-file-pool">
<h2>~file_pool() file_pool()</h2>
<pre class="literal-block">
<strong>~file_pool</strong> ();
<strong>file_pool</strong> (int size = 40);
</pre>
<p><tt class="docutils literal">size</tt> specifies the number of allowed files handles
to hold open at any given time.</p>
<a name="open_file()"></a></div>
<div class="section" id="open-file">
<h2>open_file()</h2>
<pre class="literal-block">
boost::intrusive_ptr&lt;file&gt; <strong>open_file</strong> (void* st, std::string const&amp; p
, int file_index, file_storage const&amp; fs, int m, error_code&amp; ec);
</pre>
<p>return an open file handle to file at <tt class="docutils literal">file_index</tt> in the
<a class="reference external" href="reference-Storage.html#file_storage">file_storage</a> <tt class="docutils literal">fs</tt> opened at save path <tt class="docutils literal">p</tt>. <tt class="docutils literal">m</tt> is the
file open mode (see <a class="reference external" href="file::open_mode_t">file::open_mode_t</a>).</p>
<a name="release()"></a></div>
<div class="section" id="release">
<h2>release()</h2>
<pre class="literal-block">
void <strong>release</strong> (void* st);
void <strong>release</strong> (void* st, int file_index);
</pre>
<p>release all files belonging to the specified <a class="reference external" href="reference-Custom_Storage.html#storage_interface">storage_interface</a> (<tt class="docutils literal">st</tt>)
the overload that takes <tt class="docutils literal">file_index</tt> releases only the file with
that index in storage <tt class="docutils literal">st</tt>.</p>
<a name="resize()"></a></div>
<div class="section" id="resize">
<h2>resize()</h2>
<pre class="literal-block">
void <strong>resize</strong> (int size);
</pre>
<p>update the allowed number of open file handles to <tt class="docutils literal">size</tt>.</p>
<a name="size_limit()"></a></div>
<div class="section" id="size-limit">
<h2>size_limit()</h2>
<pre class="literal-block">
int <strong>size_limit</strong> () const;
</pre>
<p>returns the current limit of number of allowed open file handles held
by the <a class="reference external" href="reference-Custom_Storage.html#file_pool">file_pool</a>.</p>
<a name="storage_interface"></a></div>
</div>
<div class="section" id="storage-interface">
<h1>storage_interface</h1>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/storage.hpp">libtorrent/storage.hpp</a>&quot;</p>
<p>The storage interface is a pure virtual class that can be implemented to
customize how and where data for a torrent is stored. The default storage
implementation uses regular files in the filesystem, mapping the files in
the torrent in the way one would assume a torrent is saved to disk.
Implementing your own storage interface makes it possible to store all
data in RAM, or in some optimized order on disk (the order the pieces are
received for instance), or saving multifile torrents in a single file in
order to be able to take advantage of optimized disk-I/O.</p>
<p>It is also possible to write a thin class that uses the default storage
but modifies some particular behavior, for instance encrypting the data
before it's written to disk, and decrypting it when it's read again.</p>
<p>The storage interface is based on slots, each slot is 'piece_size' number
of bytes. All access is done by writing and reading whole or partial
slots. One slot is one piece in the torrent, but the data in the slot
does not necessarily correspond to the piece with the same index (in
compact allocation mode it won't).</p>
<p>libtorrent comes with two built-in storage implementations;
<tt class="docutils literal">default_storage</tt> and <tt class="docutils literal">disabled_storage</tt>. Their constructor functions
are called <a class="reference external" href="reference-Storage.html#default_storage_constructor()">default_storage_constructor()</a> and
<tt class="docutils literal">disabled_storage_constructor</tt> respectively. The disabled storage does
just what it sounds like. It throws away data that's written, and it
reads garbage. It's useful mostly for benchmarking and profiling purpose.</p>
<pre class="literal-block">
struct storage_interface
{
virtual bool <strong>initialize</strong> (bool allocate_files) = 0;
virtual bool <strong>has_any_file</strong> () = 0;
virtual void <strong>set_file_priority</strong> (std::vector&lt;boost::uint8_t&gt; const&amp; prio) = 0;
virtual int <strong>writev</strong> (<a class="reference external" href="file::iovec_t">file::iovec_t</a> const* bufs, int slot, int offset, int num_bufs, int flags = <a class="reference external" href="file::random_access">file::random_access</a>);
virtual int <strong>readv</strong> (<a class="reference external" href="file::iovec_t">file::iovec_t</a> const* bufs, int slot, int offset, int num_bufs, int flags = <a class="reference external" href="file::random_access">file::random_access</a>);
virtual void <strong>hint_read</strong> (int, int, int);
virtual int <strong>read</strong> (char* buf, int slot, int offset, int size) = 0;
virtual int <strong>write</strong> (const char* buf, int slot, int offset, int size) = 0;
virtual size_type <strong>physical_offset</strong> (int slot, int offset) = 0;
virtual int <strong>sparse_end</strong> (int start) const;
virtual int <strong>move_storage</strong> (std::string const&amp; save_path, int flags) = 0;
virtual bool <strong>verify_resume_data</strong> (lazy_entry const&amp; rd, error_code&amp; error) = 0;
virtual bool <strong>write_resume_data</strong> (entry&amp; rd) const = 0;
virtual bool <strong>move_slot</strong> (int src_slot, int dst_slot) = 0;
virtual bool <strong>swap_slots</strong> (int slot1, int slot2) = 0;
virtual bool <strong>swap_slots3</strong> (int slot1, int slot2, int slot3) = 0;
virtual bool <strong>release_files</strong> () = 0;
virtual bool <strong>rename_file</strong> (int index, std::string const&amp; new_filename) = 0;
virtual bool <strong>delete_files</strong> () = 0;
disk_buffer_pool* <strong>disk_pool</strong> ();
session_settings const&amp; <strong>settings</strong> () const;
void <strong>set_error</strong> (std::string const&amp; file, error_code const&amp; ec) const;
error_code const&amp; <strong>error</strong> () const;
std::string const&amp; <strong>error_file</strong> () const;
virtual void <strong>clear_error</strong> ();
};
</pre>
<a name="initialize()"></a><div class="section" id="initialize">
<h2>initialize()</h2>
<pre class="literal-block">
virtual bool <strong>initialize</strong> (bool allocate_files) = 0;
</pre>
<p>This function is called when the storage is to be initialized. The
default storage will create directories and empty files at this point.
If <tt class="docutils literal">allocate_files</tt> is true, it will also <tt class="docutils literal">ftruncate</tt> all files to
their target size.</p>
<p>Returning <tt class="docutils literal">true</tt> indicates an error occurred.</p>
<a name="has_any_file()"></a></div>
<div class="section" id="has-any-file">
<h2>has_any_file()</h2>
<pre class="literal-block">
virtual bool <strong>has_any_file</strong> () = 0;
</pre>
<p>This function is called when first checking (or re-checking) the
storage for a torrent. It should return true if any of the files that
is used in this storage exists on disk. If so, the storage will be
checked for existing pieces before starting the download.</p>
<a name="set_file_priority()"></a></div>
<div class="section" id="set-file-priority">
<h2>set_file_priority()</h2>
<pre class="literal-block">
virtual void <strong>set_file_priority</strong> (std::vector&lt;boost::uint8_t&gt; const&amp; prio) = 0;
</pre>
<p>change the priorities of files.</p>
<a name="writev()"></a>
<a name="readv()"></a></div>
<div class="section" id="writev-readv">
<h2>writev() readv()</h2>
<pre class="literal-block">
virtual int <strong>writev</strong> (<a class="reference external" href="file::iovec_t">file::iovec_t</a> const* bufs, int slot, int offset, int num_bufs, int flags = <a class="reference external" href="file::random_access">file::random_access</a>);
virtual int <strong>readv</strong> (<a class="reference external" href="file::iovec_t">file::iovec_t</a> const* bufs, int slot, int offset, int num_bufs, int flags = <a class="reference external" href="file::random_access">file::random_access</a>);
</pre>
<p>These functions should read or write the data in or to the given
<tt class="docutils literal">slot</tt> at the given <tt class="docutils literal">offset</tt>. It should read or write <tt class="docutils literal">num_bufs</tt>
buffers sequentially, where the size of each buffer is specified in
the buffer array <tt class="docutils literal">bufs</tt>. The <a class="reference external" href="file::iovec_t">file::iovec_t</a> type has the following
members:</p>
<pre class="literal-block">
struct iovec_t { void* iov_base; size_t iov_len; };
</pre>
<p>The return value is the number of bytes actually read or written, or
-1 on failure. If it returns -1, the error code is expected to be set
to</p>
<p>Every buffer in <tt class="docutils literal">bufs</tt> can be assumed to be page aligned and be of a
page aligned size, except for the last buffer of the torrent. The
allocated buffer can be assumed to fit a fully page aligned number of
bytes though. This is useful when reading and writing the last piece
of a file in unbuffered mode.</p>
<p>The <tt class="docutils literal">offset</tt> is aligned to 16 kiB boundries <em>most of the time</em>, but
there are rare exceptions when it's not. Specifically if the read
cache is disabled/or full and a client requests unaligned data, or the
file itself is not aligned in the torrent. Most clients request
aligned data.</p>
<a name="hint_read()"></a></div>
<div class="section" id="hint-read">
<h2>hint_read()</h2>
<pre class="literal-block">
virtual void <strong>hint_read</strong> (int, int, int);
</pre>
<p>This function is called when a read job is queued. It gives the
storage wrapper an opportunity to hint the operating system about this
coming read. For instance, the storage may call
<tt class="docutils literal">posix_fadvise(POSIX_FADV_WILLNEED)</tt> or <tt class="docutils literal">fcntl(F_RDADVISE)</tt>.</p>
<a name="read()"></a></div>
<div class="section" id="read">
<h2>read()</h2>
<pre class="literal-block">
virtual int <strong>read</strong> (char* buf, int slot, int offset, int size) = 0;
</pre>
<p>negative return value indicates an error</p>
<a name="write()"></a></div>
<div class="section" id="write">
<h2>write()</h2>
<pre class="literal-block">
virtual int <strong>write</strong> (const char* buf, int slot, int offset, int size) = 0;
</pre>
<p>negative return value indicates an error</p>
<a name="physical_offset()"></a></div>
<div class="section" id="physical-offset">
<h2>physical_offset()</h2>
<pre class="literal-block">
virtual size_type <strong>physical_offset</strong> (int slot, int offset) = 0;
</pre>
<p>returns the offset on the physical storage medium for the
byte at offset <tt class="docutils literal">offset</tt> in slot <tt class="docutils literal">slot</tt>.</p>
<a name="sparse_end()"></a></div>
<div class="section" id="sparse-end">
<h2>sparse_end()</h2>
<pre class="literal-block">
virtual int <strong>sparse_end</strong> (int start) const;
</pre>
<p>This function is optional. It is supposed to return the first piece,
starting at <tt class="docutils literal">start</tt> that is fully contained within a data-region on
disk (i.e. non-sparse region). The purpose of this is to skip parts of
files that can be known to contain zeros when checking files.</p>
<a name="move_storage()"></a></div>
<div class="section" id="move-storage">
<h2>move_storage()</h2>
<pre class="literal-block">
virtual int <strong>move_storage</strong> (std::string const&amp; save_path, int flags) = 0;
</pre>
<p>This function should move all the files belonging to the storage to
the new save_path. The default storage moves the single file or the
directory of the torrent.</p>
<p>Before moving the files, any open file handles may have to be closed,
like <tt class="docutils literal">release_files()</tt>.</p>
<p>returns one of:
| no_error = 0
| need_full_check = -1
| fatal_disk_error = -2
| file_exist = -4</p>
<a name="verify_resume_data()"></a></div>
<div class="section" id="verify-resume-data">
<h2>verify_resume_data()</h2>
<pre class="literal-block">
virtual bool <strong>verify_resume_data</strong> (lazy_entry const&amp; rd, error_code&amp; error) = 0;
</pre>
<p>This function should verify the resume data <tt class="docutils literal">rd</tt> with the files
on disk. If the resume data seems to be up-to-date, return true. If
not, set <tt class="docutils literal">error</tt> to a description of what mismatched and return false.</p>
<p>The default storage may compare file sizes and time stamps of the files.</p>
<p>Returning <tt class="docutils literal">false</tt> indicates an error occurred.</p>
<a name="write_resume_data()"></a></div>
<div class="section" id="write-resume-data">
<h2>write_resume_data()</h2>
<pre class="literal-block">
virtual bool <strong>write_resume_data</strong> (entry&amp; rd) const = 0;
</pre>
<p>This function should fill in resume data, the current state of the
storage, in <tt class="docutils literal">rd</tt>. The default storage adds file timestamps and
sizes.</p>
<p>Returning <tt class="docutils literal">true</tt> indicates an error occurred.</p>
<a name="move_slot()"></a></div>
<div class="section" id="move-slot">
<h2>move_slot()</h2>
<pre class="literal-block">
virtual bool <strong>move_slot</strong> (int src_slot, int dst_slot) = 0;
</pre>
<p>This function should copy or move the data in slot <tt class="docutils literal">src_slot</tt> to
the slot <tt class="docutils literal">dst_slot</tt>. This is only used in compact mode.</p>
<p>If the storage caches slots, this could be implemented more
efficient than reading and writing the data.</p>
<p>Returning <tt class="docutils literal">true</tt> indicates an error occurred.</p>
<a name="swap_slots()"></a></div>
<div class="section" id="swap-slots">
<h2>swap_slots()</h2>
<pre class="literal-block">
virtual bool <strong>swap_slots</strong> (int slot1, int slot2) = 0;
</pre>
<p>This function should swap the data in <tt class="docutils literal">slot1</tt> and <tt class="docutils literal">slot2</tt>. The
default storage uses a scratch buffer to read the data into, then
moving the other slot and finally writing back the temporary slot's
data</p>
<p>This is only used in compact mode.</p>
<p>Returning <tt class="docutils literal">true</tt> indicates an error occurred.</p>
<a name="swap_slots3()"></a></div>
<div class="section" id="swap-slots3">
<h2>swap_slots3()</h2>
<pre class="literal-block">
virtual bool <strong>swap_slots3</strong> (int slot1, int slot2, int slot3) = 0;
</pre>
<p>This function should do a 3-way swap, or shift of the slots. <tt class="docutils literal">slot1</tt>
should move to <tt class="docutils literal">slot2</tt>, which should be moved to <tt class="docutils literal">slot3</tt> which in
turn should be moved to <tt class="docutils literal">slot1</tt>.</p>
<p>This is only used in compact mode.</p>
<p>Returning <tt class="docutils literal">true</tt> indicates an error occurred.</p>
<a name="release_files()"></a></div>
<div class="section" id="release-files">
<h2>release_files()</h2>
<pre class="literal-block">
virtual bool <strong>release_files</strong> () = 0;
</pre>
<p>This function should release all the file handles that it keeps open to files
belonging to this storage. The default implementation just calls
<tt class="docutils literal"><span class="pre">file_pool::release_files(this)</span></tt>.</p>
<p>Returning <tt class="docutils literal">true</tt> indicates an error occurred.</p>
<a name="rename_file()"></a></div>
<div class="section" id="rename-file">
<h2>rename_file()</h2>
<pre class="literal-block">
virtual bool <strong>rename_file</strong> (int index, std::string const&amp; new_filename) = 0;
</pre>
<p>Rename file with index <tt class="docutils literal">file</tt> to the thame <tt class="docutils literal">new_name</tt>. If there is an error,
<tt class="docutils literal">true</tt> should be returned.</p>
<a name="delete_files()"></a></div>
<div class="section" id="delete-files">
<h2>delete_files()</h2>
<pre class="literal-block">
virtual bool <strong>delete_files</strong> () = 0;
</pre>
<p>This function should delete all files and directories belonging to
this storage.</p>
<p>Returning <tt class="docutils literal">true</tt> indicates an error occurred.</p>
<p>The <tt class="docutils literal">disk_buffer_pool</tt> is used to allocate and free disk buffers. It
has the following members:</p>
<pre class="literal-block">
struct disk_buffer_pool : boost::noncopyable
{
char* allocate_buffer(char const* category);
void free_buffer(char* buf);
char* allocate_buffers(int blocks, char const* category);
void free_buffers(char* buf, int blocks);
int block_size() const { return m_block_size; }
void release_memory();
};
</pre>
<a name="disk_pool()"></a></div>
<div class="section" id="disk-pool">
<h2>disk_pool()</h2>
<pre class="literal-block">
disk_buffer_pool* <strong>disk_pool</strong> ();
</pre>
<p>access global disk_buffer_pool, for allocating and freeing disk buffers</p>
<a name="settings()"></a></div>
<div class="section" id="settings">
<h2>settings()</h2>
<pre class="literal-block">
session_settings const&amp; <strong>settings</strong> () const;
</pre>
<p>access global <a class="reference external" href="reference-Settings.html#session_settings">session_settings</a></p>
<a name="set_error()"></a></div>
<div class="section" id="set-error">
<h2>set_error()</h2>
<pre class="literal-block">
void <strong>set_error</strong> (std::string const&amp; file, error_code const&amp; ec) const;
</pre>
<p>called by the storage implementation to set it into an
error state. Typically whenever a critical file operation
fails.</p>
<a name="error_file()"></a>
<a name="error()"></a></div>
<div class="section" id="error-file-error">
<h2>error_file() error()</h2>
<pre class="literal-block">
error_code const&amp; <strong>error</strong> () const;
std::string const&amp; <strong>error_file</strong> () const;
</pre>
<p>returns the currently set error code and file path associated with it,
if set.</p>
<a name="clear_error()"></a></div>
<div class="section" id="clear-error">
<h2>clear_error()</h2>
<pre class="literal-block">
virtual void <strong>clear_error</strong> ();
</pre>
<p>reset the error state to allow continuing reading and writing
to the storage</p>
<a name="default_storage"></a></div>
</div>
<div class="section" id="default-storage">
<h1>default_storage</h1>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/storage.hpp">libtorrent/storage.hpp</a>&quot;</p>
<p>The default implementation of <a class="reference external" href="reference-Custom_Storage.html#storage_interface">storage_interface</a>. Behaves as a normal
bittorrent client. It is possible to derive from this class in order to
override some of its behavior, when implementing a custom storage.</p>
<pre class="literal-block">
class default_storage : public storage_interface, boost::noncopyable
{
<strong>default_storage</strong> (file_storage const&amp; fs, file_storage const* mapped
, std::string const&amp; path, file_pool&amp; fp
, std::vector&lt;boost::uint8_t&gt; const&amp; file_prio);
bool <strong>move_slot</strong> (int src_slot, int dst_slot);
void <strong>hint_read</strong> (int slot, int offset, int len);
bool <strong>rename_file</strong> (int index, std::string const&amp; new_filename);
void <strong>set_file_priority</strong> (std::vector&lt;boost::uint8_t&gt; const&amp; prio);
bool <strong>has_any_file</strong> ();
int <strong>move_storage</strong> (std::string const&amp; save_path, int flags);
bool <strong>write_resume_data</strong> (entry&amp; rd) const;
int <strong>write</strong> (char const* buf, int slot, int offset, int size);
int <strong>writev</strong> (<a class="reference external" href="file::iovec_t">file::iovec_t</a> const* buf, int slot, int offset, int num_bufs, int flags = <a class="reference external" href="file::random_access">file::random_access</a>);
size_type <strong>physical_offset</strong> (int slot, int offset);
bool <strong>release_files</strong> ();
bool <strong>delete_files</strong> ();
bool <strong>verify_resume_data</strong> (lazy_entry const&amp; rd, error_code&amp; error);
int <strong>readv</strong> (<a class="reference external" href="file::iovec_t">file::iovec_t</a> const* bufs, int slot, int offset, int num_bufs, int flags = <a class="reference external" href="file::random_access">file::random_access</a>);
bool <strong>swap_slots3</strong> (int slot1, int slot2, int slot3);
bool <strong>initialize</strong> (bool allocate_files);
int <strong>read</strong> (char* buf, int slot, int offset, int size);
bool <strong>swap_slots</strong> (int slot1, int slot2);
int <strong>sparse_end</strong> (int start) const;
file_storage const&amp; <strong>files</strong> () const;
};
</pre>
<a name="default_storage()"></a><div class="section" id="id15">
<h2>default_storage()</h2>
<pre class="literal-block">
<strong>default_storage</strong> (file_storage const&amp; fs, file_storage const* mapped
, std::string const&amp; path, file_pool&amp; fp
, std::vector&lt;boost::uint8_t&gt; const&amp; file_prio);
</pre>
<p>constructs the <a class="reference external" href="reference-Custom_Storage.html#default_storage">default_storage</a> based on the give <a class="reference external" href="reference-Storage.html#file_storage">file_storage</a> (fs).
<tt class="docutils literal">mapped</tt> is an optional argument (it may be NULL). If non-NULL it
represents the file mappsing that have been made to the torrent before
adding it. That's where files are supposed to be saved and looked for
on disk. <tt class="docutils literal">save_path</tt> is the root save folder for this torrent.
<tt class="docutils literal">file_pool</tt> is the cache of file handles that the storage will use.
All files it opens will ask the <a class="reference external" href="reference-Custom_Storage.html#file_pool">file_pool</a> to open them. <tt class="docutils literal">file_prio</tt>
is a vector indicating the priority of files on startup. It may be
an empty vector. Any file whose index is not represented by the vector
(because the vector is too short) are assumed to have priority 1.
this is used to treat files with priority 0 slightly differently.</p>
<a name="files()"></a></div>
<div class="section" id="files">
<h2>files()</h2>
<pre class="literal-block">
file_storage const&amp; <strong>files</strong> () const;
</pre>
<p>if the files in this storage are mapped, returns the mapped
<a class="reference external" href="reference-Storage.html#file_storage">file_storage</a>, otherwise returns the original <a class="reference external" href="reference-Storage.html#file_storage">file_storage</a> object.</p>
<a name="move_flags_t"></a></div>
<div class="section" id="enum-move-flags-t">
<h2>enum move_flags_t</h2>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/storage.hpp">libtorrent/storage.hpp</a>&quot;</p>
<table border="1" class="docutils">
<colgroup>
<col width="25%" />
<col width="8%" />
<col width="67%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">name</th>
<th class="head">value</th>
<th class="head">description</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>always_replace_files</td>
<td>0</td>
<td>replace any files in the destination when copying
or moving the storage</td>
</tr>
<tr><td>fail_if_exist</td>
<td>1</td>
<td>if any files that we want to copy exist in the destination
exist, fail the whole operation and don't perform
any copy or move. There is an inherent race condition
in this mode. The files are checked for existence before
the operation starts. In between the check and performing
the copy, the destination files may be created, in which
case they are replaced.</td>
</tr>
<tr><td>dont_replace</td>
<td>2</td>
<td>if any file exist in the target, take those files instead
of the ones we may have in the source.</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@ -1,211 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.11: http://docutils.sourceforge.net/" />
<title>Filter</title>
<meta name="author" content="Arvid Norberg, arvid&#64;rasterbar.com" />
<link rel="stylesheet" type="text/css" href="../../css/base.css" />
<link rel="stylesheet" type="text/css" href="../../css/rst.css" />
<script type="text/javascript">
/* <![CDATA[ */
(function() {
var s = document.createElement('script'), t = document.getElementsByTagName('script')[0];
s.type = 'text/javascript';
s.async = true;
s.src = 'http://api.flattr.com/js/0.6/load.js?mode=auto';
t.parentNode.insertBefore(s, t);
})();
/* ]]> */
</script>
<link rel="stylesheet" href="style.css" type="text/css" />
<style type="text/css">
/* Hides from IE-mac \*/
* html pre { height: 1%; }
/* End hide from IE-mac */
</style>
</head>
<body>
<div class="document" id="filter">
<div id="container">
<div id="headerNav">
<ul>
<li class="first"><a href="/">Home</a></li>
<li><a href="../../products.html">Products</a></li>
<li><a href="../../contact.html">Contact</a></li>
</ul>
</div>
<div id="header">
<div id="orange"></div>
<div id="logo"></div>
</div>
<div id="main">
<h1 class="title">Filter</h1>
<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<tr><th class="docinfo-name">Author:</th>
<td>Arvid Norberg, <a class="last reference external" href="mailto:arvid&#64;rasterbar.com">arvid&#64;rasterbar.com</a></td></tr>
<tr><th class="docinfo-name">Version:</th>
<td>1.0.0</td></tr>
</tbody>
</table>
<div class="contents topic" id="table-of-contents">
<p class="topic-title first">Table of contents</p>
<ul class="simple">
<li><a class="reference internal" href="#ip-filter" id="id10">ip_filter</a></li>
<li><a class="reference internal" href="#port-filter" id="id11">port_filter</a></li>
</ul>
</div>
<a name="ip_filter"></a><div class="section" id="ip-filter">
<h1>ip_filter</h1>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/ip_filter.hpp">libtorrent/ip_filter.hpp</a>&quot;</p>
<p>The <tt class="docutils literal">ip_filter</tt> class is a set of rules that uniquely categorizes all
ip addresses as allowed or disallowed. The default constructor creates
a single rule that allows all addresses (0.0.0.0 - 255.255.255.255 for
the IPv4 range, and the equivalent range covering all addresses for the
IPv6 range).</p>
<p>A default constructed <a class="reference external" href="reference-Filter.html#ip_filter">ip_filter</a> does not filter any address.</p>
<pre class="literal-block">
struct ip_filter
{
void <strong>add_rule</strong> (address first, address last, int flags);
int <strong>access</strong> (address const&amp; addr) const;
filter_tuple_t <strong>export_filter</strong> () const;
enum access_flags
{
blocked,
};
};
</pre>
<a name="add_rule()"></a><div class="section" id="add-rule">
<h2>add_rule()</h2>
<pre class="literal-block">
void <strong>add_rule</strong> (address first, address last, int flags);
</pre>
<p>Adds a rule to the filter. <tt class="docutils literal">first</tt> and <tt class="docutils literal">last</tt> defines a range of
ip addresses that will be marked with the given flags. The <tt class="docutils literal">flags</tt>
can currently be 0, which means allowed, or <tt class="docutils literal"><span class="pre">ip_filter::blocked</span></tt>, which
means disallowed.</p>
<p>precondition:
<tt class="docutils literal">first.is_v4() == last.is_v4() &amp;&amp; first.is_v6() == last.is_v6()</tt></p>
<p>postcondition:
<tt class="docutils literal">access(x) == flags</tt> for every <tt class="docutils literal">x</tt> in the range [<tt class="docutils literal">first</tt>, <tt class="docutils literal">last</tt>]</p>
<p>This means that in a case of overlapping ranges, the last one applied takes
precedence.</p>
<a name="access()"></a></div>
<div class="section" id="access">
<h2>access()</h2>
<pre class="literal-block">
int <strong>access</strong> (address const&amp; addr) const;
</pre>
<p>Returns the access permissions for the given address (<tt class="docutils literal">addr</tt>). The permission
can currently be 0 or <tt class="docutils literal"><span class="pre">ip_filter::blocked</span></tt>. The complexity of this operation
is O(<tt class="docutils literal">log</tt> n), where n is the minimum number of non-overlapping ranges to describe
the current filter.</p>
<a name="export_filter()"></a></div>
<div class="section" id="export-filter">
<h2>export_filter()</h2>
<pre class="literal-block">
filter_tuple_t <strong>export_filter</strong> () const;
</pre>
<p>This function will return the current state of the filter in the minimum number of
ranges possible. They are sorted from ranges in low addresses to high addresses. Each
<a class="reference external" href="reference-Bencoding.html#entry">entry</a> in the returned vector is a range with the access control specified in its
<tt class="docutils literal">flags</tt> field.</p>
<p>The return value is a tuple containing two range-lists. One for IPv4 addresses
and one for IPv6 addresses.</p>
<a name="access_flags"></a></div>
<div class="section" id="enum-access-flags">
<h2>enum access_flags</h2>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/ip_filter.hpp">libtorrent/ip_filter.hpp</a>&quot;</p>
<table border="1" class="docutils">
<colgroup>
<col width="12%" />
<col width="9%" />
<col width="78%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">name</th>
<th class="head">value</th>
<th class="head">description</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>blocked</td>
<td>1</td>
<td>indicates that IPs in this range should not be connected
to nor accepted as incoming connections</td>
</tr>
</tbody>
</table>
<a name="port_filter"></a></div>
</div>
<div class="section" id="port-filter">
<h1>port_filter</h1>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/ip_filter.hpp">libtorrent/ip_filter.hpp</a>&quot;</p>
<p>the port filter maps non-overlapping port ranges to flags. This
is primarily used to indicate whether a range of ports should
be connected to or not. The default is to have the full port
range (0-65535) set to flag 0.</p>
<pre class="literal-block">
class port_filter
{
void <strong>add_rule</strong> (boost::uint16_t first, boost::uint16_t last, int flags);
int <strong>access</strong> (boost::uint16_t port) const;
enum access_flags
{
blocked,
};
};
</pre>
<a name="add_rule()"></a><div class="section" id="id6">
<h2>add_rule()</h2>
<pre class="literal-block">
void <strong>add_rule</strong> (boost::uint16_t first, boost::uint16_t last, int flags);
</pre>
<p>set the flags for the specified port range (<tt class="docutils literal">first</tt>, <tt class="docutils literal">last</tt>) to
<tt class="docutils literal">flags</tt> overwriting any existing rule for those ports. The range
is inclusive, i.e. the port <tt class="docutils literal">last</tt> also has the flag set on it.</p>
<a name="access()"></a></div>
<div class="section" id="id7">
<h2>access()</h2>
<pre class="literal-block">
int <strong>access</strong> (boost::uint16_t port) const;
</pre>
<p>test the specified port (<tt class="docutils literal">port</tt>) for whether it is blocked
or not. The returned value is the flags set for this port.
see acces_flags.</p>
<a name="access_flags"></a></div>
<div class="section" id="id8">
<h2>enum access_flags</h2>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/ip_filter.hpp">libtorrent/ip_filter.hpp</a>&quot;</p>
<table border="1" class="docutils">
<colgroup>
<col width="13%" />
<col width="10%" />
<col width="76%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">name</th>
<th class="head">value</th>
<th class="head">description</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>blocked</td>
<td>1</td>
<td>this flag indicates that destination ports in the
range should not be connected to</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>

View File

@ -1,613 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.11: http://docutils.sourceforge.net/" />
<title></title>
<link rel="stylesheet" type="text/css" href="../../css/base.css" />
<link rel="stylesheet" type="text/css" href="../../css/rst.css" />
<script type="text/javascript">
/* <![CDATA[ */
(function() {
var s = document.createElement('script'), t = document.getElementsByTagName('script')[0];
s.type = 'text/javascript';
s.async = true;
s.src = 'http://api.flattr.com/js/0.6/load.js?mode=auto';
t.parentNode.insertBefore(s, t);
})();
/* ]]> */
</script>
<link rel="stylesheet" href="style.css" type="text/css" />
<style type="text/css">
/* Hides from IE-mac \*/
* html pre { height: 1%; }
/* End hide from IE-mac */
</style>
</head>
<body>
<div class="document">
<div id="container">
<div id="headerNav">
<ul>
<li class="first"><a href="/">Home</a></li>
<li><a href="../../products.html">Products</a></li>
<li><a href="../../contact.html">Contact</a></li>
</ul>
</div>
<div id="header">
<div id="orange"></div>
<div id="logo"></div>
</div>
<div id="main">
<div class="section" id="plugins">
<h1>Plugins</h1>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Author:</th><td class="field-body">Arvid Norberg, <a class="reference external" href="mailto:arvid&#64;rasterbar.com">arvid&#64;rasterbar.com</a></td>
</tr>
<tr class="field"><th class="field-name">Version:</th><td class="field-body">1.0.0</td>
</tr>
</tbody>
</table>
<div class="contents topic" id="table-of-contents">
<p class="topic-title first">Table of contents</p>
<ul class="simple">
<li><a class="reference internal" href="#plugins" id="id68">Plugins</a></li>
<li><a class="reference internal" href="#plugin-interface" id="id69">plugin-interface</a></li>
<li><a class="reference internal" href="#custom-alerts" id="id70">custom alerts</a></li>
</ul>
</div>
<p>libtorrent has a <a class="reference external" href="reference-Plugins.html#plugin">plugin</a> interface for implementing extensions to the protocol.
These can be general extensions for transferring metadata or peer exchange
extensions, or it could be used to provide a way to customize the protocol
to fit a particular (closed) network.</p>
<p>In short, the <a class="reference external" href="reference-Plugins.html#plugin">plugin</a> interface makes it possible to:</p>
<ul class="simple">
<li>register extension messages (sent in the extension handshake), see
<a class="reference external" href="extension_protocol.html">extensions</a>.</li>
<li>add data and parse data from the extension handshake.</li>
<li>send extension messages and standard bittorrent messages.</li>
<li>override or block the handling of standard bittorrent messages.</li>
<li>save and restore state via the <a class="reference external" href="reference-Session.html#session">session</a> state</li>
<li>see all alerts that are posted</li>
</ul>
<div class="section" id="a-word-of-caution">
<h2>a word of caution</h2>
<p>Writing your own <a class="reference external" href="reference-Plugins.html#plugin">plugin</a> is a very easy way to introduce serious bugs such as
dead locks and race conditions. Since a <a class="reference external" href="reference-Plugins.html#plugin">plugin</a> has access to internal
structures it is also quite easy to sabotage libtorrent's operation.</p>
<p>All the callbacks in this interface are called with the main libtorrent thread
mutex locked. And they are always called from the libtorrent network thread. In
case portions of your <a class="reference external" href="reference-Plugins.html#plugin">plugin</a> are called from other threads, typically the main
thread, you cannot use any of the member functions on the internal structures
in libtorrent, since those require the mutex to be locked. Futhermore, you would
also need to have a mutex on your own shared data within the <a class="reference external" href="reference-Plugins.html#plugin">plugin</a>, to make
sure it is not accessed at the same time from the libtorrent thread (through a
callback). See <a class="reference external" href="http://www.boost.org/doc/html/mutex.html">boost thread's mutex</a>. If you need to send out a message from
another thread, it is advised to use an internal queue, and do the actual
sending in <tt class="docutils literal">tick()</tt>.</p>
<p>Since the <a class="reference external" href="reference-Plugins.html#plugin">plugin</a> interface gives you easy access to internal structures, it
is not supported as a stable API. Plugins should be considered spcific to a
specific version of libtorrent. Although, in practice the internals mostly
don't change that dramatically.</p>
</div>
</div>
<div class="section" id="plugin-interface">
<h1>plugin-interface</h1>
<p>The <a class="reference external" href="reference-Plugins.html#plugin">plugin</a> interface consists of three base classes that the <a class="reference external" href="reference-Plugins.html#plugin">plugin</a> may
implement. These are called <a class="reference external" href="reference-Plugins.html#plugin">plugin</a>, <a class="reference external" href="reference-Plugins.html#torrent_plugin">torrent_plugin</a> and <a class="reference external" href="reference-Plugins.html#peer_plugin">peer_plugin</a>.
They are found in the <tt class="docutils literal">&lt;libtorrent/extensions.hpp&gt;</tt> header.</p>
<p>These plugins are instantiated for each <a class="reference external" href="reference-Session.html#session">session</a>, torrent and possibly each peer,
respectively.</p>
<p>For plugins that only need per torrent state, it is enough to only implement
<tt class="docutils literal">torrent_plugin</tt> and pass a constructor function or function object to
<tt class="docutils literal"><span class="pre">session::add_extension()</span></tt> or <tt class="docutils literal"><span class="pre">torrent_handle::add_extension()</span></tt> (if the
torrent has already been started and you want to hook in the extension at
run-time).</p>
<p>The signature of the function is:</p>
<pre class="literal-block">
boost::shared_ptr&lt;torrent_plugin&gt; (*)(torrent*, void*);
</pre>
<p>The first argument is the internal torrent object, the second argument
is the userdata passed to <tt class="docutils literal"><span class="pre">session::add_torrent()</span></tt> or
<tt class="docutils literal"><span class="pre">torrent_handle::add_extension()</span></tt>.</p>
<p>The function should return a <tt class="docutils literal"><span class="pre">boost::shared_ptr&lt;torrent_plugin&gt;</span></tt> which
may or may not be 0. If it is a null pointer, the extension is simply ignored
for this torrent. If it is a valid pointer (to a class inheriting
<tt class="docutils literal">torrent_plugin</tt>), it will be associated with this torrent and callbacks
will be made on torrent events.</p>
<p>For more elaborate plugins which require <a class="reference external" href="reference-Session.html#session">session</a> wide state, you would
implement <tt class="docutils literal">plugin</tt>, construct an object (in a <tt class="docutils literal"><span class="pre">boost::shared_ptr</span></tt>) and pass
it in to <tt class="docutils literal"><span class="pre">session::add_extension()</span></tt>.</p>
</div>
<div class="section" id="custom-alerts">
<h1>custom alerts</h1>
<p>Since plugins are running within internal libtorrent threads, one convenient
way to communicate with the client is to post custom alerts.</p>
<p>The expected interface of any <a class="reference external" href="reference-Alerts.html#alert">alert</a>, apart from deriving from the <a class="reference external" href="reference-Alerts.html#alert">alert</a>
base class, looks like this:</p>
<pre class="literal-block">
const static int alert_type = <em>&lt;unique alert ID&gt;</em>;
virtual int type() const { return alert_type; }
virtual std::string message() const;
virtual std::auto_ptr&lt;alert&gt; clone() const
{ return std::auto_ptr&lt;alert&gt;(new name(*this)); }
const static int static_category = <em>&lt;bitmask of alert::category_t flags&gt;</em>;
virtual int category() const { return static_category; }
virtual char const* what() const { return <em>&lt;string literal of the name of this alert&gt;</em>; }
</pre>
<p>The <tt class="docutils literal">alert_type</tt> is used for the type-checking in <tt class="docutils literal">alert_cast</tt>. It must
not collide with any other <a class="reference external" href="reference-Alerts.html#alert">alert</a>. The built-in alerts in libtorrent will
not use <a class="reference external" href="reference-Alerts.html#alert">alert</a> type IDs greater than <tt class="docutils literal">user_alert_id</tt>. When defining your
own <a class="reference external" href="reference-Alerts.html#alert">alert</a>, make sure it's greater than this constant.</p>
<p><tt class="docutils literal">type()</tt> is the run-time equivalence of the <tt class="docutils literal">alert_type</tt>.</p>
<p>The <tt class="docutils literal">message()</tt> virtual function is expected to construct a useful
string representation of the <a class="reference external" href="reference-Alerts.html#alert">alert</a> and the event or data it represents.
Something convenient to put in a log file for instance.</p>
<p><tt class="docutils literal">clone()</tt> is used internally to copy alerts. The suggested implementation
of simply allocating a new instance as a copy of <tt class="docutils literal">*this</tt> is all that's
expected.</p>
<p>The static category is required for checking wether or not the category
for a specific <a class="reference external" href="reference-Alerts.html#alert">alert</a> is enabled or not, without instantiating the <a class="reference external" href="reference-Alerts.html#alert">alert</a>.
The <tt class="docutils literal">category</tt> virtual function is the run-time equivalence.</p>
<p>The <tt class="docutils literal">what()</tt> virtual function may simply be a string literal of the class
name of your <a class="reference external" href="reference-Alerts.html#alert">alert</a>.</p>
<p>For more information, see the <a class="reference external" href="reference-Alerts.html">alert section</a>.</p>
<a name="plugin"></a><div class="section" id="plugin">
<h2>plugin</h2>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/extensions.hpp">libtorrent/extensions.hpp</a>&quot;</p>
<p>this is the base class for a <a class="reference external" href="reference-Session.html#session">session</a> <a class="reference external" href="reference-Plugins.html#plugin">plugin</a>. One primary feature
is that it is notified of all torrents that are added to the <a class="reference external" href="reference-Session.html#session">session</a>,
and can add its own torrent_plugins.</p>
<pre class="literal-block">
struct plugin
{
virtual boost::shared_ptr&lt;torrent_plugin&gt; <strong>new_torrent</strong> (torrent*, void*);
virtual void <strong>added</strong> (aux::session_impl*);
virtual void <strong>on_alert</strong> (alert const*);
virtual void <strong>on_tick</strong> ();
virtual bool <strong>on_optimistic_unchoke</strong> (std::vector&lt;policy::peer*&gt;&amp; <em>/* peers */</em>);
virtual void <strong>save_state</strong> (entry&amp;) const;
virtual void <strong>load_state</strong> (lazy_entry const&amp;);
};
</pre>
<a name="new_torrent()"></a><div class="section" id="new-torrent">
<h3>new_torrent()</h3>
<pre class="literal-block">
virtual boost::shared_ptr&lt;torrent_plugin&gt; <strong>new_torrent</strong> (torrent*, void*);
</pre>
<p>this is called by the <a class="reference external" href="reference-Session.html#session">session</a> every time a new torrent is added.
The <tt class="docutils literal">torrent*</tt> points to the internal torrent object created
for the new torrent. The <tt class="docutils literal">void*</tt> is the userdata pointer as
passed in via <a class="reference external" href="reference-Session.html#add_torrent_params">add_torrent_params</a>.</p>
<p>If the <a class="reference external" href="reference-Plugins.html#plugin">plugin</a> returns a <a class="reference external" href="reference-Plugins.html#torrent_plugin">torrent_plugin</a> instance, it will be added
to the new torrent. Otherwise, return an empty shared_ptr to a
<a class="reference external" href="reference-Plugins.html#torrent_plugin">torrent_plugin</a> (the default).</p>
<a name="added()"></a></div>
<div class="section" id="added">
<h3>added()</h3>
<pre class="literal-block">
virtual void <strong>added</strong> (aux::session_impl*);
</pre>
<p>called when <a class="reference external" href="reference-Plugins.html#plugin">plugin</a> is added to a <a class="reference external" href="reference-Session.html#session">session</a></p>
<a name="on_alert()"></a></div>
<div class="section" id="on-alert">
<h3>on_alert()</h3>
<pre class="literal-block">
virtual void <strong>on_alert</strong> (alert const*);
</pre>
<p>called when an <a class="reference external" href="reference-Alerts.html#alert">alert</a> is posted
alerts that are filtered are not
posted</p>
<a name="on_tick()"></a></div>
<div class="section" id="on-tick">
<h3>on_tick()</h3>
<pre class="literal-block">
virtual void <strong>on_tick</strong> ();
</pre>
<p>called once per second</p>
<a name="on_optimistic_unchoke()"></a></div>
<div class="section" id="on-optimistic-unchoke">
<h3>on_optimistic_unchoke()</h3>
<pre class="literal-block">
virtual bool <strong>on_optimistic_unchoke</strong> (std::vector&lt;policy::peer*&gt;&amp; <em>/* peers */</em>);
</pre>
<p>called when choosing peers to optimisticly unchoke
peer's will be unchoked in the order they appear in the given
vector which is initiallity sorted by when they were last
optimistically unchoked.
if the <a class="reference external" href="reference-Plugins.html#plugin">plugin</a> returns true then the ordering provided will be
used and no other <a class="reference external" href="reference-Plugins.html#plugin">plugin</a> will be allowed to change it.</p>
<a name="save_state()"></a></div>
<div class="section" id="save-state">
<h3>save_state()</h3>
<pre class="literal-block">
virtual void <strong>save_state</strong> (entry&amp;) const;
</pre>
<p>called when saving settings state</p>
<a name="load_state()"></a></div>
<div class="section" id="load-state">
<h3>load_state()</h3>
<pre class="literal-block">
virtual void <strong>load_state</strong> (lazy_entry const&amp;);
</pre>
<p>called when loading settings state</p>
<a name="torrent_plugin"></a></div>
</div>
<div class="section" id="torrent-plugin">
<h2>torrent_plugin</h2>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/extensions.hpp">libtorrent/extensions.hpp</a>&quot;</p>
<p>Torrent plugins are associated with a single torrent and have a number
of functions called at certain events. Many of its functions have the
ability to change or override the default libtorrent behavior.</p>
<pre class="literal-block">
struct torrent_plugin
{
virtual boost::shared_ptr&lt;peer_plugin&gt; <strong>new_connection</strong> (peer_connection*);
virtual void <strong>on_piece_pass</strong> (int <em>/*index*/</em>);
virtual void <strong>on_piece_failed</strong> (int <em>/*index*/</em>);
virtual void <strong>tick</strong> ();
virtual bool <strong>on_resume</strong> ();
virtual bool <strong>on_pause</strong> ();
virtual void <strong>on_files_checked</strong> ();
virtual void <strong>on_state</strong> (int <em>/*s*/</em>);
virtual void <strong>on_add_peer</strong> (<a class="reference external" href="tcp::endpoint">tcp::endpoint</a> const&amp;,
int <em>/*src*/</em>, int <em>/*flags*/</em>);
};
</pre>
<a name="new_connection()"></a><div class="section" id="new-connection">
<h3>new_connection()</h3>
<pre class="literal-block">
virtual boost::shared_ptr&lt;peer_plugin&gt; <strong>new_connection</strong> (peer_connection*);
</pre>
<p>This function is called each time a new peer is connected to the torrent. You
may choose to ignore this by just returning a default constructed
<tt class="docutils literal">shared_ptr</tt> (in which case you don't need to override this member
function).</p>
<p>If you need an extension to the peer connection (which most plugins do) you
are supposed to return an instance of your <a class="reference external" href="reference-Plugins.html#peer_plugin">peer_plugin</a> class. Which in
turn will have its hook functions called on event specific to that peer.</p>
<p>The <tt class="docutils literal">peer_connection</tt> will be valid as long as the <tt class="docutils literal">shared_ptr</tt> is being
held by the torrent object. So, it is generally a good idea to not keep a
<tt class="docutils literal">shared_ptr</tt> to your own <a class="reference external" href="reference-Plugins.html#peer_plugin">peer_plugin</a>. If you want to keep references to it,
use <tt class="docutils literal">weak_ptr</tt>.</p>
<p>If this function throws an exception, the connection will be closed.</p>
<a name="on_piece_failed()"></a>
<a name="on_piece_pass()"></a></div>
<div class="section" id="on-piece-failed-on-piece-pass">
<h3>on_piece_failed() on_piece_pass()</h3>
<pre class="literal-block">
virtual void <strong>on_piece_pass</strong> (int <em>/*index*/</em>);
virtual void <strong>on_piece_failed</strong> (int <em>/*index*/</em>);
</pre>
<p>These hooks are called when a piece passes the hash check or fails the hash
check, respectively. The <tt class="docutils literal">index</tt> is the piece index that was downloaded.
It is possible to access the list of peers that participated in sending the
piece through the <tt class="docutils literal">torrent</tt> and the <tt class="docutils literal">piece_picker</tt>.</p>
<a name="tick()"></a></div>
<div class="section" id="tick">
<h3>tick()</h3>
<pre class="literal-block">
virtual void <strong>tick</strong> ();
</pre>
<p>This hook is called approximately once per second. It is a way of making it
easy for plugins to do timed events, for sending messages or whatever.</p>
<a name="on_resume()"></a>
<a name="on_pause()"></a></div>
<div class="section" id="on-resume-on-pause">
<h3>on_resume() on_pause()</h3>
<pre class="literal-block">
virtual bool <strong>on_resume</strong> ();
virtual bool <strong>on_pause</strong> ();
</pre>
<p>These hooks are called when the torrent is paused and unpaused respectively.
The return value indicates if the event was handled. A return value of
<tt class="docutils literal">true</tt> indicates that it was handled, and no other <a class="reference external" href="reference-Plugins.html#plugin">plugin</a> after this one
will have this hook function called, and the standard handler will also not be
invoked. So, returning true effectively overrides the standard behavior of
pause or unpause.</p>
<p>Note that if you call <tt class="docutils literal">pause()</tt> or <tt class="docutils literal">resume()</tt> on the torrent from your
handler it will recurse back into your handler, so in order to invoke the
standard handler, you have to keep your own state on whether you want standard
behavior or overridden behavior.</p>
<a name="on_files_checked()"></a></div>
<div class="section" id="on-files-checked">
<h3>on_files_checked()</h3>
<pre class="literal-block">
virtual void <strong>on_files_checked</strong> ();
</pre>
<p>This function is called when the initial files of the torrent have been
checked. If there are no files to check, this function is called immediately.</p>
<p>i.e. This function is always called when the torrent is in a state where it
can start downloading.</p>
<a name="on_state()"></a></div>
<div class="section" id="on-state">
<h3>on_state()</h3>
<pre class="literal-block">
virtual void <strong>on_state</strong> (int <em>/*s*/</em>);
</pre>
<p>called when the torrent changes state
the state is one of <a class="reference external" href="reference-Core.html#state_t">torrent_status::state_t</a>
enum members</p>
<a name="on_add_peer()"></a></div>
<div class="section" id="on-add-peer">
<h3>on_add_peer()</h3>
<pre class="literal-block">
virtual void <strong>on_add_peer</strong> (<a class="reference external" href="tcp::endpoint">tcp::endpoint</a> const&amp;,
int <em>/*src*/</em>, int <em>/*flags*/</em>);
</pre>
<p>called every time a new peer is added to the peer list.
This is before the peer is connected to. For <tt class="docutils literal">flags</tt>, see
torrent_plugin::flags_t. The <tt class="docutils literal">source</tt> argument refers to
the source where we learned about this peer from. It's a
bitmask, because many sources may have told us about the same
peer. For peer source flags, see <a class="reference external" href="reference-Core.html#peer_source_flags">peer_info::peer_source_flags</a>.</p>
<a name="peer_plugin"></a></div>
</div>
<div class="section" id="peer-plugin">
<h2>peer_plugin</h2>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/extensions.hpp">libtorrent/extensions.hpp</a>&quot;</p>
<p>peer plugins are associated with a specific peer. A peer could be
both a regular bittorrent peer (<tt class="docutils literal">bt_peer_connection</tt>) or one of the
web seed connections (<tt class="docutils literal">web_peer_connection</tt> or <tt class="docutils literal">http_seed_connection</tt>).
In order to only attach to certain peers, make your
torrent_plugin::new_connection only return a <a class="reference external" href="reference-Plugins.html#plugin">plugin</a> for certain peer
connection types</p>
<pre class="literal-block">
struct peer_plugin
{
virtual char const* <strong>type</strong> () const;
virtual void <strong>add_handshake</strong> (entry&amp;);
virtual void <strong>on_disconnect</strong> (error_code const&amp; <em>/*ec*/</em>);
virtual void <strong>on_connected</strong> ();
virtual bool <strong>on_handshake</strong> (char const* <em>/*reserved_bits*/</em>);
virtual bool <strong>on_extension_handshake</strong> (lazy_entry const&amp;);
virtual bool <strong>on_have</strong> (int <em>/*index*/</em>);
virtual bool <strong>on_bitfield</strong> (bitfield const&amp; <em>/*bitfield*/</em>);
virtual bool <strong>on_have_all</strong> ();
virtual bool <strong>on_reject</strong> (peer_request const&amp;);
virtual bool <strong>on_request</strong> (peer_request const&amp;);
virtual bool <strong>on_unchoke</strong> ();
virtual bool <strong>on_interested</strong> ();
virtual bool <strong>on_allowed_fast</strong> (int <em>/*index*/</em>);
virtual bool <strong>on_have_none</strong> ();
virtual bool <strong>on_choke</strong> ();
virtual bool <strong>on_not_interested</strong> ();
virtual bool <strong>on_piece</strong> (peer_request const&amp; <em>/*piece*/</em>
, disk_buffer_holder&amp; <em>/*data*/</em>);
virtual bool <strong>on_suggest</strong> (int <em>/*index*/</em>);
virtual bool <strong>on_cancel</strong> (peer_request const&amp;);
virtual bool <strong>on_dont_have</strong> (int <em>/*index*/</em>);
virtual void <strong>sent_unchoke</strong> ();
virtual bool <strong>can_disconnect</strong> (error_code const&amp; <em>/*ec*/</em>);
virtual bool <strong>on_extended</strong> (int <em>/*length*/</em>, int <em>/*msg*/</em>,
buffer::const_interval <em>/*body*/</em>);
virtual bool <strong>on_unknown_message</strong> (int <em>/*length*/</em>, int <em>/*msg*/</em>,
buffer::const_interval <em>/*body*/</em>);
virtual void <strong>on_piece_pass</strong> (int <em>/*index*/</em>);
virtual void <strong>on_piece_failed</strong> (int <em>/*index*/</em>);
virtual void <strong>tick</strong> ();
virtual bool <strong>write_request</strong> (peer_request const&amp;);
};
</pre>
<a name="type()"></a><div class="section" id="type">
<h3>type()</h3>
<pre class="literal-block">
virtual char const* <strong>type</strong> () const;
</pre>
<p>This function is expected to return the name of
the <a class="reference external" href="reference-Plugins.html#plugin">plugin</a>.</p>
<a name="add_handshake()"></a></div>
<div class="section" id="add-handshake">
<h3>add_handshake()</h3>
<pre class="literal-block">
virtual void <strong>add_handshake</strong> (entry&amp;);
</pre>
<p>can add entries to the extension handshake
this is not called for web seeds</p>
<a name="on_disconnect()"></a></div>
<div class="section" id="on-disconnect">
<h3>on_disconnect()</h3>
<pre class="literal-block">
virtual void <strong>on_disconnect</strong> (error_code const&amp; <em>/*ec*/</em>);
</pre>
<p>called when the peer is being disconnected.</p>
<a name="on_connected()"></a></div>
<div class="section" id="on-connected">
<h3>on_connected()</h3>
<pre class="literal-block">
virtual void <strong>on_connected</strong> ();
</pre>
<p>called when the peer is successfully connected. Note that
incoming connections will have been connected by the time
the peer <a class="reference external" href="reference-Plugins.html#plugin">plugin</a> is attached to it, and won't have this hook
called.</p>
<a name="on_handshake()"></a></div>
<div class="section" id="on-handshake">
<h3>on_handshake()</h3>
<pre class="literal-block">
virtual bool <strong>on_handshake</strong> (char const* <em>/*reserved_bits*/</em>);
</pre>
<p>this is called when the initial BT handshake is received. Returning false
means that the other end doesn't support this extension and will remove
it from the list of plugins.
this is not called for web seeds</p>
<a name="on_extension_handshake()"></a></div>
<div class="section" id="on-extension-handshake">
<h3>on_extension_handshake()</h3>
<pre class="literal-block">
virtual bool <strong>on_extension_handshake</strong> (lazy_entry const&amp;);
</pre>
<p>called when the extension handshake from the other end is received
if this returns false, it means that this extension isn't
supported by this peer. It will result in this <a class="reference external" href="reference-Plugins.html#peer_plugin">peer_plugin</a>
being removed from the peer_connection and destructed.
this is not called for web seeds</p>
<a name="on_bitfield()"></a>
<a name="on_have_none()"></a>
<a name="on_suggest()"></a>
<a name="on_unchoke()"></a>
<a name="on_cancel()"></a>
<a name="on_have()"></a>
<a name="on_choke()"></a>
<a name="on_piece()"></a>
<a name="on_request()"></a>
<a name="on_reject()"></a>
<a name="on_not_interested()"></a>
<a name="on_interested()"></a>
<a name="on_allowed_fast()"></a>
<a name="on_have_all()"></a>
<a name="on_dont_have()"></a></div>
<div class="section" id="on-bitfield-on-have-none-on-suggest-on-unchoke-on-cancel-on-have-on-choke-on-piece-on-request-on-reject-on-not-interested-on-interested-on-allowed-fast-on-have-all-on-dont-have">
<h3>on_bitfield() on_have_none() on_suggest() on_unchoke() on_cancel() on_have() on_choke() on_piece() on_request() on_reject() on_not_interested() on_interested() on_allowed_fast() on_have_all() on_dont_have()</h3>
<pre class="literal-block">
virtual bool <strong>on_have</strong> (int <em>/*index*/</em>);
virtual bool <strong>on_bitfield</strong> (bitfield const&amp; <em>/*bitfield*/</em>);
virtual bool <strong>on_have_all</strong> ();
virtual bool <strong>on_reject</strong> (peer_request const&amp;);
virtual bool <strong>on_request</strong> (peer_request const&amp;);
virtual bool <strong>on_unchoke</strong> ();
virtual bool <strong>on_interested</strong> ();
virtual bool <strong>on_allowed_fast</strong> (int <em>/*index*/</em>);
virtual bool <strong>on_have_none</strong> ();
virtual bool <strong>on_choke</strong> ();
virtual bool <strong>on_not_interested</strong> ();
virtual bool <strong>on_piece</strong> (peer_request const&amp; <em>/*piece*/</em>
, disk_buffer_holder&amp; <em>/*data*/</em>);
virtual bool <strong>on_suggest</strong> (int <em>/*index*/</em>);
virtual bool <strong>on_cancel</strong> (peer_request const&amp;);
virtual bool <strong>on_dont_have</strong> (int <em>/*index*/</em>);
</pre>
<p>returning true from any of the message handlers
indicates that the <a class="reference external" href="reference-Plugins.html#plugin">plugin</a> has handeled the message.
it will break the <a class="reference external" href="reference-Plugins.html#plugin">plugin</a> chain traversing and not let
anyone else handle the message, including the default
handler.</p>
<a name="sent_unchoke()"></a></div>
<div class="section" id="sent-unchoke">
<h3>sent_unchoke()</h3>
<pre class="literal-block">
virtual void <strong>sent_unchoke</strong> ();
</pre>
<p>called after a choke message has been sent to the peer</p>
<a name="can_disconnect()"></a></div>
<div class="section" id="can-disconnect">
<h3>can_disconnect()</h3>
<pre class="literal-block">
virtual bool <strong>can_disconnect</strong> (error_code const&amp; <em>/*ec*/</em>);
</pre>
<p>called when libtorrent think this peer should be disconnected.
if the <a class="reference external" href="reference-Plugins.html#plugin">plugin</a> returns false, the peer will not be disconnected.</p>
<a name="on_extended()"></a></div>
<div class="section" id="on-extended">
<h3>on_extended()</h3>
<pre class="literal-block">
virtual bool <strong>on_extended</strong> (int <em>/*length*/</em>, int <em>/*msg*/</em>,
buffer::const_interval <em>/*body*/</em>);
</pre>
<p>called when an extended message is received. If returning true,
the message is not processed by any other <a class="reference external" href="reference-Plugins.html#plugin">plugin</a> and if false
is returned the next <a class="reference external" href="reference-Plugins.html#plugin">plugin</a> in the chain will receive it to
be able to handle it
this is not called for web seeds</p>
<a name="on_unknown_message()"></a></div>
<div class="section" id="on-unknown-message">
<h3>on_unknown_message()</h3>
<pre class="literal-block">
virtual bool <strong>on_unknown_message</strong> (int <em>/*length*/</em>, int <em>/*msg*/</em>,
buffer::const_interval <em>/*body*/</em>);
</pre>
<p>this is not called for web seeds</p>
<a name="on_piece_failed()"></a>
<a name="on_piece_pass()"></a></div>
<div class="section" id="id55">
<h3>on_piece_failed() on_piece_pass()</h3>
<pre class="literal-block">
virtual void <strong>on_piece_pass</strong> (int <em>/*index*/</em>);
virtual void <strong>on_piece_failed</strong> (int <em>/*index*/</em>);
</pre>
<p>called when a piece that this peer participated in either
fails or passes the hash_check</p>
<a name="tick()"></a></div>
<div class="section" id="id56">
<h3>tick()</h3>
<pre class="literal-block">
virtual void <strong>tick</strong> ();
</pre>
<p>called aproximately once every second</p>
<a name="write_request()"></a></div>
<div class="section" id="write-request">
<h3>write_request()</h3>
<pre class="literal-block">
virtual bool <strong>write_request</strong> (peer_request const&amp;);
</pre>
<p>called each time a request message is to be sent. If true
is returned, the original request message won't be sent and
no other <a class="reference external" href="reference-Plugins.html#plugin">plugin</a> will have this function called.</p>
<a name="create_lt_trackers_plugin()"></a></div>
<div class="section" id="create-lt-trackers-plugin">
<h3>create_lt_trackers_plugin()</h3>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/extensions/lt_trackers.hpp">libtorrent/extensions/lt_trackers.hpp</a>&quot;</p>
<pre class="literal-block">
boost::shared_ptr&lt;torrent_plugin&gt; <strong>create_lt_trackers_plugin</strong> (torrent*, void*);
</pre>
<p>constructor function for the trackers exchange extension. This can
either be passed in the add_torrent_params::extensions field, or
via <a class="reference external" href="reference-Core.html#add_extension()">torrent_handle::add_extension()</a>.</p>
<a name="create_smart_ban_plugin()"></a></div>
<div class="section" id="create-smart-ban-plugin">
<h3>create_smart_ban_plugin()</h3>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/extensions/smart_ban.hpp">libtorrent/extensions/smart_ban.hpp</a>&quot;</p>
<pre class="literal-block">
boost::shared_ptr&lt;torrent_plugin&gt; <strong>create_smart_ban_plugin</strong> (torrent*, void*);
</pre>
<p>constructor function for the smart ban extension. The extension keeps
track of the data peers have sent us for failing pieces and once the
piece completes and passes the hash check bans the peers that turned
out to have sent corrupt data.
This function can either be passed in the add_torrent_params::extensions
field, or via <a class="reference external" href="reference-Core.html#add_extension()">torrent_handle::add_extension()</a>.</p>
<a name="create_ut_metadata_plugin()"></a></div>
<div class="section" id="create-ut-metadata-plugin">
<h3>create_ut_metadata_plugin()</h3>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/extensions/ut_metadata.hpp">libtorrent/extensions/ut_metadata.hpp</a>&quot;</p>
<pre class="literal-block">
boost::shared_ptr&lt;torrent_plugin&gt; <strong>create_ut_metadata_plugin</strong> (torrent*, void*);
</pre>
<p>constructor function for the ut_metadata extension. The ut_metadata
extension allows peers to request the .torrent file (or more
specifically the 'info'-dictionary of the .torrent file) from each
other. This is the main building block in making magnet links work.
This extension is enabled by default unless explicitly disabled in
the <a class="reference external" href="reference-Session.html#session">session</a> constructor.</p>
<p>This can either be passed in the add_torrent_params::extensions field, or
via <a class="reference external" href="reference-Core.html#add_extension()">torrent_handle::add_extension()</a>.</p>
<a name="create_ut_pex_plugin()"></a></div>
<div class="section" id="create-ut-pex-plugin">
<h3>create_ut_pex_plugin()</h3>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/extensions/ut_pex.hpp">libtorrent/extensions/ut_pex.hpp</a>&quot;</p>
<pre class="literal-block">
boost::shared_ptr&lt;torrent_plugin&gt; <strong>create_ut_pex_plugin</strong> (torrent*, void*);
</pre>
<p>constructor function for the ut_pex extension. The ut_pex
extension allows peers to gossip about their connections, allowing
the swarm stay well connected and peers aware of more peers in the
swarm. This extension is enabled by default unless explicitly disabled in
the <a class="reference external" href="reference-Session.html#session">session</a> constructor.</p>
<p>This can either be passed in the add_torrent_params::extensions field, or
via <a class="reference external" href="reference-Core.html#add_extension()">torrent_handle::add_extension()</a>.</p>
</div>
</div>
</div>
</div>
</body>
</html>

View File

@ -1,298 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.11: http://docutils.sourceforge.net/" />
<title>RSS</title>
<meta name="author" content="Arvid Norberg, arvid&#64;rasterbar.com" />
<link rel="stylesheet" type="text/css" href="../../css/base.css" />
<link rel="stylesheet" type="text/css" href="../../css/rst.css" />
<script type="text/javascript">
/* <![CDATA[ */
(function() {
var s = document.createElement('script'), t = document.getElementsByTagName('script')[0];
s.type = 'text/javascript';
s.async = true;
s.src = 'http://api.flattr.com/js/0.6/load.js?mode=auto';
t.parentNode.insertBefore(s, t);
})();
/* ]]> */
</script>
<link rel="stylesheet" href="style.css" type="text/css" />
<style type="text/css">
/* Hides from IE-mac \*/
* html pre { height: 1%; }
/* End hide from IE-mac */
</style>
</head>
<body>
<div class="document" id="rss">
<div id="container">
<div id="headerNav">
<ul>
<li class="first"><a href="/">Home</a></li>
<li><a href="../../products.html">Products</a></li>
<li><a href="../../contact.html">Contact</a></li>
</ul>
</div>
<div id="header">
<div id="orange"></div>
<div id="logo"></div>
</div>
<div id="main">
<h1 class="title">RSS</h1>
<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<tr><th class="docinfo-name">Author:</th>
<td>Arvid Norberg, <a class="last reference external" href="mailto:arvid&#64;rasterbar.com">arvid&#64;rasterbar.com</a></td></tr>
<tr><th class="docinfo-name">Version:</th>
<td>1.0.0</td></tr>
</tbody>
</table>
<div class="contents topic" id="table-of-contents">
<p class="topic-title first">Table of contents</p>
<ul class="simple">
<li><a class="reference internal" href="#feed-item" id="id25">feed_item</a></li>
<li><a class="reference internal" href="#feed-settings" id="id26">feed_settings</a></li>
<li><a class="reference internal" href="#feed-status" id="id27">feed_status</a></li>
<li><a class="reference internal" href="#feed-handle" id="id28">feed_handle</a></li>
</ul>
</div>
<a name="feed_item"></a><div class="section" id="feed-item">
<h1>feed_item</h1>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/rss.hpp">libtorrent/rss.hpp</a>&quot;</p>
<p>represents one item from an RSS feed. Specifically
a feed of torrents.</p>
<pre class="literal-block">
struct feed_item
{
<strong>feed_item</strong> ();
<strong>~feed_item</strong> ();
std::string url;
std::string uuid;
std::string title;
std::string description;
std::string comment;
std::string category;
size_type size;
torrent_handle handle;
sha1_hash info_hash;
};
</pre>
<a name="url"></a>
<a name="uuid"></a>
<a name="title"></a>
<a name="description"></a>
<a name="comment"></a>
<a name="category"></a><dl class="docutils">
<dt>url uuid title description comment category</dt>
<dd>these are self explanatory and may be empty if the feed does not specify
those fields.</dd>
</dl>
<a name="size"></a><dl class="docutils">
<dt>size</dt>
<dd>the total size of the content the torrent refers to, or -1
if no size was specified by the feed.</dd>
</dl>
<a name="handle"></a><dl class="docutils">
<dt>handle</dt>
<dd>the handle to the torrent, if the <a class="reference external" href="reference-Session.html#session">session</a> is already downloading
this torrent.</dd>
</dl>
<a name="info_hash"></a><dl class="docutils">
<dt>info_hash</dt>
<dd>the info-hash of the torrent, or cleared (i.e. all zeroes) if
the feed does not specify the info-hash.</dd>
</dl>
<a name="feed_settings"></a></div>
<div class="section" id="feed-settings">
<h1>feed_settings</h1>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/rss.hpp">libtorrent/rss.hpp</a>&quot;</p>
<p>the <a class="reference external" href="reference-RSS.html#feed_settings">feed_settings</a> object is all the information
and configuration for a specific feed. All of
these settings can be changed by the user
after adding the feed</p>
<pre class="literal-block">
struct feed_settings
{
<strong>feed_settings</strong> ();
std::string url;
bool auto_download;
bool auto_map_handles;
int default_ttl;
add_torrent_params add_args;
};
</pre>
<a name="auto_download"></a><dl class="docutils">
<dt>auto_download</dt>
<dd>By default <tt class="docutils literal">auto_download</tt> is true, which means all torrents in
the feed will be downloaded. Set this to false in order to manually
add torrents to the <a class="reference external" href="reference-Session.html#session">session</a>. You may react to the <a class="reference external" href="reference-Alerts.html#rss_alert">rss_alert</a> when
a feed has been updated to poll it for the new items in the feed
when adding torrents manually. When torrents are added automatically,
an <a class="reference external" href="reference-Alerts.html#add_torrent_alert">add_torrent_alert</a> is posted which includes the torrent handle
as well as the error code if it failed to be added. You may also call
<tt class="docutils literal"><span class="pre">session::get_torrents()</span></tt> to get the handles to the new torrents.</dd>
</dl>
<a name="auto_map_handles"></a><dl class="docutils">
<dt>auto_map_handles</dt>
<dd><tt class="docutils literal">auto_map_handles</tt> defaults to true and determines whether or
not to set the <tt class="docutils literal">handle</tt> field in the <a class="reference external" href="reference-RSS.html#feed_item">feed_item</a>, returned
as the feed status. If auto-download is enabled, this setting
is ignored. If auto-download is not set, setting this to false
will save one pass through all the feed items trying to find
corresponding torrents in the <a class="reference external" href="reference-Session.html#session">session</a>.</dd>
</dl>
<a name="default_ttl"></a><dl class="docutils">
<dt>default_ttl</dt>
<dd>The <tt class="docutils literal">default_ttl</tt> is the default interval for refreshing a feed.
This may be overridden by the feed itself (by specifying the <tt class="docutils literal">&lt;ttl&gt;</tt>
tag) and defaults to 30 minutes. The field specifies the number of
minutes between refreshes.</dd>
</dl>
<a name="add_args"></a><dl class="docutils">
<dt>add_args</dt>
<dd>If torrents are added automatically, you may want to set the
<tt class="docutils literal">add_args</tt> to appropriate values for download directory etc.
This object is used as a template for adding torrents from feeds,
but some torrent specific fields will be overridden by the
individual torrent being added. For more information on the
<a class="reference external" href="reference-Session.html#add_torrent_params">add_torrent_params</a>, see <a class="reference external" href="reference-Session.html#async_add_torrent()">async_add_torrent()</a> and <a class="reference external" href="reference-Session.html#add_torrent()">add_torrent()</a>.</dd>
</dl>
<a name="feed_status"></a></div>
<div class="section" id="feed-status">
<h1>feed_status</h1>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/rss.hpp">libtorrent/rss.hpp</a>&quot;</p>
<p>holds information about the status of an RSS feed. Retrieved by
calling <a class="reference external" href="reference-RSS.html#get_feed_status()">get_feed_status()</a> on <a class="reference external" href="reference-RSS.html#feed_handle">feed_handle</a>.</p>
<pre class="literal-block">
struct feed_status
{
<strong>feed_status</strong> ();
std::string url;
std::string title;
std::string description;
time_t last_update;
int next_update;
bool updating;
std::vector&lt;feed_item&gt; items;
error_code error;
int ttl;
};
</pre>
<a name="url"></a><dl class="docutils">
<dt>url</dt>
<dd>the URL of the feed.</dd>
</dl>
<a name="title"></a><dl class="docutils">
<dt>title</dt>
<dd>the name of the feed (as specified by the feed itself). This
may be empty if we have not recevied a response from the RSS server yet,
or if the feed does not specify a title.</dd>
</dl>
<a name="description"></a><dl class="docutils">
<dt>description</dt>
<dd>the feed description (as specified by the feed itself).
This may be empty if we have not received a response from the RSS server
yet, or if the feed does not specify a description.</dd>
</dl>
<a name="last_update"></a><dl class="docutils">
<dt>last_update</dt>
<dd>the posix time of the last successful response from the feed.</dd>
</dl>
<a name="next_update"></a><dl class="docutils">
<dt>next_update</dt>
<dd>the number of seconds, from now, when the feed will be
updated again.</dd>
</dl>
<a name="updating"></a><dl class="docutils">
<dt>updating</dt>
<dd>true if the feed is currently being updated (i.e. waiting for
DNS resolution, connecting to the server or waiting for the response to the
HTTP request, or receiving the response).</dd>
</dl>
<a name="items"></a><dl class="docutils">
<dt>items</dt>
<dd>a vector of all items that we have received from the feed. See
<a class="reference external" href="reference-RSS.html#feed_item">feed_item</a> for more information.</dd>
</dl>
<a name="error"></a><dl class="docutils">
<dt>error</dt>
<dd>set to the appropriate error code if the feed encountered an
error. See error_code for more info.</dd>
</dl>
<a name="ttl"></a><dl class="docutils">
<dt>ttl</dt>
<dd>the current refresh time (in minutes). It's either the configured
default ttl, or the ttl specified by the feed.</dd>
</dl>
<a name="feed_handle"></a></div>
<div class="section" id="feed-handle">
<h1>feed_handle</h1>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/rss.hpp">libtorrent/rss.hpp</a>&quot;</p>
<p>The <tt class="docutils literal">feed_handle</tt> refers to a specific RSS feed that is watched by the <a class="reference external" href="reference-Session.html#session">session</a>.</p>
<pre class="literal-block">
struct feed_handle
{
<strong>feed_handle</strong> ();
void <strong>update_feed</strong> ();
feed_status <strong>get_feed_status</strong> () const;
void <strong>set_settings</strong> (feed_settings const&amp; s);
feed_settings <strong>settings</strong> () const;
};
</pre>
<a name="update_feed()"></a><div class="section" id="update-feed">
<h2>update_feed()</h2>
<pre class="literal-block">
void <strong>update_feed</strong> ();
</pre>
<p>Forces an update/refresh of the feed. Regular updates of the feed is managed
by libtorrent, be careful to not call this too frequently since it may
overload the RSS server.</p>
<a name="get_feed_status()"></a></div>
<div class="section" id="get-feed-status">
<h2>get_feed_status()</h2>
<pre class="literal-block">
feed_status <strong>get_feed_status</strong> () const;
</pre>
<p>Queries the RSS feed for information, including all the items in the feed.
see <a class="reference external" href="reference-RSS.html#feed_status">feed_status</a>.</p>
<a name="settings()"></a>
<a name="set_settings()"></a></div>
<div class="section" id="settings-set-settings">
<h2>settings() set_settings()</h2>
<pre class="literal-block">
void <strong>set_settings</strong> (feed_settings const&amp; s);
feed_settings <strong>settings</strong> () const;
</pre>
<p>Sets and gets settings for this feed. For more information on the
available settings, see <a class="reference external" href="reference-Session.html#add_feed()">add_feed()</a>.</p>
<a name="add_feed_item()"></a></div>
<div class="section" id="add-feed-item">
<h2>add_feed_item()</h2>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/rss.hpp">libtorrent/rss.hpp</a>&quot;</p>
<pre class="literal-block">
torrent_handle <strong>add_feed_item</strong> (session&amp; s, feed_item const&amp; fi
, add_torrent_params const&amp; p);
torrent_handle <strong>add_feed_item</strong> (session&amp; s, feed_item const&amp; fi
, add_torrent_params const&amp; p, error_code&amp; ec);
</pre>
<p>given a <a class="reference external" href="reference-RSS.html#feed_item">feed_item</a> <tt class="docutils literal">f</tt>, add the torrent it refers to to <a class="reference external" href="reference-Session.html#session">session</a> <tt class="docutils literal">s</tt>.</p>
<a name="new_feed()"></a></div>
<div class="section" id="new-feed">
<h2>new_feed()</h2>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/rss.hpp">libtorrent/rss.hpp</a>&quot;</p>
<pre class="literal-block">
boost::shared_ptr&lt;feed&gt; <strong>new_feed</strong> (aux::session_impl&amp; ses, feed_settings const&amp; sett);
</pre>
</div>
</div>
</div>
</body>
</html>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,604 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.11: http://docutils.sourceforge.net/" />
<title>Storage</title>
<meta name="author" content="Arvid Norberg, arvid&#64;rasterbar.com" />
<link rel="stylesheet" type="text/css" href="../../css/base.css" />
<link rel="stylesheet" type="text/css" href="../../css/rst.css" />
<script type="text/javascript">
/* <![CDATA[ */
(function() {
var s = document.createElement('script'), t = document.getElementsByTagName('script')[0];
s.type = 'text/javascript';
s.async = true;
s.src = 'http://api.flattr.com/js/0.6/load.js?mode=auto';
t.parentNode.insertBefore(s, t);
})();
/* ]]> */
</script>
<link rel="stylesheet" href="style.css" type="text/css" />
<style type="text/css">
/* Hides from IE-mac \*/
* html pre { height: 1%; }
/* End hide from IE-mac */
</style>
</head>
<body>
<div class="document" id="storage">
<div id="container">
<div id="headerNav">
<ul>
<li class="first"><a href="/">Home</a></li>
<li><a href="../../products.html">Products</a></li>
<li><a href="../../contact.html">Contact</a></li>
</ul>
</div>
<div id="header">
<div id="orange"></div>
<div id="logo"></div>
</div>
<div id="main">
<h1 class="title">Storage</h1>
<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<tr><th class="docinfo-name">Author:</th>
<td>Arvid Norberg, <a class="last reference external" href="mailto:arvid&#64;rasterbar.com">arvid&#64;rasterbar.com</a></td></tr>
<tr><th class="docinfo-name">Version:</th>
<td>1.0.0</td></tr>
</tbody>
</table>
<div class="contents topic" id="table-of-contents">
<p class="topic-title first">Table of contents</p>
<ul class="simple">
<li><a class="reference internal" href="#file-entry" id="id25">file_entry</a></li>
<li><a class="reference internal" href="#file-slice" id="id26">file_slice</a></li>
<li><a class="reference internal" href="#file-storage" id="id27">file_storage</a></li>
</ul>
</div>
<a name="file_entry"></a><div class="section" id="file-entry">
<h1>file_entry</h1>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/file_storage.hpp">libtorrent/file_storage.hpp</a>&quot;</p>
<p>information about a file in a <a class="reference external" href="reference-Storage.html#file_storage">file_storage</a></p>
<pre class="literal-block">
struct file_entry
{
std::string path;
std::string symlink_path;
size_type offset;
size_type size;
size_type file_base;
std::time_t mtime;
sha1_hash filehash;
bool pad_file:1;
bool hidden_attribute:1;
bool executable_attribute:1;
bool symlink_attribute:1;
};
</pre>
<a name="path"></a><dl class="docutils">
<dt>path</dt>
<dd>the full path of this file. The paths are unicode strings
encoded in UTF-8.</dd>
</dl>
<a name="symlink_path"></a><dl class="docutils">
<dt>symlink_path</dt>
<dd>the path which this is a symlink to, or empty if this is
not a symlink. This field is only used if the <tt class="docutils literal">symlink_attribute</tt> is set.</dd>
</dl>
<a name="offset"></a><dl class="docutils">
<dt>offset</dt>
<dd>the offset of this file inside the torrent</dd>
</dl>
<a name="size"></a><dl class="docutils">
<dt>size</dt>
<dd>the size of the file (in bytes) and <tt class="docutils literal">offset</tt> is the byte offset
of the file within the torrent. i.e. the sum of all the sizes of the files
before it in the list.</dd>
</dl>
<a name="file_base"></a><dl class="docutils">
<dt>file_base</dt>
<dd>the offset in the file where the storage should start. The normal
case is to have this set to 0, so that the storage starts saving data at the start
if the file. In cases where multiple files are mapped into the same file though,
the <tt class="docutils literal">file_base</tt> should be set to an offset so that the different regions do
not overlap. This is used when mapping &quot;unselected&quot; files into a so-called part
file.</dd>
</dl>
<a name="mtime"></a><dl class="docutils">
<dt>mtime</dt>
<dd>the modification time of this file specified in posix time.</dd>
</dl>
<a name="filehash"></a><dl class="docutils">
<dt>filehash</dt>
<dd>a sha-1 hash of the content of the file, or zeroes, if no
file hash was present in the torrent file. It can be used to potentially
find alternative sources for the file.</dd>
</dl>
<a name="pad_file"></a><dl class="docutils">
<dt>pad_file</dt>
<dd>set to true for files that are not part of the data of the torrent.
They are just there to make sure the next file is aligned to a particular byte offset
or piece boundry. These files should typically be hidden from an end user. They are
not written to disk.</dd>
</dl>
<a name="hidden_attribute"></a><dl class="docutils">
<dt>hidden_attribute</dt>
<dd>true if the file was marked as hidden (on windows).</dd>
</dl>
<a name="executable_attribute"></a><dl class="docutils">
<dt>executable_attribute</dt>
<dd>true if the file was marked as executable (posix)</dd>
</dl>
<a name="symlink_attribute"></a><dl class="docutils">
<dt>symlink_attribute</dt>
<dd>true if the file was a symlink. If this is the case
the <tt class="docutils literal">symlink_index</tt> refers to a string which specifies the original location
where the data for this file was found.</dd>
</dl>
<a name="file_slice"></a></div>
<div class="section" id="file-slice">
<h1>file_slice</h1>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/file_storage.hpp">libtorrent/file_storage.hpp</a>&quot;</p>
<p>represents a window of a file in a torrent.</p>
<p>The <tt class="docutils literal">file_index</tt> refers to the index of the file (in the <a class="reference external" href="reference-Core.html#torrent_info">torrent_info</a>).
To get the path and filename, use <tt class="docutils literal">file_at()</tt> and give the <tt class="docutils literal">file_index</tt>
as argument. The <tt class="docutils literal">offset</tt> is the byte offset in the file where the range
starts, and <tt class="docutils literal">size</tt> is the number of bytes this range is. The size + offset
will never be greater than the file size.</p>
<pre class="literal-block">
struct file_slice
{
int file_index;
size_type offset;
size_type size;
};
</pre>
<a name="file_index"></a><dl class="docutils">
<dt>file_index</dt>
<dd>the index of the file</dd>
</dl>
<a name="offset"></a><dl class="docutils">
<dt>offset</dt>
<dd>the offset from the start of the file, in bytes</dd>
</dl>
<a name="size"></a><dl class="docutils">
<dt>size</dt>
<dd>the size of the window, in bytes</dd>
</dl>
<a name="file_storage"></a></div>
<div class="section" id="file-storage">
<h1>file_storage</h1>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/file_storage.hpp">libtorrent/file_storage.hpp</a>&quot;</p>
<p>The <tt class="docutils literal">file_storage</tt> class represents a file list and the piece
size. Everything necessary to interpret a regular bittorrent storage
file structure.</p>
<pre class="literal-block">
class file_storage
{
bool <strong>is_valid</strong> () const;
void <strong>reserve</strong> (int num_files);
void <strong>add_file</strong> (std::string const&amp; p, size_type size, int flags = 0
, std::time_t mtime = 0, std::string const&amp; s_p = &quot;&quot;);
void <strong>add_file</strong> (file_entry const&amp; e, char const* filehash = 0);
void <strong>rename_file</strong> (int index, std::string const&amp; new_filename);
void <strong>rename_file_borrow</strong> (int index, char const* new_filename, int len);
std::vector&lt;file_slice&gt; <strong>map_block</strong> (int piece, size_type offset
, int size) const;
peer_request <strong>map_file</strong> (int file, size_type offset, int size) const;
int <strong>num_files</strong> () const;
file_entry <strong>at</strong> (int index) const;
size_type <strong>total_size</strong> () const;
void <strong>set_num_pieces</strong> (int n);
int <strong>num_pieces</strong> () const;
void <strong>set_piece_length</strong> (int l);
int <strong>piece_length</strong> () const;
int <strong>piece_size</strong> (int index) const;
void <strong>set_name</strong> (std::string const&amp; n);
const std::string&amp; <strong>name</strong> () const;
void <strong>swap</strong> (file_storage&amp; ti);
void <strong>optimize</strong> (int pad_file_limit = -1, int alignment = -1);
size_type <strong>file_size</strong> (int index) const;
sha1_hash <strong>hash</strong> (int index) const;
std::string <strong>file_name</strong> (int index) const;
size_type <strong>file_offset</strong> (int index) const;
time_t <strong>mtime</strong> (int index) const;
bool <strong>pad_file_at</strong> (int index) const;
std::string const&amp; <strong>symlink</strong> (int index) const;
std::string <strong>file_path</strong> (int index, std::string const&amp; save_path = &quot;&quot;) const;
int <strong>file_flags</strong> (int index) const;
void <strong>set_file_base</strong> (int index, size_type off);
size_type <strong>file_base</strong> (int index) const;
int <strong>file_index_at_offset</strong> (size_type offset) const;
char const* <strong>file_name_ptr</strong> (int index) const;
int <strong>file_name_len</strong> (int index) const;
enum flags_t
{
pad_file,
attribute_hidden,
attribute_executable,
attribute_symlink,
};
enum file_flags_t
{
flag_pad_file,
flag_hidden,
flag_executable,
flag_symlink,
};
};
</pre>
<a name="is_valid()"></a><div class="section" id="is-valid">
<h2>is_valid()</h2>
<pre class="literal-block">
bool <strong>is_valid</strong> () const;
</pre>
<p>returns true if the piece length has been initialized
on the <a class="reference external" href="reference-Storage.html#file_storage">file_storage</a>. This is typically taken as a proxy
of whether the <a class="reference external" href="reference-Storage.html#file_storage">file_storage</a> as a whole is initialized or
not.</p>
<a name="reserve()"></a></div>
<div class="section" id="reserve">
<h2>reserve()</h2>
<pre class="literal-block">
void <strong>reserve</strong> (int num_files);
</pre>
<p>allocates space for <tt class="docutils literal">num_files</tt> in the internal file list. This can
be used to avoid reallocating the internal file list when the number
of files to be added is known up-front.</p>
<a name="add_file()"></a></div>
<div class="section" id="add-file">
<h2>add_file()</h2>
<pre class="literal-block">
void <strong>add_file</strong> (std::string const&amp; p, size_type size, int flags = 0
, std::time_t mtime = 0, std::string const&amp; s_p = &quot;&quot;);
void <strong>add_file</strong> (file_entry const&amp; e, char const* filehash = 0);
</pre>
<p>Adds a file to the file storage. The <tt class="docutils literal">flags</tt> argument sets attributes on the file.
The file attributes is an extension and may not work in all bittorrent clients.</p>
<p>For possible file attributes, see <a class="reference external" href="reference-Storage.html#flags_t">file_storage::flags_t</a>.</p>
<p>If more files than one are added, certain restrictions to their paths apply.
In a multi-file file storage (torrent), all files must share the same root directory.</p>
<p>That is, the first path element of all files must be the same.
This shared path element is also set to the name of the torrent. It
can be changed by calling <tt class="docutils literal">set_name</tt>.</p>
<p>The built in functions to traverse a directory to add files will
make sure this requirement is fulfilled.</p>
<a name="rename_file()"></a></div>
<div class="section" id="rename-file">
<h2>rename_file()</h2>
<pre class="literal-block">
void <strong>rename_file</strong> (int index, std::string const&amp; new_filename);
</pre>
<p>renames the file at <tt class="docutils literal">index</tt> to <tt class="docutils literal">new_filename</tt>. Keep in mind
that filenames are expected to be UTF-8 encoded.</p>
<a name="rename_file_borrow()"></a></div>
<div class="section" id="rename-file-borrow">
<h2>rename_file_borrow()</h2>
<pre class="literal-block">
void <strong>rename_file_borrow</strong> (int index, char const* new_filename, int len);
</pre>
<p>this is a low-level function that sets the name of a file
by making it reference a buffer that is not owned by the <a class="reference external" href="reference-Storage.html#file_storage">file_storage</a>.
it's an optimization used when loading .torrent files, to not
duplicate names in memory.</p>
<a name="map_block()"></a></div>
<div class="section" id="map-block">
<h2>map_block()</h2>
<pre class="literal-block">
std::vector&lt;file_slice&gt; <strong>map_block</strong> (int piece, size_type offset
, int size) const;
</pre>
<p>returns a list of <a class="reference external" href="reference-Storage.html#file_slice">file_slice</a> objects representing the portions of
files the specified piece index, byte offset and size range overlaps.
this is the inverse mapping of <a class="reference external" href="reference-Core.html#map_file()">map_file()</a>.</p>
<a name="map_file()"></a></div>
<div class="section" id="map-file">
<h2>map_file()</h2>
<pre class="literal-block">
peer_request <strong>map_file</strong> (int file, size_type offset, int size) const;
</pre>
<p>returns a <a class="reference external" href="reference-Core.html#peer_request">peer_request</a> representing the piece index, byte offset
and size the specified file range overlaps. This is the inverse
mapping ove <a class="reference external" href="reference-Core.html#map_block()">map_block()</a>.</p>
<a name="num_files()"></a></div>
<div class="section" id="num-files">
<h2>num_files()</h2>
<pre class="literal-block">
int <strong>num_files</strong> () const;
</pre>
<p>returns the number of files in the <a class="reference external" href="reference-Storage.html#file_storage">file_storage</a></p>
<a name="at()"></a></div>
<div class="section" id="at">
<h2>at()</h2>
<pre class="literal-block">
file_entry <strong>at</strong> (int index) const;
</pre>
<p>returns a <a class="reference external" href="reference-Storage.html#file_entry">file_entry</a> with information about the file
at <tt class="docutils literal">index</tt>. Index must be in the range [0, <tt class="docutils literal">num_files()</tt> ).</p>
<a name="total_size()"></a></div>
<div class="section" id="total-size">
<h2>total_size()</h2>
<pre class="literal-block">
size_type <strong>total_size</strong> () const;
</pre>
<p>returns the total number of bytes all the files in this torrent spans</p>
<a name="num_pieces()"></a>
<a name="set_num_pieces()"></a></div>
<div class="section" id="num-pieces-set-num-pieces">
<h2>num_pieces() set_num_pieces()</h2>
<pre class="literal-block">
void <strong>set_num_pieces</strong> (int n);
int <strong>num_pieces</strong> () const;
</pre>
<p>set and get the number of pieces in the torrent</p>
<a name="piece_length()"></a>
<a name="set_piece_length()"></a></div>
<div class="section" id="piece-length-set-piece-length">
<h2>piece_length() set_piece_length()</h2>
<pre class="literal-block">
void <strong>set_piece_length</strong> (int l);
int <strong>piece_length</strong> () const;
</pre>
<p>set and get the size of each piece in this torrent. This size is typically an even power
of 2. It doesn't have to be though. It should be divisible by 16kiB however.</p>
<a name="piece_size()"></a></div>
<div class="section" id="piece-size">
<h2>piece_size()</h2>
<pre class="literal-block">
int <strong>piece_size</strong> (int index) const;
</pre>
<p>returns the piece size of <tt class="docutils literal">index</tt>. This will be the same as <a class="reference external" href="reference-Core.html#piece_length()">piece_length()</a>, except
for the last piece, which may be shorter.</p>
<a name="set_name()"></a>
<a name="name()"></a></div>
<div class="section" id="set-name-name">
<h2>set_name() name()</h2>
<pre class="literal-block">
void <strong>set_name</strong> (std::string const&amp; n);
const std::string&amp; <strong>name</strong> () const;
</pre>
<p>set and get the name of this torrent. For multi-file torrents, this is also
the name of the root directory all the files are stored in.</p>
<a name="swap()"></a></div>
<div class="section" id="swap">
<h2>swap()</h2>
<pre class="literal-block">
void <strong>swap</strong> (file_storage&amp; ti);
</pre>
<p>swap all content of <em>this</em> with <em>ti</em>.</p>
<a name="optimize()"></a></div>
<div class="section" id="optimize">
<h2>optimize()</h2>
<pre class="literal-block">
void <strong>optimize</strong> (int pad_file_limit = -1, int alignment = -1);
</pre>
<p>if pad_file_limit &gt;= 0, files larger than that limit will be padded,
default is to not add any padding (-1). The alignment specifies the
alignment files should be padded to. This defaults to the piece size
(-1) but it may also make sense to set it to 16 kiB, or something
divisible by 16 kiB.
If pad_file_limit is 0, every file will be padded (except empty ones).</p>
<a name="mtime()"></a>
<a name="hash()"></a>
<a name="symlink()"></a>
<a name="file_name()"></a>
<a name="pad_file_at()"></a>
<a name="file_size()"></a>
<a name="file_path()"></a>
<a name="file_offset()"></a></div>
<div class="section" id="mtime-hash-symlink-file-name-pad-file-at-file-size-file-path-file-offset">
<h2>mtime() hash() symlink() file_name() pad_file_at() file_size() file_path() file_offset()</h2>
<pre class="literal-block">
size_type <strong>file_size</strong> (int index) const;
sha1_hash <strong>hash</strong> (int index) const;
std::string <strong>file_name</strong> (int index) const;
size_type <strong>file_offset</strong> (int index) const;
time_t <strong>mtime</strong> (int index) const;
bool <strong>pad_file_at</strong> (int index) const;
std::string const&amp; <strong>symlink</strong> (int index) const;
std::string <strong>file_path</strong> (int index, std::string const&amp; save_path = &quot;&quot;) const;
</pre>
<p>These functions are used to query attributes of files at
a given index.</p>
<p>The <tt class="docutils literal">file_hash()</tt> is a sha-1 hash of the file, or 0 if none was
provided in the torrent file. This can potentially be used to
join a bittorrent network with other file sharing networks.</p>
<p>The <tt class="docutils literal">mtime()</tt> is the modification time is the posix
time when a file was last modified when the torrent
was created, or 0 if it was not included in the torrent file.</p>
<p><tt class="docutils literal">file_path()</tt> returns the full path to a file.</p>
<p><tt class="docutils literal">file_size()</tt> returns the size of a file.</p>
<p><tt class="docutils literal">pad_file_at()</tt> returns true if the file at the given
index is a pad-file.</p>
<p><tt class="docutils literal">file_name()</tt> returns <em>just</em> the name of the file, whereas
<tt class="docutils literal">file_path()</tt> returns the path (inside the torrent file) with
the filename appended.</p>
<p><tt class="docutils literal">file_offset()</tt> returns the byte offset within the torrent file
where this file starts. It can be used to map the file to a piece
index (given the piece size).</p>
<a name="file_flags()"></a></div>
<div class="section" id="file-flags">
<h2>file_flags()</h2>
<pre class="literal-block">
int <strong>file_flags</strong> (int index) const;
</pre>
<p>returns a bitmask of flags from <a class="reference external" href="reference-Storage.html#file_flags_t">file_flags_t</a> that apply
to file at <tt class="docutils literal">index</tt>.</p>
<a name="file_base()"></a>
<a name="set_file_base()"></a></div>
<div class="section" id="file-base-set-file-base">
<h2>file_base() set_file_base()</h2>
<pre class="literal-block">
void <strong>set_file_base</strong> (int index, size_type off);
size_type <strong>file_base</strong> (int index) const;
</pre>
<p>The file base of a file is the offset within the file on the filsystem
where it starts to write. For the most part, this is always 0. It's
possible to map several files (in the torrent) into a single file on
the filesystem by making them all point to the same filename, but with
different file bases, so that they don't overlap.
<a class="reference external" href="reference-Core.html#remap_files()">torrent_info::remap_files()</a> can be used to use a new file layout.</p>
<a name="file_index_at_offset()"></a></div>
<div class="section" id="file-index-at-offset">
<h2>file_index_at_offset()</h2>
<pre class="literal-block">
int <strong>file_index_at_offset</strong> (size_type offset) const;
</pre>
<p>returns the index of the file at the given offset in the torrent</p>
<a name="file_name_len()"></a>
<a name="file_name_ptr()"></a></div>
<div class="section" id="file-name-len-file-name-ptr">
<h2>file_name_len() file_name_ptr()</h2>
<pre class="literal-block">
char const* <strong>file_name_ptr</strong> (int index) const;
int <strong>file_name_len</strong> (int index) const;
</pre>
<p>low-level function. returns a pointer to the internal storage for
the filename. This string may not be null terinated!
the <tt class="docutils literal">file_name_len()</tt> function returns the length of the filename.</p>
<a name="flags_t"></a></div>
<div class="section" id="enum-flags-t">
<h2>enum flags_t</h2>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/file_storage.hpp">libtorrent/file_storage.hpp</a>&quot;</p>
<table border="1" class="docutils">
<colgroup>
<col width="25%" />
<col width="8%" />
<col width="67%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">name</th>
<th class="head">value</th>
<th class="head">description</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>pad_file</td>
<td>1</td>
<td>the file is a pad file. It's required to contain zeroes
at it will not be saved to disk. Its purpose is to make
the following file start on a piece boundary.</td>
</tr>
<tr><td>attribute_hidden</td>
<td>2</td>
<td>this file has the hidden attribute set. This is primarily
a windows attribute</td>
</tr>
<tr><td>attribute_executable</td>
<td>4</td>
<td>this file has the executable attribute set.</td>
</tr>
<tr><td>attribute_symlink</td>
<td>8</td>
<td>this file is a symbilic link. It should have a link
target string associated with it.</td>
</tr>
</tbody>
</table>
<a name="file_flags_t"></a></div>
<div class="section" id="enum-file-flags-t">
<h2>enum file_flags_t</h2>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/file_storage.hpp">libtorrent/file_storage.hpp</a>&quot;</p>
<table border="1" class="docutils">
<colgroup>
<col width="23%" />
<col width="9%" />
<col width="68%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">name</th>
<th class="head">value</th>
<th class="head">description</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>flag_pad_file</td>
<td>1</td>
<td>this file is a pad file. The creator of the
torrent promises the file is entirely filled with
zeroes and does not need to be downloaded. The
purpose is just to align the next file to either
a block or piece boundary.</td>
</tr>
<tr><td>flag_hidden</td>
<td>2</td>
<td>this file is hiddent (sets the hidden attribute
on windows)</td>
</tr>
<tr><td>flag_executable</td>
<td>4</td>
<td>this file is executable (sets the executable bit
on posix like systems)</td>
</tr>
<tr><td>flag_symlink</td>
<td>8</td>
<td>this file is a symlink. The symlink target is
specified in a separate field</td>
</tr>
</tbody>
</table>
<a name="default_storage_constructor()"></a></div>
<div class="section" id="default-storage-constructor">
<h2>default_storage_constructor()</h2>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/storage_defs.hpp">libtorrent/storage_defs.hpp</a>&quot;</p>
<pre class="literal-block">
storage_interface* <strong>default_storage_constructor</strong> (
file_storage const&amp;, file_storage const* mapped, std::string const&amp;, file_pool&amp;
, std::vector&lt;boost::uint8_t&gt; const&amp;);
</pre>
<p>the constructor function for the regular file storage. This is the
default value for <a class="reference external" href="reference-Session.html#storage">add_torrent_params::storage</a>.</p>
<a name="disabled_storage_constructor()"></a></div>
<div class="section" id="disabled-storage-constructor">
<h2>disabled_storage_constructor()</h2>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/storage_defs.hpp">libtorrent/storage_defs.hpp</a>&quot;</p>
<pre class="literal-block">
storage_interface* <strong>disabled_storage_constructor</strong> (
file_storage const&amp;, file_storage const* mapped, std::string const&amp;, file_pool&amp;
, std::vector&lt;boost::uint8_t&gt; const&amp;);
</pre>
<p>the constructor function for the disabled storage. This can be used for
testing and benchmarking. It will throw away any data written to
it and return garbage for anything read from it.</p>
<a name="storage_mode_t"></a></div>
<div class="section" id="enum-storage-mode-t">
<h2>enum storage_mode_t</h2>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/storage_defs.hpp">libtorrent/storage_defs.hpp</a>&quot;</p>
<table border="1" class="docutils">
<colgroup>
<col width="22%" />
<col width="7%" />
<col width="72%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">name</th>
<th class="head">value</th>
<th class="head">description</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>storage_mode_allocate</td>
<td>0</td>
<td>All pieces will be written to their final position, all files will be
allocated in full when the torrent is first started. This is done with
<tt class="docutils literal">fallocate()</tt> and similar calls. This mode minimizes fragmentation.</td>
</tr>
<tr><td>storage_mode_sparse</td>
<td>1</td>
<td>All pieces will be written to the place where they belong and sparse files
will be used. This is the recommended, and default mode.</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>

View File

@ -1,158 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.11: http://docutils.sourceforge.net/" />
<title>String</title>
<meta name="author" content="Arvid Norberg, arvid&#64;rasterbar.com" />
<link rel="stylesheet" type="text/css" href="../../css/base.css" />
<link rel="stylesheet" type="text/css" href="../../css/rst.css" />
<script type="text/javascript">
/* <![CDATA[ */
(function() {
var s = document.createElement('script'), t = document.getElementsByTagName('script')[0];
s.type = 'text/javascript';
s.async = true;
s.src = 'http://api.flattr.com/js/0.6/load.js?mode=auto';
t.parentNode.insertBefore(s, t);
})();
/* ]]> */
</script>
<link rel="stylesheet" href="style.css" type="text/css" />
<style type="text/css">
/* Hides from IE-mac \*/
* html pre { height: 1%; }
/* End hide from IE-mac */
</style>
</head>
<body>
<div class="document" id="string">
<div id="container">
<div id="headerNav">
<ul>
<li class="first"><a href="/">Home</a></li>
<li><a href="../../products.html">Products</a></li>
<li><a href="../../contact.html">Contact</a></li>
</ul>
</div>
<div id="header">
<div id="orange"></div>
<div id="logo"></div>
</div>
<div id="main">
<h1 class="title">String</h1>
<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<tr><th class="docinfo-name">Author:</th>
<td>Arvid Norberg, <a class="last reference external" href="mailto:arvid&#64;rasterbar.com">arvid&#64;rasterbar.com</a></td></tr>
<tr><th class="docinfo-name">Version:</th>
<td>1.0.0</td></tr>
</tbody>
</table>
<div class="contents topic" id="table-of-contents">
<p class="topic-title first">Table of contents</p>
<ul class="simple">
<li><a class="reference internal" href="#to-hex" id="id9">to_hex()</a></li>
<li><a class="reference internal" href="#id2" id="id10">to_hex()</a></li>
<li><a class="reference internal" href="#from-hex" id="id11">from_hex()</a></li>
<li><a class="reference internal" href="#is-digit" id="id12">is_digit()</a></li>
<li><a class="reference internal" href="#utf8-wchar-wchar-utf8" id="id13">utf8_wchar() wchar_utf8()</a></li>
<li><a class="reference internal" href="#enum-utf8-conv-result-t" id="id14">enum utf8_conv_result_t</a></li>
</ul>
</div>
<a name="to_hex()"></a><div class="section" id="to-hex">
<h1>to_hex()</h1>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/escape_string.hpp">libtorrent/escape_string.hpp</a>&quot;</p>
<pre class="literal-block">
std::string <strong>to_hex</strong> (std::string const&amp; s);
</pre>
<p>converts (binary) the string <tt class="docutils literal">s</tt> to hexadecimal representation and
returns it.</p>
<a name="to_hex()"></a></div>
<div class="section" id="id2">
<h1>to_hex()</h1>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/escape_string.hpp">libtorrent/escape_string.hpp</a>&quot;</p>
<pre class="literal-block">
void <strong>to_hex</strong> (char const *in, int len, char* out);
</pre>
<p>converts the binary buffer [<tt class="docutils literal">in</tt>, <tt class="docutils literal">in</tt> + len) to hexadecimal
and prints it to the buffer <tt class="docutils literal">out</tt>. The caller is responsible for
making sure the buffer pointed to by <tt class="docutils literal">out</tt> is large enough,
i.e. has at least len * 2 bytes of space.</p>
<a name="from_hex()"></a></div>
<div class="section" id="from-hex">
<h1>from_hex()</h1>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/escape_string.hpp">libtorrent/escape_string.hpp</a>&quot;</p>
<pre class="literal-block">
bool <strong>from_hex</strong> (char const *in, int len, char* out);
</pre>
<p>converts the buffer [<tt class="docutils literal">in</tt>, <tt class="docutils literal">in</tt> + len) from hexadecimal to
binary. The binary output is written to the buffer pointed to
by <tt class="docutils literal">out</tt>. The caller is responsible for making sure the buffer
at <tt class="docutils literal">out</tt> has enough space for the result to be written to, i.e.
(len + 1) / 2 bytes.</p>
<a name="is_digit()"></a></div>
<div class="section" id="is-digit">
<h1>is_digit()</h1>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/string_util.hpp">libtorrent/string_util.hpp</a>&quot;</p>
<pre class="literal-block">
bool <strong>is_digit</strong> (char c);
</pre>
<p>this is used by bdecode_recursive's header file</p>
<a name="utf8_wchar()"></a>
<a name="wchar_utf8()"></a></div>
<div class="section" id="utf8-wchar-wchar-utf8">
<h1>utf8_wchar() wchar_utf8()</h1>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/utf8.hpp">libtorrent/utf8.hpp</a>&quot;</p>
<pre class="literal-block">
utf8_conv_result_t <strong>wchar_utf8</strong> (
const std::wstring &amp;wide, std::string &amp;utf8);
utf8_conv_result_t <strong>utf8_wchar</strong> (
const std::string &amp;utf8, std::wstring &amp;wide);
</pre>
<p><tt class="docutils literal">utf8_wchar</tt> converts a UTF-8 string (<tt class="docutils literal">utf8</tt>) to a wide character
string (<tt class="docutils literal">wide</tt>). <tt class="docutils literal">wchar_utf8</tt> converts a wide character string
(<tt class="docutils literal">wide</tt>) to a UTF-8 string (<tt class="docutils literal">utf8</tt>). The return value is one of
the enumeration values from <a class="reference external" href="reference-String.html#utf8_conv_result_t">utf8_conv_result_t</a>.</p>
<a name="utf8_conv_result_t"></a></div>
<div class="section" id="enum-utf8-conv-result-t">
<h1>enum utf8_conv_result_t</h1>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/utf8.hpp">libtorrent/utf8.hpp</a>&quot;</p>
<table border="1" class="docutils">
<colgroup>
<col width="27%" />
<col width="10%" />
<col width="63%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">name</th>
<th class="head">value</th>
<th class="head">description</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>conversion_ok</td>
<td>0</td>
<td>conversion successful</td>
</tr>
<tr><td>source_exhausted</td>
<td>1</td>
<td>partial character in source, but hit end</td>
</tr>
<tr><td>target_exhausted</td>
<td>2</td>
<td>insuff. room in target for conversion</td>
</tr>
<tr><td>source_illegal</td>
<td>3</td>
<td>source sequence is illegal/malformed</td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
</html>

View File

@ -1,236 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.11: http://docutils.sourceforge.net/" />
<title>Time</title>
<meta name="author" content="Arvid Norberg, arvid&#64;rasterbar.com" />
<link rel="stylesheet" type="text/css" href="../../css/base.css" />
<link rel="stylesheet" type="text/css" href="../../css/rst.css" />
<script type="text/javascript">
/* <![CDATA[ */
(function() {
var s = document.createElement('script'), t = document.getElementsByTagName('script')[0];
s.type = 'text/javascript';
s.async = true;
s.src = 'http://api.flattr.com/js/0.6/load.js?mode=auto';
t.parentNode.insertBefore(s, t);
})();
/* ]]> */
</script>
<link rel="stylesheet" href="style.css" type="text/css" />
<style type="text/css">
/* Hides from IE-mac \*/
* html pre { height: 1%; }
/* End hide from IE-mac */
</style>
</head>
<body>
<div class="document" id="time">
<div id="container">
<div id="headerNav">
<ul>
<li class="first"><a href="/">Home</a></li>
<li><a href="../../products.html">Products</a></li>
<li><a href="../../contact.html">Contact</a></li>
</ul>
</div>
<div id="header">
<div id="orange"></div>
<div id="logo"></div>
</div>
<div id="main">
<h1 class="title">Time</h1>
<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<tr><th class="docinfo-name">Author:</th>
<td>Arvid Norberg, <a class="last reference external" href="mailto:arvid&#64;rasterbar.com">arvid&#64;rasterbar.com</a></td></tr>
<tr><th class="docinfo-name">Version:</th>
<td>1.0.0</td></tr>
</tbody>
</table>
<div class="contents topic" id="table-of-contents">
<p class="topic-title first">Table of contents</p>
<ul class="simple">
<li><a class="reference internal" href="#time-duration" id="id18">time_duration</a></li>
<li><a class="reference internal" href="#ptime" id="id19">ptime</a></li>
</ul>
</div>
<p>This section contains fundamental time types used internally by
libtorrent and exposed through various places in the API. The two
basic types are <tt class="docutils literal">ptime</tt> and <tt class="docutils literal">time_duration</tt>. The first represents
a point in time and the second the difference between two points
in time.</p>
<p>The internal representation of these types is implementation defined
and they can only be constructed via one of the construction functions
that take a well defined time unit (seconds, minutes, etc.). They can
only be turned into well defined time units by the accessor functions
(<a class="reference external" href="reference-Time.html#total_microseconds()">total_microseconds()</a>, etc.).</p>
<div class="note">
<p class="first admonition-title">Note</p>
<p class="last">In a future version of libtorrent, these types will be replaced
by the standard timer types from <tt class="docutils literal"><span class="pre">std::chrono</span></tt>.</p>
</div>
<a name="time_duration"></a><div class="section" id="time-duration">
<h1>time_duration</h1>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/ptime.hpp">libtorrent/ptime.hpp</a>&quot;</p>
<p>libtorrent <a class="reference external" href="reference-Time.html#time_duration">time_duration</a> type</p>
<pre class="literal-block">
struct time_duration
{
time_duration&amp; <strong>operator-=</strong> (time_duration const&amp; c);
time_duration <strong>operator+</strong> (time_duration const&amp; c);
time_duration&amp; <strong>operator+=</strong> (time_duration const&amp; c);
time_duration <strong>operator/</strong> (int rhs) const;
explicit <strong>time_duration</strong> (boost::int64_t d);
time_duration <strong>operator-</strong> (time_duration const&amp; c);
time_duration&amp; <strong>operator*=</strong> (int v);
};
</pre>
<a name="operator+=()"></a>
<a name="time_duration()"></a>
<a name="operator*=()"></a>
<a name="operator-=()"></a>
<a name="operator+()"></a>
<a name="operator/()"></a>
<a name="operator-()"></a><div class="section" id="operator-time-duration-operator-operator-operator-operator-operator">
<h2>operator+=() time_duration() operator*=() operator-=() operator+() operator/() operator-()</h2>
<pre class="literal-block">
time_duration&amp; <strong>operator-=</strong> (time_duration const&amp; c);
time_duration <strong>operator+</strong> (time_duration const&amp; c);
time_duration&amp; <strong>operator+=</strong> (time_duration const&amp; c);
time_duration <strong>operator/</strong> (int rhs) const;
explicit <strong>time_duration</strong> (boost::int64_t d);
time_duration <strong>operator-</strong> (time_duration const&amp; c);
time_duration&amp; <strong>operator*=</strong> (int v);
</pre>
<p>all operators have the same semantics as a 64 bit signed integer</p>
<a name="ptime"></a></div>
</div>
<div class="section" id="ptime">
<h1>ptime</h1>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/ptime.hpp">libtorrent/ptime.hpp</a>&quot;</p>
<p>This type represents a point in time.</p>
<pre class="literal-block">
struct ptime
{
ptime&amp; <strong>operator-=</strong> (time_duration rhs);
ptime&amp; <strong>operator+=</strong> (time_duration rhs);
};
</pre>
<a name="operator+=()"></a>
<a name="operator-=()"></a><div class="section" id="operator-operator">
<h2>operator+=() operator-=()</h2>
<pre class="literal-block">
ptime&amp; <strong>operator-=</strong> (time_duration rhs);
ptime&amp; <strong>operator+=</strong> (time_duration rhs);
</pre>
<p>these operators have the same semantics as signed 64 bit integers</p>
<a name="is_negative()"></a></div>
<div class="section" id="is-negative">
<h2>is_negative()</h2>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/ptime.hpp">libtorrent/ptime.hpp</a>&quot;</p>
<pre class="literal-block">
inline bool <strong>is_negative</strong> (time_duration dt);
</pre>
<p>returns true of the time duration is less than 0</p>
<a name="operator*()"></a>
<a name="operator>=()"></a>
<a name="operator!=()"></a>
<a name="operator>()"></a>
<a name="operator<()"></a>
<a name="operator==()"></a>
<a name="operator+()"></a>
<a name="operator<=()"></a>
<a name="operator-()"></a></div>
<div class="section" id="operator-operator-operator-operator-operator-operator-operator-operator-operator">
<h2>operator*() operator&gt;=() operator!=() operator&gt;() operator&lt;() operator==() operator+() operator&lt;=() operator-()</h2>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/ptime.hpp">libtorrent/ptime.hpp</a>&quot;</p>
<pre class="literal-block">
inline time_duration <strong>operator*</strong> (int lhs, time_duration rhs);
inline bool <strong>operator==</strong> (time_duration lhs, time_duration rhs);
inline bool <strong>operator&lt;=</strong> (time_duration lhs, time_duration rhs);
inline bool <strong>operator==</strong> (ptime lhs, ptime rhs);
inline bool <strong>operator&gt;=</strong> (time_duration lhs, time_duration rhs);
inline bool <strong>operator&lt;</strong> (time_duration lhs, time_duration rhs);
inline bool <strong>operator&gt;</strong> (time_duration lhs, time_duration rhs);
inline bool <strong>operator&gt;</strong> (ptime lhs, ptime rhs);
inline ptime <strong>operator+</strong> (time_duration lhs, ptime rhs);
inline ptime <strong>operator+</strong> (ptime lhs, time_duration rhs);
inline time_duration <strong>operator*</strong> (time_duration lhs, int rhs);
inline time_duration <strong>operator-</strong> (ptime lhs, ptime rhs);
inline bool <strong>operator&lt;=</strong> (ptime lhs, ptime rhs);
inline bool <strong>operator!=</strong> (ptime lhs, ptime rhs);
inline bool <strong>operator&lt;</strong> (ptime lhs, ptime rhs);
inline bool <strong>operator&gt;=</strong> (ptime lhs, ptime rhs);
inline ptime <strong>operator-</strong> (ptime lhs, time_duration rhs);
</pre>
<p>all operators have the same semantics as signed 64 bit integers</p>
<a name="time_now()"></a></div>
<div class="section" id="time-now">
<h2>time_now()</h2>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/time.hpp">libtorrent/time.hpp</a>&quot;</p>
<pre class="literal-block">
ptime const&amp; <strong>time_now</strong> ();
</pre>
<p>returns the current time, as represented by <a class="reference external" href="reference-Time.html#ptime">ptime</a>. The
resolution of this timer is about 100 ms.</p>
<a name="time_now_hires()"></a></div>
<div class="section" id="time-now-hires">
<h2>time_now_hires()</h2>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/time.hpp">libtorrent/time.hpp</a>&quot;</p>
<pre class="literal-block">
ptime <strong>time_now_hires</strong> ();
</pre>
<p>returns the current time as represented by <a class="reference external" href="reference-Time.html#ptime">ptime</a>. This is
more expensive than <a class="reference external" href="reference-Time.html#time_now()">time_now()</a>, but provides as high resolution
as the operating system can provide.</p>
<a name="min_time()"></a>
<a name="max_time()"></a></div>
<div class="section" id="min-time-max-time">
<h2>min_time() max_time()</h2>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/time.hpp">libtorrent/time.hpp</a>&quot;</p>
<pre class="literal-block">
ptime <strong>max_time</strong> ();
ptime <strong>min_time</strong> ();
</pre>
<p>the earliest and latest possible time points
representable by <a class="reference external" href="reference-Time.html#ptime">ptime</a>.</p>
<a name="microsec()"></a>
<a name="minutes()"></a>
<a name="hours()"></a>
<a name="milliseconds()"></a>
<a name="seconds()"></a></div>
<div class="section" id="microsec-minutes-hours-milliseconds-seconds">
<h2>microsec() minutes() hours() milliseconds() seconds()</h2>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/time.hpp">libtorrent/time.hpp</a>&quot;</p>
<pre class="literal-block">
time_duration <strong>microsec</strong> (boost::int64_t s);
time_duration <strong>seconds</strong> (boost::int64_t s);
time_duration <strong>milliseconds</strong> (boost::int64_t s);
time_duration <strong>minutes</strong> (boost::int64_t s);
time_duration <strong>hours</strong> (boost::int64_t s);
</pre>
<p>returns a <a class="reference external" href="reference-Time.html#time_duration">time_duration</a> representing the specified number of seconds, milliseconds
microseconds, minutes and hours.</p>
<a name="total_seconds()"></a>
<a name="total_microseconds()"></a>
<a name="total_milliseconds()"></a></div>
<div class="section" id="total-seconds-total-microseconds-total-milliseconds">
<h2>total_seconds() total_microseconds() total_milliseconds()</h2>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/time.hpp">libtorrent/time.hpp</a>&quot;</p>
<pre class="literal-block">
boost::int64_t <strong>total_seconds</strong> (time_duration td);
boost::int64_t <strong>total_milliseconds</strong> (time_duration td);
boost::int64_t <strong>total_microseconds</strong> (time_duration td);
</pre>
<p>returns the number of seconds, milliseconds and microseconds
a <a class="reference external" href="reference-Time.html#time_duration">time_duration</a> represents.</p>
</div>
</div>
</div>
</body>
</html>

View File

@ -1,430 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.11: http://docutils.sourceforge.net/" />
<title>Utility</title>
<meta name="author" content="Arvid Norberg, arvid&#64;rasterbar.com" />
<link rel="stylesheet" type="text/css" href="../../css/base.css" />
<link rel="stylesheet" type="text/css" href="../../css/rst.css" />
<script type="text/javascript">
/* <![CDATA[ */
(function() {
var s = document.createElement('script'), t = document.getElementsByTagName('script')[0];
s.type = 'text/javascript';
s.async = true;
s.src = 'http://api.flattr.com/js/0.6/load.js?mode=auto';
t.parentNode.insertBefore(s, t);
})();
/* ]]> */
</script>
<link rel="stylesheet" href="style.css" type="text/css" />
<style type="text/css">
/* Hides from IE-mac \*/
* html pre { height: 1%; }
/* End hide from IE-mac */
</style>
</head>
<body>
<div class="document" id="utility">
<div id="container">
<div id="headerNav">
<ul>
<li class="first"><a href="/">Home</a></li>
<li><a href="../../products.html">Products</a></li>
<li><a href="../../contact.html">Contact</a></li>
</ul>
</div>
<div id="header">
<div id="orange"></div>
<div id="logo"></div>
</div>
<div id="main">
<h1 class="title">Utility</h1>
<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<tr><th class="docinfo-name">Author:</th>
<td>Arvid Norberg, <a class="last reference external" href="mailto:arvid&#64;rasterbar.com">arvid&#64;rasterbar.com</a></td></tr>
<tr><th class="docinfo-name">Version:</th>
<td>1.0.0</td></tr>
</tbody>
</table>
<div class="contents topic" id="table-of-contents">
<p class="topic-title first">Table of contents</p>
<ul class="simple">
<li><a class="reference internal" href="#bitfield" id="id39">bitfield</a></li>
<li><a class="reference internal" href="#sha1-hash" id="id40">sha1_hash</a></li>
</ul>
</div>
<a name="bitfield"></a><div class="section" id="bitfield">
<h1>bitfield</h1>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/bitfield.hpp">libtorrent/bitfield.hpp</a>&quot;</p>
<p>The bitfiled type stores any number of bits as a <a class="reference external" href="reference-Utility.html#bitfield">bitfield</a>
in a heap allocated or borrowed array.</p>
<pre class="literal-block">
struct bitfield
{
<strong>bitfield</strong> (int bits);
<strong>bitfield</strong> (bitfield const&amp; rhs);
<strong>bitfield</strong> (bitfield&amp;&amp; rhs);
<strong>bitfield</strong> (int bits, bool val);
<strong>bitfield</strong> ();
<strong>bitfield</strong> (char const* b, int bits);
void <strong>borrow_bytes</strong> (char* b, int bits);
void <strong>assign</strong> (char const* b, int bits);
bool <strong>get_bit</strong> (int index) const;
bool <strong>operator[]</strong> (int index) const;
void <strong>clear_bit</strong> (int index);
void <strong>set_bit</strong> (int index);
bool <strong>all_set</strong> () const;
std::size_t <strong>size</strong> () const;
bool <strong>empty</strong> () const;
char const* <strong>bytes</strong> () const;
bitfield&amp; <strong>operator=</strong> (bitfield const&amp; rhs);
int <strong>count</strong> () const;
};
</pre>
<a name="bitfield()"></a><div class="section" id="id3">
<h2>bitfield()</h2>
<pre class="literal-block">
<strong>bitfield</strong> (int bits);
<strong>bitfield</strong> (bitfield const&amp; rhs);
<strong>bitfield</strong> (bitfield&amp;&amp; rhs);
<strong>bitfield</strong> (int bits, bool val);
<strong>bitfield</strong> ();
<strong>bitfield</strong> (char const* b, int bits);
</pre>
<p>constructs a new <a class="reference external" href="reference-Utility.html#bitfield">bitfield</a>. The default constructor creates an empty
<a class="reference external" href="reference-Utility.html#bitfield">bitfield</a>. <tt class="docutils literal">bits</tt> is the size of the <a class="reference external" href="reference-Utility.html#bitfield">bitfield</a> (specified in bits).
<tt class="docutils literal">val</tt> is the value to initialize the bits to. If not specified
all bits are initialized to 0.</p>
<p>The constructor taking a pointer <tt class="docutils literal">b</tt> and <tt class="docutils literal">bits</tt> copies a <a class="reference external" href="reference-Utility.html#bitfield">bitfield</a>
from the specified buffer, and <tt class="docutils literal">bits</tt> number of bits (rounded up to
the nearest byte boundry).</p>
<a name="borrow_bytes()"></a></div>
<div class="section" id="borrow-bytes">
<h2>borrow_bytes()</h2>
<pre class="literal-block">
void <strong>borrow_bytes</strong> (char* b, int bits);
</pre>
<p>assigns a <a class="reference external" href="reference-Utility.html#bitfield">bitfield</a> pointed to <tt class="docutils literal">b</tt> of <tt class="docutils literal">bits</tt> number of bits, without
taking ownership of the buffer. This is a way to avoid copying data and
yet provide a raw buffer to functions that may operate on the <a class="reference external" href="reference-Utility.html#bitfield">bitfield</a>
type. It is the user's responsibility to make sure the passed-in buffer's
life time exceeds all uses of the <a class="reference external" href="reference-Utility.html#bitfield">bitfield</a>.</p>
<a name="assign()"></a></div>
<div class="section" id="assign">
<h2>assign()</h2>
<pre class="literal-block">
void <strong>assign</strong> (char const* b, int bits);
</pre>
<p>copy <a class="reference external" href="reference-Utility.html#bitfield">bitfield</a> from buffer <tt class="docutils literal">b</tt> of <tt class="docutils literal">bits</tt> number of bits, rounded up to
the nearest byte boundary.</p>
<a name="operator[]()"></a>
<a name="get_bit()"></a></div>
<div class="section" id="operator-get-bit">
<h2>operator[]() get_bit()</h2>
<pre class="literal-block">
bool <strong>get_bit</strong> (int index) const;
bool <strong>operator[]</strong> (int index) const;
</pre>
<p>query bit at <tt class="docutils literal">index</tt>. Returns true if bit is 1, otherwise false.</p>
<a name="set_bit()"></a>
<a name="clear_bit()"></a></div>
<div class="section" id="set-bit-clear-bit">
<h2>set_bit() clear_bit()</h2>
<pre class="literal-block">
void <strong>clear_bit</strong> (int index);
void <strong>set_bit</strong> (int index);
</pre>
<p>set bit at <tt class="docutils literal">index</tt> to 0 (clear_bit) or 1 (set_bit).</p>
<a name="all_set()"></a></div>
<div class="section" id="all-set">
<h2>all_set()</h2>
<pre class="literal-block">
bool <strong>all_set</strong> () const;
</pre>
<p>returns true if all bits in the <a class="reference external" href="reference-Utility.html#bitfield">bitfield</a> are set</p>
<a name="size()"></a></div>
<div class="section" id="size">
<h2>size()</h2>
<pre class="literal-block">
std::size_t <strong>size</strong> () const;
</pre>
<p>returns the size of the <a class="reference external" href="reference-Utility.html#bitfield">bitfield</a> in bits.</p>
<a name="empty()"></a></div>
<div class="section" id="empty">
<h2>empty()</h2>
<pre class="literal-block">
bool <strong>empty</strong> () const;
</pre>
<p>returns true if the <a class="reference external" href="reference-Utility.html#bitfield">bitfield</a> has zero size.</p>
<a name="bytes()"></a></div>
<div class="section" id="bytes">
<h2>bytes()</h2>
<pre class="literal-block">
char const* <strong>bytes</strong> () const;
</pre>
<p>returns a pointer to the internal buffer of the <a class="reference external" href="reference-Utility.html#bitfield">bitfield</a>.</p>
<a name="operator=()"></a></div>
<div class="section" id="operator">
<h2>operator=()</h2>
<pre class="literal-block">
bitfield&amp; <strong>operator=</strong> (bitfield const&amp; rhs);
</pre>
<p>copy operator</p>
<a name="count()"></a></div>
<div class="section" id="count">
<h2>count()</h2>
<pre class="literal-block">
int <strong>count</strong> () const;
</pre>
<p>count the number of bits in the <a class="reference external" href="reference-Utility.html#bitfield">bitfield</a> that are set to 1.</p>
<a name="sha1_hash"></a></div>
</div>
<div class="section" id="sha1-hash">
<h1>sha1_hash</h1>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/sha1_hash.hpp">libtorrent/sha1_hash.hpp</a>&quot;</p>
<p>This type holds a SHA-1 digest or any other kind of 20 byte
sequence. It implements a number of convenience functions, such
as bit operations, comparison operators etc.</p>
<p>In libtorrent it is primarily used to hold info-hashes, piece-hashes,
peer IDs, node IDs etc.</p>
<pre class="literal-block">
class sha1_hash
{
<strong>sha1_hash</strong> ();
static sha1_hash <strong>max</strong> ();
static sha1_hash <strong>min</strong> ();
explicit <strong>sha1_hash</strong> (char const* s);
void <strong>assign</strong> (char const* str);
explicit <strong>sha1_hash</strong> (std::string const&amp; s);
void <strong>assign</strong> (std::string const&amp; s);
void <strong>clear</strong> ();
bool <strong>is_all_zeros</strong> () const;
sha1_hash&amp; <strong>operator&lt;&lt;=</strong> (int n);
sha1_hash&amp; <strong>operator&gt;&gt;=</strong> (int n);
bool <strong>operator!=</strong> (sha1_hash const&amp; n) const;
bool <strong>operator&lt;</strong> (sha1_hash const&amp; n) const;
bool <strong>operator==</strong> (sha1_hash const&amp; n) const;
sha1_hash <strong>operator~</strong> ();
sha1_hash <strong>operator^</strong> (sha1_hash const&amp; n) const;
sha1_hash&amp; <strong>operator^=</strong> (sha1_hash const&amp; n);
sha1_hash <strong>operator&amp;</strong> (sha1_hash const&amp; n) const;
sha1_hash&amp; <strong>operator&amp;=</strong> (sha1_hash const&amp; n);
sha1_hash&amp; <strong>operator|=</strong> (sha1_hash const&amp; n);
unsigned char&amp; <strong>operator[]</strong> (int i);
unsigned char const&amp; <strong>operator[]</strong> (int i) const;
const_iterator <strong>begin</strong> () const;
iterator <strong>begin</strong> ();
iterator <strong>end</strong> ();
const_iterator <strong>end</strong> () const;
std::string <strong>to_string</strong> () const;
static const int size = number_size;
};
</pre>
<a name="sha1_hash()"></a><div class="section" id="id18">
<h2>sha1_hash()</h2>
<pre class="literal-block">
<strong>sha1_hash</strong> ();
</pre>
<p>constructs an all-sero sha1-hash</p>
<a name="max()"></a></div>
<div class="section" id="max">
<h2>max()</h2>
<pre class="literal-block">
static sha1_hash <strong>max</strong> ();
</pre>
<p>returns an all-F sha1-hash. i.e. the maximum value
representable by a 160 bit number (20 bytes). This is
a static member function.</p>
<a name="min()"></a></div>
<div class="section" id="min">
<h2>min()</h2>
<pre class="literal-block">
static sha1_hash <strong>min</strong> ();
</pre>
<p>returns an all-zero sha1-hash. i.e. the minimum value
representable by a 160 bit number (20 bytes). This is
a static member function.</p>
<a name="assign()"></a>
<a name="sha1_hash()"></a></div>
<div class="section" id="assign-sha1-hash">
<h2>assign() sha1_hash()</h2>
<pre class="literal-block">
explicit <strong>sha1_hash</strong> (char const* s);
void <strong>assign</strong> (char const* str);
explicit <strong>sha1_hash</strong> (std::string const&amp; s);
void <strong>assign</strong> (std::string const&amp; s);
</pre>
<p>copies 20 bytes from the pointer provided, into the sha1-hash.
The passed in string MUST be at least 20 bytes. NULL terminators
are ignored, <tt class="docutils literal">s</tt> is treated like a raw memory buffer.</p>
<a name="clear()"></a></div>
<div class="section" id="clear">
<h2>clear()</h2>
<pre class="literal-block">
void <strong>clear</strong> ();
</pre>
<p>set the sha1-hash to all zeroes.</p>
<a name="is_all_zeros()"></a></div>
<div class="section" id="is-all-zeros">
<h2>is_all_zeros()</h2>
<pre class="literal-block">
bool <strong>is_all_zeros</strong> () const;
</pre>
<p>return true if the sha1-hash is all zero.</p>
<a name="operator<<=()"></a></div>
<div class="section" id="id19">
<h2>operator&lt;&lt;=()</h2>
<pre class="literal-block">
sha1_hash&amp; <strong>operator&lt;&lt;=</strong> (int n);
</pre>
<p>shift left <tt class="docutils literal">n</tt> bits.</p>
<a name="operator>>=()"></a></div>
<div class="section" id="id20">
<h2>operator&gt;&gt;=()</h2>
<pre class="literal-block">
sha1_hash&amp; <strong>operator&gt;&gt;=</strong> (int n);
</pre>
<p>shift r <tt class="docutils literal">n</tt> bits.</p>
<a name="operator!=()"></a>
<a name="operator<()"></a>
<a name="operator==()"></a></div>
<div class="section" id="operator-operator-operator">
<h2>operator!=() operator&lt;() operator==()</h2>
<pre class="literal-block">
bool <strong>operator!=</strong> (sha1_hash const&amp; n) const;
bool <strong>operator&lt;</strong> (sha1_hash const&amp; n) const;
bool <strong>operator==</strong> (sha1_hash const&amp; n) const;
</pre>
<p>standard comparison operators</p>
<a name="operator~()"></a></div>
<div class="section" id="id21">
<h2>operator~()</h2>
<pre class="literal-block">
sha1_hash <strong>operator~</strong> ();
</pre>
<p>returns a bit-wise negated copy of the sha1-hash</p>
<a name="operator^()"></a></div>
<div class="section" id="id22">
<h2>operator^()</h2>
<pre class="literal-block">
sha1_hash <strong>operator^</strong> (sha1_hash const&amp; n) const;
</pre>
<p>returns the bit-wise XOR of the two sha1-hashes.</p>
<a name="operator^=()"></a></div>
<div class="section" id="id23">
<h2>operator^=()</h2>
<pre class="literal-block">
sha1_hash&amp; <strong>operator^=</strong> (sha1_hash const&amp; n);
</pre>
<p>in-place bit-wise XOR with the passed in <a class="reference external" href="reference-Utility.html#sha1_hash">sha1_hash</a>.</p>
<a name="operator&()"></a></div>
<div class="section" id="id25">
<h2>operator&amp;()</h2>
<pre class="literal-block">
sha1_hash <strong>operator&amp;</strong> (sha1_hash const&amp; n) const;
</pre>
<p>returns the bit-wise AND of the two sha1-hashes.</p>
<a name="operator&=()"></a></div>
<div class="section" id="id26">
<h2>operator&amp;=()</h2>
<pre class="literal-block">
sha1_hash&amp; <strong>operator&amp;=</strong> (sha1_hash const&amp; n);
</pre>
<p>in-place bit-wise AND of the passed in <a class="reference external" href="reference-Utility.html#sha1_hash">sha1_hash</a></p>
<a name="operator|=()"></a></div>
<div class="section" id="id28">
<h2>operator|=()</h2>
<pre class="literal-block">
sha1_hash&amp; <strong>operator|=</strong> (sha1_hash const&amp; n);
</pre>
<p>in-place bit-wise OR of the two sha1-hash.</p>
<a name="operator[]()"></a></div>
<div class="section" id="id29">
<h2>operator[]()</h2>
<pre class="literal-block">
unsigned char&amp; <strong>operator[]</strong> (int i);
unsigned char const&amp; <strong>operator[]</strong> (int i) const;
</pre>
<p>accessors for specific bytes</p>
<a name="begin()"></a>
<a name="end()"></a></div>
<div class="section" id="begin-end">
<h2>begin() end()</h2>
<pre class="literal-block">
const_iterator <strong>begin</strong> () const;
iterator <strong>begin</strong> ();
iterator <strong>end</strong> ();
const_iterator <strong>end</strong> () const;
</pre>
<p>start and end iterators for the hash. The value type
of these iterators is <tt class="docutils literal">unsigned char</tt>.</p>
<a name="to_string()"></a></div>
<div class="section" id="to-string">
<h2>to_string()</h2>
<pre class="literal-block">
std::string <strong>to_string</strong> () const;
</pre>
<p>return a copy of the 20 bytes representing the sha1-hash as a std::string.
It's still a binary string with 20 binary characters.</p>
<a name="number_size"></a><dl class="docutils">
<dt>number_size</dt>
<dd>the number of bytes of the number</dd>
</dl>
<a name="identify_client()"></a></div>
<div class="section" id="identify-client">
<h2>identify_client()</h2>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/identify_client.hpp">libtorrent/identify_client.hpp</a>&quot;</p>
<pre class="literal-block">
std::string <strong>identify_client</strong> (const peer_id&amp; p);
</pre>
<p>This function can can be used to extract a string describing a client
version from its peer-id. It will recognize most clients that have this
kind of identification in the peer-id.</p>
<a name="client_fingerprint()"></a></div>
<div class="section" id="client-fingerprint">
<h2>client_fingerprint()</h2>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/identify_client.hpp">libtorrent/identify_client.hpp</a>&quot;</p>
<pre class="literal-block">
boost::optional&lt;fingerprint&gt; <strong>client_fingerprint</strong> (peer_id const&amp; p);
</pre>
<p>Returns an optional fingerprint if any can be identified from the peer
id. This can be used to automate the identification of clients. It will
not be able to identify peers with non- standard encodings. Only Azureus
style, Shadow's style and Mainline style.</p>
<a name="operator<<()"></a></div>
<div class="section" id="id32">
<h2>operator&lt;&lt;()</h2>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/sha1_hash.hpp">libtorrent/sha1_hash.hpp</a>&quot;</p>
<pre class="literal-block">
inline std::ostream&amp; <strong>operator&lt;&lt;</strong> (std::ostream&amp; os, sha1_hash const&amp; peer);
</pre>
<p>print a <a class="reference external" href="reference-Utility.html#sha1_hash">sha1_hash</a> object to an ostream as 40 hexadecimal digits</p>
<a name="operator>>()"></a></div>
<div class="section" id="id35">
<h2>operator&gt;&gt;()</h2>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/sha1_hash.hpp">libtorrent/sha1_hash.hpp</a>&quot;</p>
<pre class="literal-block">
inline std::istream&amp; <strong>operator&gt;&gt;</strong> (std::istream&amp; is, sha1_hash&amp; peer);
</pre>
<p>read 40 hexadecimal digits from an istream into a <a class="reference external" href="reference-Utility.html#sha1_hash">sha1_hash</a></p>
<a name="sleep()"></a></div>
<div class="section" id="sleep">
<h2>sleep()</h2>
<p>Declared in &quot;<a class="reference external" href="../include/libtorrent/thread.hpp">libtorrent/thread.hpp</a>&quot;</p>
<pre class="literal-block">
void <strong>sleep</strong> (int milliseconds);
</pre>
<p>pauses the calling thread at least for the specified
number of milliseconds</p>
</div>
</div>
</div>
</body>
</html>

View File

@ -1,322 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.11: http://docutils.sourceforge.net/" />
<title>libtorrent reference documentation</title>
<link rel="stylesheet" type="text/css" href="../../css/base.css" />
<link rel="stylesheet" type="text/css" href="../../css/rst.css" />
<script type="text/javascript">
/* <![CDATA[ */
(function() {
var s = document.createElement('script'), t = document.getElementsByTagName('script')[0];
s.type = 'text/javascript';
s.async = true;
s.src = 'http://api.flattr.com/js/0.6/load.js?mode=auto';
t.parentNode.insertBefore(s, t);
})();
/* ]]> */
</script>
<link rel="stylesheet" href="style.css" type="text/css" />
<style type="text/css">
/* Hides from IE-mac \*/
* html pre { height: 1%; }
/* End hide from IE-mac */
</style>
</head>
<body>
<div class="document" id="libtorrent-reference-documentation">
<div id="container">
<div id="headerNav">
<ul>
<li class="first"><a href="/">Home</a></li>
<li><a href="../../products.html">Products</a></li>
<li><a href="../../contact.html">Contact</a></li>
</ul>
</div>
<div id="header">
<div id="orange"></div>
<div id="logo"></div>
</div>
<div id="main">
<h1 class="title">libtorrent reference documentation</h1>
<div style="column-count: 4; -webkit-column-count: 4; -moz-column-count: 4"><div class="section" id="custom-storage">
<h1>Custom Storage</h1>
<div class="line-block">
<div class="line"><a class="reference external" href="reference-Custom_Storage.html#overview">overview</a></div>
<div class="line"><a class="reference external" href="reference-Custom_Storage.html#file_pool">file_pool</a></div>
<div class="line"><a class="reference external" href="reference-Custom_Storage.html#storage_interface">storage_interface</a></div>
<div class="line"><a class="reference external" href="reference-Custom_Storage.html#default_storage">default_storage</a></div>
<div class="line"><a class="reference external" href="reference-Custom_Storage.html#move_flags_t">move_flags_t</a></div>
</div>
</div>
<div class="section" id="core">
<h1>Core</h1>
<div class="line-block">
<div class="line"><a class="reference external" href="reference-Core.html#disk_buffer_holder">disk_buffer_holder</a></div>
<div class="line"><a class="reference external" href="reference-Core.html#hasher">hasher</a></div>
<div class="line"><a class="reference external" href="reference-Core.html#peer_info">peer_info</a></div>
<div class="line"><a class="reference external" href="reference-Core.html#peer_request">peer_request</a></div>
<div class="line"><a class="reference external" href="reference-Core.html#block_info">block_info</a></div>
<div class="line"><a class="reference external" href="reference-Core.html#partial_piece_info">partial_piece_info</a></div>
<div class="line"><a class="reference external" href="reference-Core.html#torrent_handle">torrent_handle</a></div>
<div class="line"><a class="reference external" href="reference-Core.html#torrent_status">torrent_status</a></div>
<div class="line"><a class="reference external" href="reference-Core.html#announce_entry">announce_entry</a></div>
<div class="line"><a class="reference external" href="reference-Core.html#torrent_info">torrent_info</a></div>
<div class="line"><a class="reference external" href="reference-Core.html#make_magnet_uri()">make_magnet_uri()</a></div>
<div class="line"><a class="reference external" href="reference-Core.html#parse_magnet_uri()">parse_magnet_uri()</a></div>
<div class="line"><a class="reference external" href="reference-Core.html#hash_value()">hash_value()</a></div>
<div class="line"><a class="reference external" href="reference-Core.html#sign_mutable_item()">sign_mutable_item()</a></div>
</div>
</div>
<div class="section" id="time">
<h1>Time</h1>
<div class="line-block">
<div class="line"><a class="reference external" href="reference-Time.html#overview">overview</a></div>
<div class="line"><a class="reference external" href="reference-Time.html#time_duration">time_duration</a></div>
<div class="line"><a class="reference external" href="reference-Time.html#ptime">ptime</a></div>
<div class="line"><a class="reference external" href="reference-Time.html#is_negative()">is_negative()</a></div>
<div class="line"><a class="reference external" href="reference-Time.html#operator*()">operator*()</a></div>
<div class="line"><a class="reference external" href="reference-Time.html#operator&gt;=()">operator&gt;=()</a></div>
<div class="line"><a class="reference external" href="reference-Time.html#operator!=()">operator!=()</a></div>
<div class="line"><a class="reference external" href="reference-Time.html#operator&gt;()">operator&gt;()</a></div>
<div class="line"><a class="reference external" href="reference-Time.html#operator&lt;()">operator&lt;()</a></div>
<div class="line"><a class="reference external" href="reference-Time.html#operator==()">operator==()</a></div>
<div class="line"><a class="reference external" href="reference-Time.html#operator+()">operator+()</a></div>
<div class="line"><a class="reference external" href="reference-Time.html#operator&lt;=()">operator&lt;=()</a></div>
<div class="line"><a class="reference external" href="reference-Time.html#operator-()">operator-()</a></div>
<div class="line"><a class="reference external" href="reference-Time.html#time_now()">time_now()</a></div>
<div class="line"><a class="reference external" href="reference-Time.html#time_now_hires()">time_now_hires()</a></div>
<div class="line"><a class="reference external" href="reference-Time.html#min_time()">min_time()</a></div>
<div class="line"><a class="reference external" href="reference-Time.html#max_time()">max_time()</a></div>
<div class="line"><a class="reference external" href="reference-Time.html#microsec()">microsec()</a></div>
<div class="line"><a class="reference external" href="reference-Time.html#minutes()">minutes()</a></div>
<div class="line"><a class="reference external" href="reference-Time.html#hours()">hours()</a></div>
<div class="line"><a class="reference external" href="reference-Time.html#milliseconds()">milliseconds()</a></div>
<div class="line"><a class="reference external" href="reference-Time.html#seconds()">seconds()</a></div>
<div class="line"><a class="reference external" href="reference-Time.html#total_seconds()">total_seconds()</a></div>
<div class="line"><a class="reference external" href="reference-Time.html#total_microseconds()">total_microseconds()</a></div>
<div class="line"><a class="reference external" href="reference-Time.html#total_milliseconds()">total_milliseconds()</a></div>
</div>
</div>
<div class="section" id="bencoding">
<h1>Bencoding</h1>
<div class="line-block">
<div class="line"><a class="reference external" href="reference-Bencoding.html#overview">overview</a></div>
<div class="line"><a class="reference external" href="reference-Bencoding.html#invalid_encoding">invalid_encoding</a></div>
<div class="line"><a class="reference external" href="reference-Bencoding.html#type_error">type_error</a></div>
<div class="line"><a class="reference external" href="reference-Bencoding.html#entry">entry</a></div>
<div class="line"><a class="reference external" href="reference-Bencoding.html#pascal_string">pascal_string</a></div>
<div class="line"><a class="reference external" href="reference-Bencoding.html#lazy_entry">lazy_entry</a></div>
<div class="line"><a class="reference external" href="reference-Bencoding.html#bdecode()">bdecode()</a></div>
<div class="line"><a class="reference external" href="reference-Bencoding.html#bencode()">bencode()</a></div>
<div class="line"><a class="reference external" href="reference-Utility.html#operator&lt;&lt;()">operator&lt;&lt;()</a></div>
<div class="line"><a class="reference external" href="reference-Bencoding.html#lazy_bdecode()">lazy_bdecode()</a></div>
<div class="line"><a class="reference external" href="reference-Bencoding.html#print_entry()">print_entry()</a></div>
</div>
</div>
<div class="section" id="string">
<h1>String</h1>
<div class="line-block">
<div class="line"><a class="reference external" href="reference-String.html#to_hex()">to_hex()</a></div>
<div class="line"><a class="reference external" href="reference-String.html#to_hex()">to_hex()</a></div>
<div class="line"><a class="reference external" href="reference-String.html#from_hex()">from_hex()</a></div>
<div class="line"><a class="reference external" href="reference-String.html#is_digit()">is_digit()</a></div>
<div class="line"><a class="reference external" href="reference-String.html#utf8_wchar()">utf8_wchar()</a></div>
<div class="line"><a class="reference external" href="reference-String.html#wchar_utf8()">wchar_utf8()</a></div>
<div class="line"><a class="reference external" href="reference-String.html#utf8_conv_result_t">utf8_conv_result_t</a></div>
</div>
</div>
<div class="section" id="settings">
<h1>Settings</h1>
<div class="line-block">
<div class="line"><a class="reference external" href="reference-Settings.html#proxy_settings">proxy_settings</a></div>
<div class="line"><a class="reference external" href="reference-Settings.html#session_settings">session_settings</a></div>
<div class="line"><a class="reference external" href="reference-Settings.html#dht_settings">dht_settings</a></div>
<div class="line"><a class="reference external" href="reference-Settings.html#pe_settings">pe_settings</a></div>
<div class="line"><a class="reference external" href="reference-Settings.html#min_memory_usage()">min_memory_usage()</a></div>
<div class="line"><a class="reference external" href="reference-Settings.html#high_performance_seed()">high_performance_seed()</a></div>
</div>
</div>
<div class="section" id="plugins">
<h1>Plugins</h1>
<div class="line-block">
<div class="line"><a class="reference external" href="reference-Plugins.html#overview">overview</a></div>
<div class="line"><a class="reference external" href="reference-Plugins.html#plugin">plugin</a></div>
<div class="line"><a class="reference external" href="reference-Plugins.html#torrent_plugin">torrent_plugin</a></div>
<div class="line"><a class="reference external" href="reference-Plugins.html#peer_plugin">peer_plugin</a></div>
<div class="line"><a class="reference external" href="reference-Plugins.html#create_lt_trackers_plugin()">create_lt_trackers_plugin()</a></div>
<div class="line"><a class="reference external" href="reference-Plugins.html#create_smart_ban_plugin()">create_smart_ban_plugin()</a></div>
<div class="line"><a class="reference external" href="reference-Plugins.html#create_ut_metadata_plugin()">create_ut_metadata_plugin()</a></div>
<div class="line"><a class="reference external" href="reference-Plugins.html#create_ut_pex_plugin()">create_ut_pex_plugin()</a></div>
</div>
</div>
<div class="section" id="alerts">
<h1>Alerts</h1>
<div class="line-block">
<div class="line"><a class="reference external" href="reference-Alerts.html#overview">overview</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#alert">alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#torrent_alert">torrent_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#peer_alert">peer_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#tracker_alert">tracker_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#torrent_added_alert">torrent_added_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#torrent_removed_alert">torrent_removed_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#read_piece_alert">read_piece_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#file_completed_alert">file_completed_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#file_renamed_alert">file_renamed_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#file_rename_failed_alert">file_rename_failed_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#performance_alert">performance_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#state_changed_alert">state_changed_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#tracker_error_alert">tracker_error_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#tracker_warning_alert">tracker_warning_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#scrape_reply_alert">scrape_reply_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#scrape_failed_alert">scrape_failed_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#tracker_reply_alert">tracker_reply_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#dht_reply_alert">dht_reply_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#tracker_announce_alert">tracker_announce_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#hash_failed_alert">hash_failed_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#peer_ban_alert">peer_ban_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#peer_unsnubbed_alert">peer_unsnubbed_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#peer_snubbed_alert">peer_snubbed_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#peer_error_alert">peer_error_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#peer_connect_alert">peer_connect_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#peer_disconnected_alert">peer_disconnected_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#invalid_request_alert">invalid_request_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#torrent_finished_alert">torrent_finished_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#piece_finished_alert">piece_finished_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#request_dropped_alert">request_dropped_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#block_timeout_alert">block_timeout_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#block_finished_alert">block_finished_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#block_downloading_alert">block_downloading_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#unwanted_block_alert">unwanted_block_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#storage_moved_alert">storage_moved_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#storage_moved_failed_alert">storage_moved_failed_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#torrent_deleted_alert">torrent_deleted_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#torrent_delete_failed_alert">torrent_delete_failed_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#save_resume_data_alert">save_resume_data_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#save_resume_data_failed_alert">save_resume_data_failed_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#torrent_paused_alert">torrent_paused_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#torrent_resumed_alert">torrent_resumed_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#torrent_checked_alert">torrent_checked_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#url_seed_alert">url_seed_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#file_error_alert">file_error_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#metadata_failed_alert">metadata_failed_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#metadata_received_alert">metadata_received_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#udp_error_alert">udp_error_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#external_ip_alert">external_ip_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#listen_failed_alert">listen_failed_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#listen_succeeded_alert">listen_succeeded_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#portmap_error_alert">portmap_error_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#portmap_alert">portmap_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#portmap_log_alert">portmap_log_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#fastresume_rejected_alert">fastresume_rejected_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#peer_blocked_alert">peer_blocked_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#dht_announce_alert">dht_announce_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#dht_get_peers_alert">dht_get_peers_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#stats_alert">stats_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#cache_flushed_alert">cache_flushed_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#anonymous_mode_alert">anonymous_mode_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#lsd_peer_alert">lsd_peer_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#trackerid_alert">trackerid_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#dht_bootstrap_alert">dht_bootstrap_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#rss_alert">rss_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#torrent_error_alert">torrent_error_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#torrent_need_cert_alert">torrent_need_cert_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#incoming_connection_alert">incoming_connection_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#add_torrent_alert">add_torrent_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#state_update_alert">state_update_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#torrent_update_alert">torrent_update_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#rss_item_alert">rss_item_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#dht_error_alert">dht_error_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#dht_immutable_item_alert">dht_immutable_item_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#dht_mutable_item_alert">dht_mutable_item_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#dht_put_alert">dht_put_alert</a></div>
<div class="line"><a class="reference external" href="reference-Alerts.html#i2p_alert">i2p_alert</a></div>
</div>
</div>
<div class="section" id="storage">
<h1>Storage</h1>
<div class="line-block">
<div class="line"><a class="reference external" href="reference-Storage.html#file_entry">file_entry</a></div>
<div class="line"><a class="reference external" href="reference-Storage.html#file_slice">file_slice</a></div>
<div class="line"><a class="reference external" href="reference-Storage.html#file_storage">file_storage</a></div>
<div class="line"><a class="reference external" href="reference-Storage.html#default_storage_constructor()">default_storage_constructor()</a></div>
<div class="line"><a class="reference external" href="reference-Storage.html#disabled_storage_constructor()">disabled_storage_constructor()</a></div>
<div class="line"><a class="reference external" href="reference-Storage.html#storage_mode_t">storage_mode_t</a></div>
</div>
</div>
<div class="section" id="filter">
<h1>Filter</h1>
<div class="line-block">
<div class="line"><a class="reference external" href="reference-Filter.html#ip_filter">ip_filter</a></div>
<div class="line"><a class="reference external" href="reference-Filter.html#port_filter">port_filter</a></div>
</div>
</div>
<div class="section" id="session">
<h1>Session</h1>
<div class="line-block">
<div class="line"><a class="reference external" href="reference-Session.html#add_torrent_params">add_torrent_params</a></div>
<div class="line"><a class="reference external" href="reference-Session.html#cache_status">cache_status</a></div>
<div class="line"><a class="reference external" href="reference-Session.html#session_proxy">session_proxy</a></div>
<div class="line"><a class="reference external" href="reference-Session.html#session">session</a></div>
<div class="line"><a class="reference external" href="reference-Session.html#dht_lookup">dht_lookup</a></div>
<div class="line"><a class="reference external" href="reference-Session.html#dht_routing_bucket">dht_routing_bucket</a></div>
<div class="line"><a class="reference external" href="reference-Session.html#utp_status">utp_status</a></div>
<div class="line"><a class="reference external" href="reference-Session.html#session_status">session_status</a></div>
</div>
</div>
<div class="section" id="create-torrents">
<h1>Create Torrents</h1>
<div class="line-block">
<div class="line"><a class="reference external" href="reference-Create_Torrents.html#overview">overview</a></div>
<div class="line"><a class="reference external" href="reference-Create_Torrents.html#create_torrent">create_torrent</a></div>
<div class="line"><a class="reference external" href="reference-Create_Torrents.html#add_files()">add_files()</a></div>
<div class="line"><a class="reference external" href="reference-Create_Torrents.html#set_piece_hashes()">set_piece_hashes()</a></div>
</div>
</div>
<div class="section" id="error-codes">
<h1>Error Codes</h1>
<div class="line-block">
<div class="line"><a class="reference external" href="reference-Error_Codes.html#libtorrent_exception">libtorrent_exception</a></div>
<div class="line"><a class="reference external" href="reference-Error_Codes.html#get_libtorrent_category()">get_libtorrent_category()</a></div>
<div class="line"><a class="reference external" href="reference-Error_Codes.html#get_http_category()">get_http_category()</a></div>
<div class="line"><a class="reference external" href="reference-Error_Codes.html#get_i2p_category()">get_i2p_category()</a></div>
<div class="line"><a class="reference external" href="reference-Error_Codes.html#get_bdecode_category()">get_bdecode_category()</a></div>
<div class="line"><a class="reference external" href="reference-Error_Codes.html#get_socks_category()">get_socks_category()</a></div>
<div class="line"><a class="reference external" href="reference-Error_Codes.html#get_upnp_category()">get_upnp_category()</a></div>
<div class="line"><a class="reference external" href="reference-Error_Codes.html#error_code_enum">error_code_enum</a></div>
<div class="line"><a class="reference external" href="reference-Error_Codes.html#http_errors">http_errors</a></div>
<div class="line"><a class="reference external" href="reference-Error_Codes.html#i2p_error_code">i2p_error_code</a></div>
<div class="line"><a class="reference external" href="reference-Error_Codes.html#error_code_enum">error_code_enum</a></div>
<div class="line"><a class="reference external" href="reference-Error_Codes.html#socks_error_code">socks_error_code</a></div>
<div class="line"><a class="reference external" href="reference-Error_Codes.html#error_code_enum">error_code_enum</a></div>
</div>
</div>
<div class="section" id="rss">
<h1>RSS</h1>
<div class="line-block">
<div class="line"><a class="reference external" href="reference-RSS.html#feed_item">feed_item</a></div>
<div class="line"><a class="reference external" href="reference-RSS.html#feed_settings">feed_settings</a></div>
<div class="line"><a class="reference external" href="reference-RSS.html#feed_status">feed_status</a></div>
<div class="line"><a class="reference external" href="reference-RSS.html#feed_handle">feed_handle</a></div>
<div class="line"><a class="reference external" href="reference-RSS.html#add_feed_item()">add_feed_item()</a></div>
<div class="line"><a class="reference external" href="reference-RSS.html#new_feed()">new_feed()</a></div>
</div>
</div>
<div class="section" id="utility">
<h1>Utility</h1>
<div class="line-block">
<div class="line"><a class="reference external" href="reference-Utility.html#bitfield">bitfield</a></div>
<div class="line"><a class="reference external" href="reference-Utility.html#sha1_hash">sha1_hash</a></div>
<div class="line"><a class="reference external" href="reference-Utility.html#identify_client()">identify_client()</a></div>
<div class="line"><a class="reference external" href="reference-Utility.html#client_fingerprint()">client_fingerprint()</a></div>
<div class="line"><a class="reference external" href="reference-Utility.html#operator&lt;&lt;()">operator&lt;&lt;()</a></div>
<div class="line"><a class="reference external" href="reference-Utility.html#operator&gt;&gt;()">operator&gt;&gt;()</a></div>
<div class="line"><a class="reference external" href="reference-Utility.html#sleep()">sleep()</a></div>
</div>
</div></div>
</div>
</body>
</html>

3217
docs/settings.rst Normal file

File diff suppressed because it is too large Load Diff

368
docs/stats_counters.rst Normal file
View File

@ -0,0 +1,368 @@
.. _peer.error_peers:
.. _peer.disconnected_peers:
+-------------------------+---------+
| name | type |
+=========================+=========+
| peer.error_peers | counter |
+-------------------------+---------+
| peer.disconnected_peers | counter |
+-------------------------+---------+
``error_peers`` is the total number of peer disconnects
caused by an error (not initiated by this client) and
disconnected initiated by this client (``disconnected_peers``).
.. _peer.eof_peers:
.. _peer.connreset_peers:
.. _peer.connrefused_peers:
.. _peer.connaborted_peers:
.. _peer.perm_peers:
.. _peer.buffer_peers:
.. _peer.unreachable_peers:
.. _peer.broken_pipe_peers:
.. _peer.addrinuse_peers:
.. _peer.no_access_peers:
.. _peer.invalid_arg_peers:
.. _peer.aborted_peers:
+------------------------+---------+
| name | type |
+========================+=========+
| peer.eof_peers | counter |
+------------------------+---------+
| peer.connreset_peers | counter |
+------------------------+---------+
| peer.connrefused_peers | counter |
+------------------------+---------+
| peer.connaborted_peers | counter |
+------------------------+---------+
| peer.perm_peers | counter |
+------------------------+---------+
| peer.buffer_peers | counter |
+------------------------+---------+
| peer.unreachable_peers | counter |
+------------------------+---------+
| peer.broken_pipe_peers | counter |
+------------------------+---------+
| peer.addrinuse_peers | counter |
+------------------------+---------+
| peer.no_access_peers | counter |
+------------------------+---------+
| peer.invalid_arg_peers | counter |
+------------------------+---------+
| peer.aborted_peers | counter |
+------------------------+---------+
these counters break down the peer errors into more specific
categories. These errors are what the underlying transport
reported (i.e. TCP or uTP)
.. _peer.error_incoming_peers:
.. _peer.error_outgoing_peers:
+---------------------------+---------+
| name | type |
+===========================+=========+
| peer.error_incoming_peers | counter |
+---------------------------+---------+
| peer.error_outgoing_peers | counter |
+---------------------------+---------+
these counters break down the peer errors into
whether they happen on incoming or outgoing peers.
.. _peer.error_rc4_peers:
.. _peer.error_encrypted_peers:
+----------------------------+---------+
| name | type |
+============================+=========+
| peer.error_rc4_peers | counter |
+----------------------------+---------+
| peer.error_encrypted_peers | counter |
+----------------------------+---------+
these counters break down the peer errors into
whether they happen on encrypted peers (just
encrypted handshake) and rc4 peers (full stream
encryption). These can indicate whether encrypted
peers are more or less likely to fail
.. _peer.error_tcp_peers:
.. _peer.error_utp_peers:
+----------------------+---------+
| name | type |
+======================+=========+
| peer.error_tcp_peers | counter |
+----------------------+---------+
| peer.error_utp_peers | counter |
+----------------------+---------+
these counters break down the peer errors into
whether they happen on uTP peers or TCP peers.
these may indicate whether one protocol is
more error prone
.. _peer.connect_timeouts:
.. _peer.uninteresting_peers:
.. _peer.timeout_peers:
.. _peer.no_memory_peers:
.. _peer.too_many_peers:
.. _peer.transport_timeout_peers:
.. _peer.num_banned_peers:
.. _peer.connection_attempts:
.. _peer.banned_for_hash_failure:
+------------------------------+---------+
| name | type |
+==============================+=========+
| peer.connect_timeouts | counter |
+------------------------------+---------+
| peer.uninteresting_peers | counter |
+------------------------------+---------+
| peer.timeout_peers | counter |
+------------------------------+---------+
| peer.no_memory_peers | counter |
+------------------------------+---------+
| peer.too_many_peers | counter |
+------------------------------+---------+
| peer.transport_timeout_peers | counter |
+------------------------------+---------+
| peer.num_banned_peers | counter |
+------------------------------+---------+
| peer.connection_attempts | counter |
+------------------------------+---------+
| peer.banned_for_hash_failure | counter |
+------------------------------+---------+
these counters break down the reasons to
disconnect peers.
.. _peer.num_tcp_peers:
.. _peer.num_socks5_peers:
.. _peer.num_http_proxy_peers:
.. _peer.num_utp_peers:
.. _peer.num_i2p_peers:
.. _peer.num_ssl_peers:
.. _peer.num_ssl_socks5_peers:
.. _peer.num_ssl_http_proxy_peers:
.. _peer.num_ssl_utp_peers:
+-------------------------------+-------+
| name | type |
+===============================+=======+
| peer.num_tcp_peers | gauge |
+-------------------------------+-------+
| peer.num_socks5_peers | gauge |
+-------------------------------+-------+
| peer.num_http_proxy_peers | gauge |
+-------------------------------+-------+
| peer.num_utp_peers | gauge |
+-------------------------------+-------+
| peer.num_i2p_peers | gauge |
+-------------------------------+-------+
| peer.num_ssl_peers | gauge |
+-------------------------------+-------+
| peer.num_ssl_socks5_peers | gauge |
+-------------------------------+-------+
| peer.num_ssl_http_proxy_peers | gauge |
+-------------------------------+-------+
| peer.num_ssl_utp_peers | gauge |
+-------------------------------+-------+
the number of peer connections for each kind of socket.
these counts include half-open (connecting) peers.
.. _net.on_read_counter:
.. _net.on_write_counter:
.. _net.on_tick_counter:
.. _net.on_lsd_counter:
.. _net.on_lsd_peer_counter:
.. _net.on_udp_counter:
.. _net.on_accept_counter:
.. _net.on_disk_counter:
+-------------------------+---------+
| name | type |
+=========================+=========+
| net.on_read_counter | counter |
+-------------------------+---------+
| net.on_write_counter | counter |
+-------------------------+---------+
| net.on_tick_counter | counter |
+-------------------------+---------+
| net.on_lsd_counter | counter |
+-------------------------+---------+
| net.on_lsd_peer_counter | counter |
+-------------------------+---------+
| net.on_udp_counter | counter |
+-------------------------+---------+
| net.on_accept_counter | counter |
+-------------------------+---------+
| net.on_disk_counter | counter |
+-------------------------+---------+
These counters count the number of times the
network thread wakes up for each respective
reason. If these counters are very large, it
may indicate a performance issue, causing the
network thread to wake up too ofte, wasting CPU.
mitigate it by increasing buffers and limits
for the specific trigger that wakes up the
thread.
.. _ses.num_checking_torrents:
.. _ses.num_stopped_torrents:
.. _ses.num_upload_only_torrents:
.. _ses.num_downloading_torrents:
.. _ses.num_seeding_torrents:
.. _ses.num_queued_seeding_torrents:
.. _ses.num_queued_download_torrents:
.. _ses.num_error_torrents:
+----------------------------------+-------+
| name | type |
+==================================+=======+
| ses.num_checking_torrents | gauge |
+----------------------------------+-------+
| ses.num_stopped_torrents | gauge |
+----------------------------------+-------+
| ses.num_upload_only_torrents | gauge |
+----------------------------------+-------+
| ses.num_downloading_torrents | gauge |
+----------------------------------+-------+
| ses.num_seeding_torrents | gauge |
+----------------------------------+-------+
| ses.num_queued_seeding_torrents | gauge |
+----------------------------------+-------+
| ses.num_queued_download_torrents | gauge |
+----------------------------------+-------+
| ses.num_error_torrents | gauge |
+----------------------------------+-------+
these gauges count the number of torrents in
different states. Each torrent only belongs to
one of these states. For torrents that could
belong to multiple of these, the most prominent
in picked. For instance, a torrent with an error
counts as an error-torrent, regardless of its other
state.
.. _ses.torrent_evicted_counter:
+-----------------------------+---------+
| name | type |
+=============================+=========+
| ses.torrent_evicted_counter | counter |
+-----------------------------+---------+
this counts the number of times a torrent has been
evicted (only applies when `dynamic loading of torrent files`_
is enabled).
.. _picker.piece_picks:
+--------------------+---------+
| name | type |
+====================+=========+
| picker.piece_picks | counter |
+--------------------+---------+
counts the number of times the piece picker has been invoked
.. _picker.piece_picker_loops:
+---------------------------+---------+
| name | type |
+===========================+=========+
| picker.piece_picker_loops | counter |
+---------------------------+---------+
the number of pieces considered while picking pieces
.. _picker.end_game_piece_picker_blocks:
.. _picker.piece_picker_blocks:
.. _picker.reject_piece_picks:
.. _picker.unchoke_piece_picks:
.. _picker.incoming_redundant_piece_picks:
.. _picker.incoming_piece_picks:
.. _picker.end_game_piece_picks:
.. _picker.snubbed_piece_picks:
+---------------------------------------+---------+
| name | type |
+=======================================+=========+
| picker.end_game_piece_picker_blocks | counter |
+---------------------------------------+---------+
| picker.piece_picker_blocks | counter |
+---------------------------------------+---------+
| picker.reject_piece_picks | counter |
+---------------------------------------+---------+
| picker.unchoke_piece_picks | counter |
+---------------------------------------+---------+
| picker.incoming_redundant_piece_picks | counter |
+---------------------------------------+---------+
| picker.incoming_piece_picks | counter |
+---------------------------------------+---------+
| picker.end_game_piece_picks | counter |
+---------------------------------------+---------+
| picker.snubbed_piece_picks | counter |
+---------------------------------------+---------+
This breaks down the piece picks into the event that
triggered it

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 488 KiB

After

Width:  |  Height:  |  Size: 272 KiB

View File

@ -49,7 +49,7 @@
<tr><th class="docinfo-name">Author:</th>
<td>Arvid Norberg, <a class="last reference external" href="mailto:arvid&#64;rasterbar.com">arvid&#64;rasterbar.com</a></td></tr>
<tr><th class="docinfo-name">Version:</th>
<td>1.0.0</td></tr>
<td>1.1.0</td></tr>
</tbody>
</table>
<div class="contents topic" id="table-of-contents">
@ -71,20 +71,22 @@
<li><a class="reference internal" href="#high-performance-seeding" id="id12">high performance seeding</a><ul>
<li><a class="reference internal" href="#file-pool" id="id13">file pool</a></li>
<li><a class="reference internal" href="#disk-cache" id="id14">disk cache</a></li>
<li><a class="reference internal" href="#utp-tcp-mixed-mode" id="id15">uTP-TCP mixed mode</a></li>
<li><a class="reference internal" href="#send-buffer-low-watermark" id="id16">send buffer low watermark</a></li>
<li><a class="reference internal" href="#peers" id="id17">peers</a></li>
<li><a class="reference internal" href="#torrent-limits" id="id18">torrent limits</a></li>
<li><a class="reference internal" href="#ssd-as-level-2-cache" id="id15">SSD as level 2 cache</a></li>
<li><a class="reference internal" href="#utp-tcp-mixed-mode" id="id16">uTP-TCP mixed mode</a></li>
<li><a class="reference internal" href="#send-buffer-low-watermark" id="id17">send buffer low watermark</a></li>
<li><a class="reference internal" href="#peers" id="id18">peers</a></li>
<li><a class="reference internal" href="#torrent-limits" id="id19">torrent limits</a></li>
<li><a class="reference internal" href="#sha-1-hashing" id="id20">SHA-1 hashing</a></li>
</ul>
</li>
<li><a class="reference internal" href="#scalability" id="id19">scalability</a></li>
<li><a class="reference internal" href="#benchmarking" id="id20">benchmarking</a><ul>
<li><a class="reference internal" href="#disk-metrics" id="id21">disk metrics</a></li>
<li><a class="reference internal" href="#session-stats" id="id22">session stats</a></li>
<li><a class="reference internal" href="#scalability" id="id21">scalability</a></li>
<li><a class="reference internal" href="#benchmarking" id="id22">benchmarking</a><ul>
<li><a class="reference internal" href="#disk-metrics" id="id23">disk metrics</a></li>
<li><a class="reference internal" href="#session-stats" id="id24">session stats</a></li>
</ul>
</li>
<li><a class="reference internal" href="#understanding-the-disk-thread" id="id23">understanding the disk thread</a></li>
<li><a class="reference internal" href="#contributions" id="id24">contributions</a></li>
<li><a class="reference internal" href="#understanding-the-disk-thread" id="id25">understanding the disk thread</a></li>
<li><a class="reference internal" href="#contributions" id="id26">contributions</a></li>
</ul>
</div>
<div class="section" id="tuning-libtorrent">
@ -315,6 +317,21 @@ the same pieces, and on the other hand assume that they won't request the same p
and drop them when the first peer requests it. To enable volatile read cache, set
<tt class="docutils literal"><span class="pre">session_settings::volatile_read_cache</span></tt> to true.</p>
</div>
<div class="section" id="ssd-as-level-2-cache">
<h2>SSD as level 2 cache</h2>
<p>It is possible to introduce a second level of cache, below the RAM disk cache. This is done
by setting <tt class="docutils literal"><span class="pre">session_settings::mmap_cache</span></tt> to a file path pointing to the SSD drive, and
increasing the <tt class="docutils literal"><span class="pre">session_settings::cache_size</span></tt> to the number of 16 kiB blocks would fit
on the drive (or less).</p>
<p>This will allocate disk buffers (for reading and writing) from a memory region that has
been mapped to the specified file. If the drive this file lives on is not significantly
faster than the destination drive, performance will be degraded. The point is to take
advantage primarily of the fast read speed from SSD drives and use it to extend the read
cache, improving seed performance.</p>
<p>Which parts of the cache that actually live in RAM is determined by the operating system.</p>
<p>Note that when using this feature, any block which ends up being pulled from the mmapped
file will be considered a cache hit.</p>
</div>
<div class="section" id="utp-tcp-mixed-mode">
<h2>uTP-TCP mixed mode</h2>
<p>libtorrent supports <a class="reference external" href="utp.html">uTP</a>, which has a delay based congestion controller. In order to
@ -363,6 +380,15 @@ number via <tt class="docutils literal"><span class="pre">session::set_max_uploa
<p>To seed thousands of torrents, you need to increase the <tt class="docutils literal"><span class="pre">session_settings::active_limit</span></tt>
and <tt class="docutils literal"><span class="pre">session_settings::active_seeds</span></tt>.</p>
</div>
<div class="section" id="sha-1-hashing">
<h2>SHA-1 hashing</h2>
<p>When downloading at very high rates, it is possible to have the CPU be the bottleneck
for passing every downloaded byte through SHA-1. In order to enable calculating SHA-1
hashes in parallel, on multi-core systems, set <tt class="docutils literal"><span class="pre">session_settings::hashing_threads</span></tt>
to the number of threads libtorrent should start to do SHA-1 hashing. This defaults
to 1, and only if that thread is close to saturating one core does it make sense to
increase the number of threads.</p>
</div>
</div>
<div class="section" id="scalability">
<h1>scalability</h1>
@ -599,7 +625,7 @@ of these jobs are then posted back on the main thread's io_service.</p>
<p>A disk job is essentially one of:</p>
<ol class="arabic simple">
<li>write this block to disk, i.e. a write job. For the most part this is just a matter of sticking the block in the disk cache, but if we've run out of cache space or completed a whole piece, we'll also flush blocks to disk. This is typically very fast, since the OS just sticks these buffers in its write cache which will be flushed at a later time, presumably when the drive head will pass the place on the platter where the blocks go.</li>
<li>read this block from disk. The first thing that happens is we look in the cache to see if the block is already in RAM. If it is, we'll return immediately with this block. If it's a cache miss, we'll have to hit the disk. Here we decide to defer this job. We find the physical offset on the drive for this block and insert the job in an ordere queue, sorted by the physical location. At a later time, once we don't have any more non-read jobs left in the queue, we pick one read job out of the ordered queue and service it. The order we pick jobs out of the queue is according to an elevator cursor moving up and down along the ordered queue of read jobs. If we have enough space in the cache we'll read read_cache_line_size number of blocks and stick those in the cache. This defaults to 32 blocks.</li>
<li>read this block from disk. The first thing that happens is we look in the cache to see if the block is already in RAM. If it is, we'll return immediately with this block. If it's a cache miss, we'll have to hit the disk. Here we decide to defer this job. We find the physical offset on the drive for this block and insert the job in an ordered queue, sorted by the physical location. At a later time, once we don't have any more non-read jobs left in the queue, we pick one read job out of the ordered queue and service it. The order we pick jobs out of the queue is according to an elevator cursor moving up and down along the ordered queue of read jobs. If we have enough space in the cache we'll read read_cache_line_size number of blocks and stick those in the cache. This defaults to 32 blocks. If the system supports asynchronous I/O (Windows, Linux, Mac OS X, BSD, Solars for instance), jobs will be issued immediately to the OS. This especially increases read throughput, since the OS has a much greater flexibility to reorder the read jobs.</li>
</ol>
<p>Other disk job consist of operations that needs to be synchronized with the disk I/O, like renaming files, closing files, flushing the cache, updating the settings etc. These are relatively rare though.</p>
</div>

View File

@ -3,7 +3,7 @@ libtorrent manual
=================
:Author: Arvid Norberg, arvid@rasterbar.com
:Version: 1.0.0
:Version: 1.1.0
.. contents:: Table of contents
:depth: 2
@ -285,6 +285,25 @@ the same pieces, and on the other hand assume that they won't request the same p
and drop them when the first peer requests it. To enable volatile read cache, set
``session_settings::volatile_read_cache`` to true.
SSD as level 2 cache
--------------------
It is possible to introduce a second level of cache, below the RAM disk cache. This is done
by setting ``session_settings::mmap_cache`` to a file path pointing to the SSD drive, and
increasing the ``session_settings::cache_size`` to the number of 16 kiB blocks would fit
on the drive (or less).
This will allocate disk buffers (for reading and writing) from a memory region that has
been mapped to the specified file. If the drive this file lives on is not significantly
faster than the destination drive, performance will be degraded. The point is to take
advantage primarily of the fast read speed from SSD drives and use it to extend the read
cache, improving seed performance.
Which parts of the cache that actually live in RAM is determined by the operating system.
Note that when using this feature, any block which ends up being pulled from the mmapped
file will be considered a cache hit.
uTP-TCP mixed mode
------------------
@ -344,6 +363,16 @@ torrent limits
To seed thousands of torrents, you need to increase the ``session_settings::active_limit``
and ``session_settings::active_seeds``.
SHA-1 hashing
-------------
When downloading at very high rates, it is possible to have the CPU be the bottleneck
for passing every downloaded byte through SHA-1. In order to enable calculating SHA-1
hashes in parallel, on multi-core systems, set ``session_settings::hashing_threads``
to the number of threads libtorrent should start to do SHA-1 hashing. This defaults
to 1, and only if that thread is close to saturating one core does it make sense to
increase the number of threads.
scalability
===========
@ -569,7 +598,7 @@ A disk job is essentially one of:
1. write this block to disk, i.e. a write job. For the most part this is just a matter of sticking the block in the disk cache, but if we've run out of cache space or completed a whole piece, we'll also flush blocks to disk. This is typically very fast, since the OS just sticks these buffers in its write cache which will be flushed at a later time, presumably when the drive head will pass the place on the platter where the blocks go.
2. read this block from disk. The first thing that happens is we look in the cache to see if the block is already in RAM. If it is, we'll return immediately with this block. If it's a cache miss, we'll have to hit the disk. Here we decide to defer this job. We find the physical offset on the drive for this block and insert the job in an ordere queue, sorted by the physical location. At a later time, once we don't have any more non-read jobs left in the queue, we pick one read job out of the ordered queue and service it. The order we pick jobs out of the queue is according to an elevator cursor moving up and down along the ordered queue of read jobs. If we have enough space in the cache we'll read read_cache_line_size number of blocks and stick those in the cache. This defaults to 32 blocks.
2. read this block from disk. The first thing that happens is we look in the cache to see if the block is already in RAM. If it is, we'll return immediately with this block. If it's a cache miss, we'll have to hit the disk. Here we decide to defer this job. We find the physical offset on the drive for this block and insert the job in an ordered queue, sorted by the physical location. At a later time, once we don't have any more non-read jobs left in the queue, we pick one read job out of the ordered queue and service it. The order we pick jobs out of the queue is according to an elevator cursor moving up and down along the ordered queue of read jobs. If we have enough space in the cache we'll read read_cache_line_size number of blocks and stick those in the cache. This defaults to 32 blocks. If the system supports asynchronous I/O (Windows, Linux, Mac OS X, BSD, Solars for instance), jobs will be issued immediately to the OS. This especially increases read throughput, since the OS has a much greater flexibility to reorder the read jobs.
Other disk job consist of operations that needs to be synchronized with the disk I/O, like renaming files, closing files, flushing the cache, updating the settings etc. These are relatively rare though.

View File

@ -49,7 +49,7 @@
<tr><th class="docinfo-name">Author:</th>
<td>Arvid Norberg, <a class="last reference external" href="mailto:arvid&#64;rasterbar.com">arvid&#64;rasterbar.com</a></td></tr>
<tr><th class="docinfo-name">Version:</th>
<td>1.0.0</td></tr>
<td>1.1.0</td></tr>
</tbody>
</table>
<div class="contents topic" id="table-of-contents">

View File

@ -3,7 +3,7 @@ libtorrent manual
=================
:Author: Arvid Norberg, arvid@rasterbar.com
:Version: 1.0.0
:Version: 1.1.0
.. contents:: Table of contents
:depth: 2

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -19,12 +19,16 @@ project client_test
exe client_test : client_test.cpp ;
exe simple_client : simple_client.cpp ;
exe stats_counters : stats_counters.cpp ;
exe dump_torrent : dump_torrent.cpp ;
exe make_torrent : make_torrent.cpp ;
exe connection_tester : connection_tester.cpp ;
exe rss_reader : rss_reader.cpp ;
exe upnp_test : upnp_test.cpp ;
explicit stage_client_test ;
explicit stage_connection_tester ;
install stage_client_test : client_test : <location>. ;
install stage_connection_tester : connection_tester : <location>. ;

View File

@ -17,6 +17,9 @@ EXTRA_DIST = Jamfile
client_test_SOURCES = client_test.cpp
#client_test_LDADD = $(top_builddir)/src/libtorrent-rasterbar.la
stats_counters_SOURCES = stats_counters.cpp
#stats_counters_LDADD = $(top_builddir)/src/libtorrent-rasterbar.la
dump_torrent_SOURCES = dump_torrent.cpp
#dump_torrent_LDADD = $(top_builddir)/src/libtorrent-rasterbar.la

File diff suppressed because it is too large Load Diff

View File

@ -40,6 +40,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/thread.hpp"
#include "libtorrent/create_torrent.hpp"
#include "libtorrent/hasher.hpp"
#include "libtorrent/socket_io.hpp"
#include <cstring>
#include <boost/bind.hpp>
#include <iostream>
@ -66,6 +67,10 @@ void generate_block(boost::uint32_t* buffer, int piece, int start, int length)
int local_if_counter = 0;
bool local_bind = false;
// when set to true, blocks downloaded are verified to match
// the test torrents
bool verify_downloads = false;
// if this is true, one block in 1000 will be sent corrupt.
// this only applies to dual and upload tests
bool test_corruption = false;
@ -88,33 +93,43 @@ boost::detail::atomic_count num_suggest(0);
// the number of requests made from suggested pieces
boost::detail::atomic_count num_suggested_requests(0);
struct peer_conn
{
peer_conn(io_service& ios, int num_pieces, int blocks_pp, tcp::endpoint const& ep
, char const* ih, bool seed_)
, char const* ih, bool seed_, int churn_, bool corrupt_)
: s(ios)
, read_pos(0)
, state(handshaking)
, choked(true)
, current_piece(-1)
, current_piece_is_allowed(false)
, block(0)
, blocks_per_piece(blocks_pp)
, info_hash(ih)
, outstanding_requests(0)
, seed(seed_)
, fast_extension(false)
, choked(true)
, blocks_received(0)
, blocks_sent(0)
, num_pieces(num_pieces)
, start_time(time_now_hires())
, churn(churn_)
, corrupt(corrupt_)
, endpoint(ep)
, restarting(false)
{
corruption_counter = rand() % 1000;
if (seed) ++num_seeds;
pieces.reserve(num_pieces);
start_conn();
}
void start_conn()
{
if (local_bind)
{
error_code ec;
s.open(ep.protocol(), ec);
s.open(endpoint.protocol(), ec);
if (ec)
{
close("ERROR OPEN: %s", ec);
@ -132,7 +147,8 @@ struct peer_conn
return;
}
}
s.async_connect(ep, boost::bind(&peer_conn::on_connect, this, _1));
restarting = false;
s.async_connect(endpoint, boost::bind(&peer_conn::on_connect, this, _1));
}
stream_socket s;
@ -151,7 +167,10 @@ struct peer_conn
int state;
std::vector<int> pieces;
std::vector<int> suggested_pieces;
std::vector<int> allowed_fast;
bool choked;
int current_piece; // the piece we're currently requesting blocks from
bool current_piece_is_allowed;
int block;
int blocks_per_piece;
char const* info_hash;
@ -159,12 +178,15 @@ struct peer_conn
// if this is true, this connection is a seed
bool seed;
bool fast_extension;
bool choked;
int blocks_received;
int blocks_sent;
int num_pieces;
ptime start_time;
ptime end_time;
int churn;
bool corrupt;
tcp::endpoint endpoint;
bool restarting;
void on_connect(error_code const& ec)
{
@ -273,21 +295,33 @@ struct peer_conn
bool write_request()
{
if (choked) return false;
// if we're choked (and there are no allowed-fast pieces left)
if (choked && allowed_fast.empty() && !current_piece_is_allowed) return false;
// if there are no pieces left to request
if (pieces.empty() && suggested_pieces.empty() && current_piece == -1) return false;
if (current_piece == -1)
{
if (suggested_pieces.size() > 0)
// pick a new piece
if (choked && allowed_fast.size() > 0)
{
current_piece = allowed_fast.front();
allowed_fast.erase(allowed_fast.begin());
current_piece_is_allowed = true;
}
else if (suggested_pieces.size() > 0)
{
current_piece = suggested_pieces.front();
suggested_pieces.erase(suggested_pieces.begin());
++num_suggested_requests;
current_piece_is_allowed = false;
}
else if (pieces.size() > 0)
{
current_piece = pieces.front();
pieces.erase(pieces.begin());
current_piece_is_allowed = false;
}
else
{
@ -314,6 +348,7 @@ struct peer_conn
{
block = 0;
current_piece = -1;
current_piece_is_allowed = false;
}
return true;
}
@ -339,8 +374,9 @@ struct peer_conn
if (time == 0) time = 1;
float up = (boost::int64_t(blocks_sent) * 0x4000) / time / 1000.f;
float down = (boost::int64_t(blocks_received) * 0x4000) / time / 1000.f;
printf("%s sent: %d received: %d duration: %d ms up: %.1fMB/s down: %.1fMB/s\n"
, tmp, blocks_sent, blocks_received, time, up, down);
error_code e;
printf("%s ep: %s sent: %d received: %d duration: %d ms up: %.1fMB/s down: %.1fMB/s\n"
, tmp, libtorrent::print_endpoint(s.local_endpoint(e)).c_str(), blocks_sent, blocks_received, time, up, down);
if (seed) --num_seeds;
}
@ -369,6 +405,13 @@ struct peer_conn
void on_msg_length(error_code const& ec, size_t bytes_transferred)
{
if ((ec == boost::asio::error::operation_aborted || ec == boost::asio::error::bad_descriptor)
&& restarting)
{
start_conn();
return;
}
if (ec)
{
close("ERROR RECEIVE MESSAGE PREFIX: %s", ec);
@ -378,6 +421,7 @@ struct peer_conn
unsigned int length = read_uint32(ptr);
if (length > sizeof(buffer))
{
fprintf(stderr, "len: %d\n", length);
close("ERROR RECEIVE MESSAGE PREFIX: packet too big", error_code());
return;
}
@ -387,6 +431,13 @@ struct peer_conn
void on_message(error_code const& ec, size_t bytes_transferred)
{
if ((ec == boost::asio::error::operation_aborted || ec == boost::asio::error::bad_descriptor)
&& restarting)
{
start_conn();
return;
}
if (ec)
{
close("ERROR RECEIVE MESSAGE: %s", ec);
@ -466,7 +517,7 @@ struct peer_conn
}
else if (msg == 7) // piece
{
// if (verify_downloads)
if (verify_downloads)
{
int piece = read_uint32(ptr);
int start = read_uint32(ptr);
@ -477,6 +528,13 @@ struct peer_conn
--outstanding_requests;
int piece = detail::read_int32(ptr);
int start = detail::read_int32(ptr);
if (churn && (blocks_received % churn) == 0) {
outstanding_requests = 0;
restarting = true;
s.close();
return;
}
if (int((start + bytes_transferred) / 0x4000) == blocks_per_piece)
{
write_have(piece);
@ -494,14 +552,49 @@ struct peer_conn
++num_suggest;
}
}
else if (msg == 1) // unchoke
else if (msg == 16) // reject request
{
choked = false;
int piece = detail::read_int32(ptr);
int start = detail::read_int32(ptr);
int length = detail::read_int32(ptr);
// put it back!
if (current_piece != piece)
{
if (pieces.empty() || pieces.back() != piece)
pieces.push_back(piece);
}
else
{
block = (std::min)(start / 0x4000, block);
if (block == 0)
{
pieces.push_back(current_piece);
current_piece = -1;
current_piece_is_allowed = false;
}
}
--outstanding_requests;
fprintf(stderr, "REJECT: [ piece: %d start: %d length: %d ]\n", piece, start, length);
}
else if (msg == 0) // choke
{
choked = true;
}
else if (msg == 1) // unchoke
{
choked = false;
}
else if (msg == 17) // allowed_fast
{
int piece = detail::read_int32(ptr);
std::vector<int>::iterator i = std::find(pieces.begin(), pieces.end(), piece);
if (i != pieces.end())
{
pieces.erase(i);
allowed_fast.push_back(piece);
}
}
work_download();
}
}
@ -526,7 +619,7 @@ struct peer_conn
{
generate_block(write_buffer, piece, start, length);
if (test_corruption)
if (corrupt)
{
--corruption_counter;
if (corruption_counter == 0)
@ -546,6 +639,11 @@ struct peer_conn
vec[1] = libtorrent::asio::buffer(write_buffer, length);
boost::asio::async_write(s, vec, boost::bind(&peer_conn::on_have_all_sent, this, _1, _2));
++blocks_sent;
if (churn && (blocks_sent % churn) == 0 && seed) {
outstanding_requests = 0;
restarting = true;
s.close();
}
}
void write_have(int piece)
@ -583,8 +681,9 @@ void print_usage()
" -c <num-conns> the number of connections to make to the target\n"
" -d <dst> the IP address of the target\n"
" -p <dst-port> the port the target listens on\n"
" -t <torrent-file> the torrent file previously generated by gen-torrent\n\n"
" -C send corrupt pieces sometimes (applies to upload and dual)\n\n"
" -t <torrent-file> the torrent file previously generated by gen-torrent\n"
" -C send corrupt pieces sometimes (applies to upload and dual)\n"
" -r <reconnects> churn - number of reconnects per second\n\n"
"examples:\n\n"
"connection_tester gen-torrent -s 1024 -n 4 -t test.torrent\n"
"connection_tester upload -c 200 -d 127.0.0.1 -p 6881 -t test.torrent\n"
@ -612,7 +711,7 @@ void hasher_thread(libtorrent::create_torrent* t, int start_piece, int end_piece
}
// size is in megabytes
void generate_torrent(std::vector<char>& buf, int size, int num_files)
void generate_torrent(std::vector<char>& buf, int size, int num_files, char const* name)
{
file_storage fs;
// 1 MiB piece size
@ -626,7 +725,7 @@ void generate_torrent(std::vector<char>& buf, int size, int num_files)
while (s > 0)
{
char b[100];
snprintf(b, sizeof(b), "t/stress_test%d", i);
snprintf(b, sizeof(b), "%s/stress_test%d", name, i);
++i;
fs.add_file(b, (std::min)(s, size_type(file_size)));
s -= file_size;
@ -696,6 +795,7 @@ int main(int argc, char* argv[])
int num_connections = 50;
char const* destination_ip = "127.0.0.1";
int destination_port = 6881;
int churn = 0;
argv += 2;
argc -= 2;
@ -738,6 +838,7 @@ int main(int argc, char* argv[])
case 'c': num_connections = atoi(optarg); break;
case 'p': destination_port = atoi(optarg); break;
case 'd': destination_ip = optarg; break;
case 'r': churn = atoi(optarg); break;
default: fprintf(stderr, "unknown option: %s\n", optname);
}
}
@ -745,7 +846,10 @@ int main(int argc, char* argv[])
if (strcmp(command, "gen-torrent") == 0)
{
std::vector<char> tmp;
generate_torrent(tmp, size ? size : 1024, num_files ? num_files : 1);
std::string name = filename(torrent_file);
name = name.substr(0, name.find_last_of('.'));
printf("generating torrent: %s\n", name.c_str());
generate_torrent(tmp, size ? size : 1024, num_files ? num_files : 1, name.c_str());
FILE* output = stdout;
if (strcmp("-", torrent_file) != 0)
@ -862,16 +966,18 @@ int main(int argc, char* argv[])
return 1;
}
std::list<peer_conn*> conns;
std::vector<peer_conn*> conns;
conns.reserve(num_connections);
const int num_threads = 2;
io_service ios[num_threads];
for (int i = 0; i < num_connections; ++i)
{
bool corrupt = test_corruption && (i & 1) == 0;
bool seed = false;
if (test_mode == upload_test) seed = true;
else if (test_mode == dual_test) seed = (i & 1);
conns.push_back(new peer_conn(ios[i % num_threads], ti.num_pieces(), ti.piece_length() / 16 / 1024
, ep, (char const*)&ti.info_hash()[0], seed));
, ep, (char const*)&ti.info_hash()[0], seed, churn, corrupt));
libtorrent::sleep(1);
ios[i % num_threads].poll_one(ec);
if (ec)
@ -881,7 +987,6 @@ int main(int argc, char* argv[])
}
}
thread t1(boost::bind(&io_thread, &ios[0]));
thread t2(boost::bind(&io_thread, &ios[1]));
@ -893,7 +998,7 @@ int main(int argc, char* argv[])
boost::uint64_t total_sent = 0;
boost::uint64_t total_received = 0;
for (std::list<peer_conn*>::iterator i = conns.begin()
for (std::vector<peer_conn*>::iterator i = conns.begin()
, end(conns.end()); i != end; ++i)
{
peer_conn* p = *i;

View File

@ -42,21 +42,21 @@ int load_file(std::string const& filename, std::vector<char>& v, libtorrent::err
FILE* f = fopen(filename.c_str(), "rb");
if (f == NULL)
{
ec.assign(errno, boost::system::get_generic_category());
ec.assign(errno, boost::system::generic_category());
return -1;
}
int r = fseek(f, 0, SEEK_END);
if (r != 0)
{
ec.assign(errno, boost::system::get_generic_category());
ec.assign(errno, boost::system::generic_category());
fclose(f);
return -1;
}
long s = ftell(f);
if (s < 0)
{
ec.assign(errno, boost::system::get_generic_category());
ec.assign(errno, boost::system::generic_category());
fclose(f);
return -1;
}
@ -70,7 +70,7 @@ int load_file(std::string const& filename, std::vector<char>& v, libtorrent::err
r = fseek(f, 0, SEEK_SET);
if (r != 0)
{
ec.assign(errno, boost::system::get_generic_category());
ec.assign(errno, boost::system::generic_category());
fclose(f);
return -1;
}
@ -85,7 +85,7 @@ int load_file(std::string const& filename, std::vector<char>& v, libtorrent::err
r = fread(&v[0], 1, v.size(), f);
if (r < 0)
{
ec.assign(errno, boost::system::get_generic_category());
ec.assign(errno, boost::system::generic_category());
fclose(f);
return -1;
}

View File

@ -50,21 +50,21 @@ int load_file(std::string const& filename, std::vector<char>& v, libtorrent::err
FILE* f = fopen(filename.c_str(), "rb");
if (f == NULL)
{
ec.assign(errno, boost::system::get_generic_category());
ec.assign(errno, boost::system::generic_category());
return -1;
}
int r = fseek(f, 0, SEEK_END);
if (r != 0)
{
ec.assign(errno, boost::system::get_generic_category());
ec.assign(errno, boost::system::generic_category());
fclose(f);
return -1;
}
long s = ftell(f);
if (s < 0)
{
ec.assign(errno, boost::system::get_generic_category());
ec.assign(errno, boost::system::generic_category());
fclose(f);
return -1;
}
@ -78,7 +78,7 @@ int load_file(std::string const& filename, std::vector<char>& v, libtorrent::err
r = fseek(f, 0, SEEK_SET);
if (r != 0)
{
ec.assign(errno, boost::system::get_generic_category());
ec.assign(errno, boost::system::generic_category());
fclose(f);
return -1;
}
@ -93,7 +93,7 @@ int load_file(std::string const& filename, std::vector<char>& v, libtorrent::err
r = fread(&v[0], 1, v.size(), f);
if (r < 0)
{
ec.assign(errno, boost::system::get_generic_category());
ec.assign(errno, boost::system::generic_category());
fclose(f);
return -1;
}

View File

@ -38,6 +38,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <stdio.h>
using namespace libtorrent;
namespace lt = libtorrent;
int load_file(std::string const& filename, std::vector<char>& v, libtorrent::error_code& ec, int limit = 8000000)
{
@ -45,21 +46,21 @@ int load_file(std::string const& filename, std::vector<char>& v, libtorrent::err
FILE* f = fopen(filename.c_str(), "rb");
if (f == NULL)
{
ec.assign(errno, boost::system::get_generic_category());
ec.assign(errno, boost::system::generic_category());
return -1;
}
int r = fseek(f, 0, SEEK_END);
if (r != 0)
{
ec.assign(errno, boost::system::get_generic_category());
ec.assign(errno, boost::system::generic_category());
fclose(f);
return -1;
}
long s = ftell(f);
if (s < 0)
{
ec.assign(errno, boost::system::get_generic_category());
ec.assign(errno, boost::system::generic_category());
fclose(f);
return -1;
}
@ -73,7 +74,7 @@ int load_file(std::string const& filename, std::vector<char>& v, libtorrent::err
r = fseek(f, 0, SEEK_SET);
if (r != 0)
{
ec.assign(errno, boost::system::get_generic_category());
ec.assign(errno, boost::system::generic_category());
fclose(f);
return -1;
}
@ -88,7 +89,7 @@ int load_file(std::string const& filename, std::vector<char>& v, libtorrent::err
r = fread(&v[0], 1, v.size(), f);
if (r < 0)
{
ec.assign(errno, boost::system::get_generic_category());
ec.assign(errno, boost::system::generic_category());
fclose(f);
return -1;
}
@ -163,13 +164,13 @@ int main(int argc, char* argv[])
return 0;
}
session ses;
lt::session ses;
session_settings sett;
sett.active_downloads = 2;
sett.active_seeds = 1;
sett.active_limit = 3;
ses.set_settings(sett);
settings_pack pack;
pack.set_int(settings_pack::active_downloads, 2);
pack.set_int(settings_pack::active_seeds, 1);
pack.set_int(settings_pack::active_limit, 3);
ses.apply_settings(pack);
std::vector<char> in;
error_code ec;

View File

@ -6,6 +6,8 @@ import shlex
import time
import subprocess
import random
import signal
import hashlib
# this is a disk I/O benchmark script. It runs menchmarks
# over different filesystems, different cache sizes and
@ -29,43 +31,51 @@ import random
# variables to test. All these are run on the first
# entry in the filesystem list.
cache_sizes = [0, 32768, 393216]
peers = [200, 1000, 2000]
builds = ['syncio']
cache_sizes = [0, 32768, 400000]
peers = [200, 500, 1000]
builds = ['rtorrent', 'utorrent', 'aio', 'syncio']
# the drives are assumed to be mounted under ./<name>
# or have symbolic links to them.
#filesystem = ['ext4', 'ext3', 'reiser', 'xfs']
filesystem = ['ext3']
filesystem = ['xfs', 'ext4', 'ext3', 'reiser']
default_fs = filesystem[0]
# the number of peers for the filesystem test. The
# idea is to stress test the filesystem by using a lot
# of peers, since each peer essentially is a separate
# read location on the platter
filesystem_peers = 200
default_peers = peers[1]
# the amount of cache for the filesystem test
# 6 GiB of cache
filesystem_cache = 393216
# 5.5 GiB of cache
default_cache = cache_sizes[-1]
# the number of seconds to run each test. It's important that
# this is shorter than what it takes to finish downloading
# the test torrent, since then the average rate will not
# be representative of the peak anymore
# this has to be long enough to download a full copy
# of the test torrent
test_duration = 1000
# of the test torrent. It's also important for the
# test to be long enough that the warming up of the
# disk cache is not a significant part of the test,
# since download rates will be extremely high while downloading
# into RAM
test_duration = 200 # 700
# make sure the environment is properly set up
try:
if os.name == 'posix':
resource.setrlimit(resource.RLIMIT_NOFILE, (4000, 5000))
except:
if resource.getrlimit(resource.RLIMIT_NOFILE)[0] < 4000:
print 'please set ulimit -n to at least 4000'
sys.exit(1)
def build_stage_dirs():
ret = []
for i in builds:
for i in builds[2:3]:
ret.append('stage_%s' % i)
return ret
@ -88,29 +98,81 @@ for i in filesystem:
# make sure we have a test torrent
if not os.path.exists('test.torrent'):
print 'generating test torrent'
os.system('./stage_%s/connection_tester gen-torrent test.torrent' % builds[0])
# generate a 100 GB torrent, to make sure it won't all fit in physical RAM
os.system('./stage_aio/connection_tester gen-torrent 10000 test.torrent')
if not os.path.exists('test2.torrent'):
print 'generating test torrent 2'
# generate a 6 GB torrent, to make sure it will fit in physical RAM
os.system('./stage_aio/connection_tester gen-torrent 6000 test2.torrent')
# use a new port for each test to make sure they keep working
# this port is incremented for each test run
port = 10000 + random.randint(0, 5000)
port = 10000 + random.randint(0, 40000)
def clear_caches():
if 'linux' in sys.platform:
os.system('sync')
open('/proc/sys/vm/drop_caches', 'w').write('3')
elif 'darwin' in sys.platform:
os.system('purge')
def build_commandline(config, port):
num_peers = config['num-peers']
no_disk_reorder = '';
if config['allow-disk-reorder'] == False:
no_disk_reorder = '-O'
no_read_ahead = ''
if config['read-ahead'] == False:
no_read_ahead = '-j'
allocation_mode = config['allocation-mode']
torrent_path = config['torrent']
#TODO: take config['coalesce'] into account
if config['build'] == 'utorrent':
try: os.mkdir('utorrent_session')
except: pass
cfg = open('utorrent_session/settings.dat', 'w+')
global test_duration
cfg.write('d')
cfg.write('20:ul_slots_per_torrenti%de' % num_peers)
cfg.write('17:conns_per_torrenti%de' % num_peers)
cfg.write('14:conns_globallyi%de' % num_peers)
cfg.write('9:bind_porti%de' % port)
cfg.write('19:dir_active_download%d:%s' % (len(config['save-path']), config['save-path']))
cfg.write('19:diskio.sparse_filesi1e')
cfg.write('14:cache.overridei1e')
cfg.write('19:cache.override_sizei%de' % int(config['cache-size'] * 16 / 1024))
cfg.write('17:dir_autoload_flagi1e')
cfg.write('12:dir_autoload8:autoload')
cfg.write('11:logger_maski4294967295e')
cfg.write('1:vi0e')
cfg.write('12:webui.enablei1e')
cfg.write('19:webui.enable_listeni1e')
cfg.write('14:webui.hashword20:' + hashlib.sha1('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadmin').digest())
cfg.write('10:webui.porti8080e')
cfg.write('10:webui.salt32:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')
cfg.write('14:webui.username5:admin')
cfg.write('e')
cfg.close()
try: os.mkdir('utorrent_session/autoload')
except: pass
try: shutil.copy(torrent_path, 'utorrent_session/autoload/')
except: pass
return './utorrent-server-v3_0/utserver -logfile session_stats/alerts_log.txt -settingspath utorrent_session'
return './stage_%s/client_test -k -z -N -h -H -M -B %d -l %d -S %d -T %d -c %d -C %d -s "%s" %s %s -q %d -p %d -f session_stats/alerts_log.txt -a %s test.torrent' \
% (config['build'], test_duration, num_peers, num_peers, num_peers, num_peers, config['cache-size'], config['save-path'] \
, no_disk_reorder, no_read_ahead, test_duration, port, config['allocation-mode'])
if config['build'] == 'rtorrent':
if os.path.exists('rtorrent_session'):
add_command = ''
else:
try: os.mkdir('rtorrent_session')
except: pass
# it seems rtorrent may delete the original torrent when it's being added
try: shutil.copy(torrent_path, 'rtorrent_session/')
except: pass
add_command = '-O load_start_verbose=rtorrent_session/%s ' % torrent_path
return 'rtorrent -d %s -n -p %d-%d -O max_peers=%d -O max_uploads=%d %s -s rtorrent_session -O max_memory_usage=128000000000' \
% (config['save-path'], port, port, num_peers, num_peers, add_command)
disable_disk = ''
if config['disable-disk']: disable_disk = '-0'
return './stage_%s/client_test -k -N -H -M -B %d -l %d -S %d -T %d -c %d -C %d -s "%s" -p %d -E %d %s -f session_stats/alerts_log.txt %s' \
% (config['build'], test_duration, num_peers, num_peers, num_peers, num_peers, config['cache-size'], config['save-path'], port, \
config['hash-threads'], disable_disk, torrent_path)
def delete_files(files):
for i in files:
@ -119,29 +181,78 @@ def delete_files(files):
try: shutil.rmtree(i)
except:
try:
if os.exists(i): print 'failed to delete %s' % i
if os.path.exists(i): print 'failed to delete %s' % i
except: pass
def build_test_config(fs, num_peers, cache_size, readahead=True, reorder=True, preallocate=False, coalesce=True, test='upload', build='aio'):
config = {'test': test, 'save-path': os.path.join('./', fs), 'num-peers': num_peers, 'allow-disk-reorder': reorder, 'cache-size': cache_size, 'read-ahead': readahead}
if preallocate: config['allocation-mode'] = 'allocate'
else: config['allocation-mode'] = 'sparse'
if coalesce: config['coalesce'] = True
else: config['coalesce'] = False
config['build'] = build
# typically the schedulers available are 'noop', 'deadline' and 'cfq'
def build_test_config(fs=default_fs, num_peers=default_peers, cache_size=default_cache, \
test='upload', build='aio', profile='', hash_threads=1, torrent='test.torrent', \
disable_disk = False):
config = {'test': test, 'save-path': os.path.join('./', fs), 'num-peers': num_peers, \
'cache-size': cache_size, 'build': build, 'profile':profile, \
'hash-threads': hash_threads, 'torrent': torrent, 'disable-disk': disable_disk }
return config
def prefix_len(text, prefix):
for i in xrange(1, len(prefix)):
if (not text.startswith(prefix[0:i])): return i-1
return len(prefix)
def device_name(path):
mount = subprocess.Popen('mount', stdout=subprocess.PIPE)
max_match_len = 0
match_device = ''
path = os.path.abspath(path)
for mp in mount.stdout.readlines():
c = mp.split(' ')
device = c[0]
mountpoint = c[2]
prefix = prefix_len(path, mountpoint)
if prefix > max_match_len:
max_match_len = prefix
match_device = device
device = match_device
device = device.split('/')[-1][0:3]
print 'device for path: %s -> %s' % (path, device)
return device
def build_target_folder(config):
reorder = 'reorder'
if config['allow-disk-reorder'] == False: reorder = 'no-reorder'
readahead = 'readahead'
if config['read-ahead'] == False: readahead = 'no-readahead'
coalesce = 'coalesce'
if config['coalesce'] == False: coalesce = 'no-coalesce'
test = 'seed'
if config['test'] == 'upload': test = 'download'
elif config['test'] == 'dual': test = 'dual'
return 'results_%s_%s_%d_%d_%s_%s_%s_%s_%s' % (config['build'], test, config['num-peers'], config['cache-size'], os.path.split(config['save-path'])[1], reorder, readahead, config['allocation-mode'], coalesce)
if 'linux' in sys.platform:
io_scheduler = open('/sys/block/%s/queue/scheduler' % device_name(config['save-path'])).read().split('[')[1].split(']')[0]
else:
io_scheduler = sys.platform
no_disk = ''
if config['disable-disk']: no_disk = '_no-disk'
return 'results_%s_%s_%d_%d_%s_%s_h%d%s' % (config['build'], test, config['num-peers'], \
config['cache-size'], os.path.split(config['save-path'])[1], io_scheduler, \
config['hash-threads'], no_disk)
def find_library(name):
paths = ['/usr/lib64/', '/usr/local/lib64/', '/usr/lib/', '/usr/local/lib/']
for p in paths:
try:
if os.path.exists(p + name): return p + name
except: pass
return name
def find_binary(names):
paths = ['/usr/bin/', '/usr/local/bin/']
for n in names:
for p in paths:
try:
if os.path.exists(p + n): return p + n
except: pass
return names[0]
def run_test(config):
@ -150,12 +261,18 @@ def run_test(config):
print 'results already exists, skipping test (%s)' % target_folder
return
print '\n\n*********************************'
print '* RUNNING TEST *'
print '*********************************\n\n'
print '%s %s' % (config['build'], config['test'])
# make sure any previous test file is removed
# don't clean up unless we're running a download-test, so that we leave the test file
# complete for a seed test.
if config['test'] == 'upload':
delete_files(['utorrent_session/settings.dat', 'utorrent_session/settings.dat.old', 'asserts.log'])
if config['test'] == 'upload' or config['test'] == 'dual':
print 'deleting files'
delete_files([os.path.join(config['save-path'], 'stress_test_file'), '.ses_state', os.path.join(config['save-path'], '.resume'), '.dht_state', 'session_stats'])
delete_files([os.path.join(config['save-path'], 'stress_test_file'), '.ses_state', os.path.join(config['save-path'], '.resume'), 'utorrent_session', '.dht_state', 'session_stats', 'rtorrent_session'])
try: os.mkdir('session_stats')
except: pass
@ -163,6 +280,11 @@ def run_test(config):
# save off the command line for reference
global port
cmdline = build_commandline(config, port)
binary = cmdline.split(' ')[0]
environment = None
if config['profile'] == 'tcmalloc': environment = {'LD_PRELOAD':find_library('libprofiler.so.0'), 'CPUPROFILE': 'session_stats/cpu_profile.prof'}
if config['profile'] == 'memory': environment = {'LD_PRELOAD':find_library('libprofiler.so.0'), 'HEAPPROFILE': 'session_stats/heap_profile.prof'}
if config['profile'] == 'perf': cmdline = 'perf timechart record --call-graph --output=session_stats/perf_profile.prof ' + cmdline
f = open('session_stats/cmdline.txt', 'w+')
f.write(cmdline)
f.close()
@ -171,80 +293,145 @@ def run_test(config):
print >>f, config
f.close()
print '\n\n*********************************'
print '* RUNNING TEST *'
print '*********************************\n\n'
print 'clearing disk cache'
clear_caches()
print 'OK'
client_output = open('session_stats/client.output', 'w+')
client_error = open('session_stats/client.error', 'w+')
print 'launching: %s' % cmdline
client = subprocess.Popen(shlex.split(cmdline), stdout=client_output, stdin=subprocess.PIPE)
client = subprocess.Popen(shlex.split(cmdline), stdout=client_output, stdin=subprocess.PIPE, stderr=client_error, env=environment)
print 'OK'
# enable disk stats printing
if config['build'] != 'rtorrent' and config['build'] != 'utorrent':
print >>client.stdin, 'x',
# when allocating storage, we have to wait for it to complete before we can connect
time.sleep(1)
cmdline = './stage_%s/connection_tester %s %d 127.0.0.1 %d test.torrent' % (config['build'], config['test'], config['num-peers'], port)
time.sleep(4)
cmdline = './stage_aio/connection_tester %s %d 127.0.0.1 %d %s' % (config['test'], config['num-peers'], port, config['torrent'])
print 'launching: %s' % cmdline
tester_output = open('session_stats/tester.output', 'w+')
tester = subprocess.Popen(shlex.split(cmdline), stdout=tester_output)
print 'OK'
tester.wait()
time.sleep(2)
print '\n'
i = 0
while True:
time.sleep(1)
tester.poll()
if tester.returncode != None:
print 'tester terminated'
break
client.poll()
if client.returncode != None:
print 'client terminated'
break
print '\r%d / %d' % (i, test_duration),
sys.stdout.flush()
i += 1
if config['test'] != 'upload' and config['test'] != 'dual' and i >= test_duration: break
print '\n'
if client.returncode == None:
try:
print 'killing client'
client.send_signal(signal.SIGINT)
except:
pass
time.sleep(10)
client.wait()
tester.wait()
tester_output.close()
client_output.close()
if tester.returncode != 0: sys.exit(tester.returncode)
if client.returncode != 0: sys.exit(client.returncode)
terminate = False
if tester.returncode != 0:
print 'tester returned %d' % tester.returncode
terminate = True
if client.returncode != 0:
print 'client returned %d' % client.returncode
terminate = True
try: shutil.copy('asserts.log', 'session_stats/')
except: pass
try: shutil.move('libtorrent_logs0', 'session_stats/')
except: pass
try: shutil.move('libtorrent_logs%s' % port, 'session_stats/')
except: pass
# run fragmentation test
print 'analyzing fragmentation'
os.system('./stage_%s/fragmentation_test test.torrent %s' % (config['build'], config['save-path']))
shutil.copy('fragmentation.log', 'session_stats/')
shutil.copy('fragmentation.png', 'session_stats/')
os.system('./stage_aio/fragmentation_test test.torrent %s' % (config['save-path']))
try: shutil.copy('fragmentation.log', 'session_stats/')
except: pass
shutil.copy('fragmentation.gnuplot', 'session_stats/')
try: shutil.copy('file_access.log', 'session_stats/')
except: pass
os.system('filefrag %s >session_stats/filefrag.out' % config['save-path'])
os.system('filefrag -v %s >session_stats/filefrag_verbose.out' % config['save-path'])
os.chdir('session_stats')
# parse session stats
print 'parsing session log'
os.system('python ../../parse_session_stats.py *.0000.log')
os.system('../stage_aio/parse_access_log file_access.log %s' % (os.path.join('..', config['save-path'], 'stress_test_file')))
os.chdir('..')
if config['profile'] == 'tcmalloc':
print 'analyzing CPU profile [%s]' % binary
os.system('%s --pdf %s session_stats/cpu_profile.prof >session_stats/cpu_profile.pdf' % (find_binary(['google-pprof', 'pprof']), binary))
if config['profile'] == 'memory':
for i in xrange(1, 300):
profile = 'session_stats/heap_profile.prof.%04d.heap' % i
try: os.stat(profile)
except: break
print 'analyzing heap profile [%s] %d' % (binary, i)
os.system('%s --pdf %s %s >session_stats/heap_profile_%d.pdf' % (find_binary(['google-pprof', 'pprof']), binary, profile, i))
if config['profile'] == 'perf':
print 'analyzing CPU profile [%s]' % binary
os.system('perf timechart --input=session_stats/perf_profile.prof --output=session_stats/profile_timechart.svg')
os.system('perf report --input=session_stats/perf_profile.prof --threads --show-nr-samples --vmlinux vmlinuz-2.6.38-8-generic.bzip >session_stats/profile.txt')
# move the results into its final place
print 'saving results'
os.rename('session_stats', build_target_folder(config))
# clean up
# don't clean up unless we ran a seed-test, so that we leave the test file
# complete for the seed test. i.e. we don't clean up if we ran a download test
# if config['test'] == 'download':
# print 'cleaning up'
# delete_files([os.path.join(config['save-path'], 'stress_test_file'), '.ses_state', os.path.join(config['save-path'], '.resume'), '.dht_state'])
port += 1
#config = build_test_config('ext4', filesystem_peers, filesystem_cache, True, True, False)
#run_test(config)
#sys.exit(0)
if terminate: sys.exit(1)
for h in range(0, 7):
config = build_test_config(num_peers=30, build='aio', test='upload', torrent='test.torrent', hash_threads=h, disable_disk=True)
run_test(config)
sys.exit(0)
for b in ['aio', 'syncio']:
for test in ['dual', 'upload', 'download']:
config = build_test_config(build=b, test=test)
run_test(config)
sys.exit(0)
for fs in filesystem:
# for preallocate in [True, False]:
rdahead = True
reorder = True
preallocate = False
for b in builds:
for test in ['upload', 'download']:
config = build_test_config(fs, filesystem_peers, filesystem_cache, rdahead, reorder, preallocate, test=test, build=b)
config = build_test_config(build=b, test=test)
run_test(config)
for p in peers:
for test in ['upload', 'download']:
config = build_test_config(num_peers=p, test=test)
run_test(config)
for c in cache_sizes:
for p in peers:
# for rdahead in [True, False]:
rdahead = False
# for reorder in [True, False]:
reorder = True
# for preallocate in [True, False]:
preallocate = False
for b in builds:
for test in ['upload', 'download']:
config = build_test_config(filesystem[0], p, c, rdahead, reorder, preallocate, test=test, build=b)
config = build_test_config(cache_size=c, test=test)
run_test(config)
for fs in filesystem:
for test in ['upload', 'download']:
config = build_test_config(fs=fs, test=test)
run_test(config)

View File

@ -31,6 +31,7 @@ POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdlib.h>
#include <boost/make_shared.hpp>
#include "libtorrent/entry.hpp"
#include "libtorrent/bencode.hpp"
#include "libtorrent/session.hpp"
@ -38,6 +39,7 @@ POSSIBILITY OF SUCH DAMAGE.
int main(int argc, char* argv[])
{
using namespace libtorrent;
namespace lt = libtorrent;
if (argc != 2)
{
@ -46,9 +48,10 @@ int main(int argc, char* argv[])
return 1;
}
session s;
settings_pack sett;
sett.set_str(settings_pack::listen_interfaces, "0.0.0.0:6881");
lt::session s(sett);
error_code ec;
s.listen_on(std::make_pair(6881, 6889), ec);
if (ec)
{
fprintf(stderr, "failed to open listen socket: %s\n", ec.message().c_str());
@ -56,7 +59,7 @@ int main(int argc, char* argv[])
}
add_torrent_params p;
p.save_path = "./";
p.ti = new torrent_info(argv[1], ec);
p.ti = boost::make_shared<torrent_info>(std::string(argv[1]), boost::ref(ec), 0);
if (ec)
{
fprintf(stderr, "%s\n", ec.message().c_str());

View File

@ -0,0 +1,49 @@
/*
Copyright (c) 2008, Arvid Norberg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <libtorrent/session.hpp>
using namespace libtorrent;
int main()
{
std::vector<stats_metric> m = session_stats_metrics();
for (int i = 0; i < int(m.size()); ++i)
{
printf("%s: %s (%d)\n"
, m[i].type == stats_metric::type_counter ? "CNTR" : "GAUG"
, m[i].name, m[i].value_index);
}
return 0;
}

View File

@ -63,6 +63,7 @@ void print_alert(libtorrent::alert const* a)
int main(int argc, char* argv[])
{
using namespace libtorrent;
namespace lt = libtorrent;
if (argc != 1)
{
@ -70,16 +71,19 @@ int main(int argc, char* argv[])
return 1;
}
session s;
s.set_alert_mask(alert::port_mapping_notification);
settings_pack p;
p.set_int(settings_pack::alert_mask, alert::port_mapping_notification);
lt::session s(p);
for (;;)
{
alert const* a = s.wait_for_alert(seconds(5));
if (a == 0)
{
s.stop_upnp();
s.stop_natpmp();
settings_pack p;
p.set_bool(settings_pack::enable_upnp, false);
p.set_bool(settings_pack::enable_natpmp, false);
s.apply_settings(p);
break;
}
std::auto_ptr<alert> holder = s.pop_alert();

53
gather_todo.py Normal file
View File

@ -0,0 +1,53 @@
import glob
import os
paths = ['src/*.cpp', 'src/kademlia/*.cpp', 'include/libtorrent/*.hpp', 'include/libtorrent/kademlia/*.hpp', 'include/libtorrent/aux_/*.hpp', 'include/libtorrent/extensions/*.hpp']
os.system('ctags %s' % ' '.join(paths))
files = []
for p in paths:
files.extend(glob.glob(p))
output = open('todo.rst', 'w+')
for f in files:
h = open(f)
state = ''
line_no = 0
for line in h:
line_no += 1
line = line.strip()
if 'TODO:' in line and line.startswith('//'):
line = line.split('TODO:')[1]
state = 'todo'
headline = '%s:%d' % (f.replace('_', '\\_'), line_no)
print >>output, '\n' + headline
print >>output, ('-' * len(headline)) + '\n'
print >>output, line.strip()
continue
if state == '': continue
if state == 'todo':
if line.strip().startswith('//'):
print >>output, line[2:].strip()
else:
state = 'context'
print >>output, '\n::\n'
print >>output, '\t%s' % line
continue
if state == 'context':
print >>output, '\t%s' % line
state = ''
h.close()
output.close()
os.system('rst2html-2.6.py todo.rst >todo.html')

View File

@ -9,33 +9,44 @@ nobase_include_HEADERS = \
add_torrent_params.hpp \
alert.hpp \
alert_manager.hpp \
alert_observer.hpp \
alert_dispatcher.hpp \
alert_types.hpp \
alloca.hpp \
allocator.hpp \
assert.hpp \
atomic.hpp \
bandwidth_limit.hpp \
bandwidth_manager.hpp \
bandwidth_socket.hpp \
bandwidth_queue_entry.hpp \
bencode.hpp \
bitfield.hpp \
block_cache.hpp \
bloom_filter.hpp \
broadcast_socket.hpp \
bt_peer_connection.hpp \
buffer.hpp \
build_config.hpp \
byteswap.hpp \
chained_buffer.hpp \
config.hpp \
connection_interface.hpp \
connection_queue.hpp \
ConvertUTF.h \
copy_ptr.hpp \
cpuid.hpp \
crc32c.hpp \
create_torrent.hpp \
deadline_timer.hpp \
debug.hpp \
disk_buffer_holder.hpp \
disk_buffer_pool.hpp \
disk_interface.hpp \
disk_io_job.hpp \
disk_io_thread.hpp \
disk_observer.hpp \
disk_job_pool.hpp \
entry.hpp \
enum_net.hpp \
error.hpp \
@ -64,30 +75,43 @@ nobase_include_HEADERS = \
ip_filter.hpp \
ip_voter.hpp \
lazy_entry.hpp \
link.hpp \
linked_list.hpp \
lsd.hpp \
magnet_uri.hpp \
max.hpp \
natpmp.hpp \
network_thread_pool.hpp \
packet_buffer.hpp \
parse_url.hpp \
part_file.hpp \
pe_crypto.hpp \
performance_counters.hpp \
peer_connection.hpp \
peer_connection_interface.hpp \
peer.hpp \
peer_class.hpp \
peer_class_set.hpp \
peer_class_type_filter.hpp \
peer_id.hpp \
peer_info.hpp \
peer_request.hpp \
piece_block_progress.hpp \
piece_picker.hpp \
platform_util.hpp \
policy.hpp \
proxy_base.hpp \
ptime.hpp \
puff.hpp \
random.hpp \
resolver.hpp \
resolver_interface.hpp \
rss.hpp \
session.hpp \
session_settings.hpp \
session_status.hpp \
settings.hpp \
settings_pack.hpp \
sha1_hash.hpp \
size_type.hpp \
sliding_average.hpp \
@ -98,23 +122,30 @@ nobase_include_HEADERS = \
socks5_stream.hpp \
ssl_stream.hpp \
stat.hpp \
stat_cache.hpp \
storage.hpp \
storage_defs.hpp \
tailqueue.hpp \
string_util.hpp \
thread.hpp \
thread_pool.hpp \
time.hpp \
timestamp_history.hpp \
torrent_handle.hpp \
torrent.hpp \
torrent_info.hpp \
torrent_peer.hpp \
torrent_peer_allocator.hpp \
tracker_manager.hpp \
udp_socket.hpp \
udp_tracker_connection.hpp \
uncork_interface.hpp \
union_endpoint.hpp \
upnp.hpp \
utp_socket_manager.hpp \
utp_stream.hpp \
utf8.hpp \
vector_utils.hpp \
version.hpp \
web_connection_base.hpp \
web_peer_connection.hpp \
@ -126,6 +157,7 @@ nobase_include_HEADERS = \
tommath_superclass.h \
\
aux_/session_impl.hpp \
aux_/session_settings.hpp\
\
extensions/logger.hpp \
extensions/lt_trackers.hpp \
@ -136,6 +168,7 @@ nobase_include_HEADERS = \
\
kademlia/dht_tracker.hpp \
kademlia/dht_observer.hpp \
kademlia/dos_blocker.hpp \
kademlia/find_data.hpp \
kademlia/logging.hpp \
kademlia/msg.hpp \

View File

@ -35,7 +35,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <string>
#include <vector>
#include <boost/intrusive_ptr.hpp>
#include <boost/shared_ptr.hpp>
#include "libtorrent/storage_defs.hpp"
#include "libtorrent/peer_id.hpp" // sha1_hash
@ -249,20 +249,26 @@ namespace libtorrent
// case the save_path specified in add_torrent_params is always used.
flag_use_resume_save_path = 0x1000,
// indicates that this torrent should never be unloaded from RAM, even
// if unloading torrents are allowed in general. Setting this makes
// the torrent exempt from loading/unloading management.
flag_pinned = 0x2000,
// internal
default_flags = flag_update_subscribe | flag_auto_managed | flag_paused | flag_apply_ip_filter
default_flags = flag_pinned | flag_update_subscribe
| flag_auto_managed | flag_paused | flag_apply_ip_filter
#ifndef TORRENT_NO_DEPRECATE
, flag_ignore_flags = 0x80000000
#endif
};
// filled in by the constructor and should be left untouched. It
// is used for forward binary compatibility.
// filled in by the constructor and should be left untouched. It is used
// for forward binary compatibility.
int version;
// torrent_info object with the torrent to add. Unless the url or
// info_hash is set, this is required to be initiazlied.
boost::intrusive_ptr<torrent_info> ti;
boost::shared_ptr<torrent_info> ti;
#ifndef TORRENT_NO_DEPRECATE
char const* tracker_url;
@ -350,8 +356,8 @@ namespace libtorrent
// items which has UUIDs specified.
std::string uuid;
// should point to the URL of the RSS feed this torrent comes from,
// if it comes from an RSS feed.
// should point to the URL of the RSS feed this torrent comes from, if it
// comes from an RSS feed.
std::string source_feed_url;
// flags controlling aspects of this torrent and how it's added. See

View File

@ -36,6 +36,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <memory>
#include <deque>
#include <string>
#include <vector>
#ifdef _MSC_VER
#pragma warning(push, 1)
@ -71,7 +72,7 @@ POSSIBILITY OF SUCH DAMAGE.
#pragma warning(pop)
#endif
#include "libtorrent/ptime.hpp"
#include "libtorrent/time.hpp"
#include "libtorrent/config.hpp"
#ifndef TORRENT_NO_DEPRECATE
@ -84,6 +85,12 @@ POSSIBILITY OF SUCH DAMAGE.
#define TORRENT_MAX_ALERT_TYPES 15
#endif
#ifndef TORRENT_NO_DEPRECATE
#ifndef BOOST_NO_TYPEID
#include <typeinfo>
#endif
#endif
namespace libtorrent {
// The ``alert`` class is the base class that specific messages are derived from.

View File

@ -37,7 +37,7 @@ namespace libtorrent
{
class alert;
struct alert_dispatcher
struct TORRENT_EXPORT alert_dispatcher
{
// return true if the alert was swallowed (i.e.
// ownership was taken over). In this case, the

View File

@ -0,0 +1,58 @@
/*
Copyright (c) 2012-2013, Arvid Norberg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TORRENT_ALERT_OBSERVER_HPP_INCLUDED
#define TORRENT_ALERT_OBSERVER_HPP_INCLUDED
#include <boost/cstdint.hpp>
namespace libtorrent
{
class alert;
struct alert_observer
{
friend struct alert_handler;
alert_observer(): num_types(0), flags(0) {}
virtual void handle_alert(alert const* a) = 0;
private:
boost::uint8_t types[64];
int num_types;
int flags;
};
};
#endif // TORRENT_ALERT_OBSERVER_HPP_INCLUDED

View File

@ -43,17 +43,13 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/stat.hpp"
#include "libtorrent/rss.hpp" // for feed_handle
// lines reserved for future includes
// the type-ids of the alert types
// are derived from the line on which
// they are declared
namespace libtorrent
{
// maps an operation id (from peer_error_alert and peer_disconnected_alert)
// to its name. See peer_connection for the constants
TORRENT_EXPORT char const* operation_name(int op);
// user defined alerts should use IDs greater than this
const static int user_alert_id = 10000;
@ -62,17 +58,16 @@ namespace libtorrent
struct TORRENT_EXPORT torrent_alert: alert
{
// internal
torrent_alert(torrent_handle const& h)
: handle(h)
{}
torrent_alert(torrent_handle const& h);
// internal
const static int alert_type = 1;
const static int alert_type = 0;
virtual std::string message() const;
// The torrent_handle pointing to the torrent this
// alert is associated with.
torrent_handle handle;
std::string name;
};
// The peer alert is a base class for alerts that refer to a specific peer. It includes all
@ -87,7 +82,7 @@ namespace libtorrent
, pid(pi)
{}
const static int alert_type = 2;
const static int alert_type = 1;
const static int static_category = alert::peer_notification;
virtual int category() const { return static_category; }
virtual std::string message() const;
@ -111,7 +106,7 @@ namespace libtorrent
, url(u)
{}
const static int alert_type = 3;
const static int alert_type = 2;
const static int static_category = alert::tracker_notification;
virtual int category() const { return static_category; }
virtual std::string message() const;
@ -120,8 +115,8 @@ namespace libtorrent
std::string url;
};
#define TORRENT_DEFINE_ALERT(name) \
const static int alert_type = __LINE__; \
#define TORRENT_DEFINE_ALERT(name, seq) \
const static int alert_type = seq; \
virtual int type() const { return alert_type; } \
virtual std::auto_ptr<alert> clone() const \
{ return std::auto_ptr<alert>(new name(*this)); } \
@ -139,7 +134,7 @@ namespace libtorrent
: torrent_alert(h)
{}
TORRENT_DEFINE_ALERT(torrent_added_alert);
TORRENT_DEFINE_ALERT(torrent_added_alert, 3);
const static int static_category = alert::status_notification;
virtual std::string message() const;
};
@ -164,9 +159,10 @@ namespace libtorrent
, info_hash(ih)
{}
TORRENT_DEFINE_ALERT(torrent_removed_alert);
TORRENT_DEFINE_ALERT(torrent_removed_alert, 4);
const static int static_category = alert::status_notification;
virtual std::string message() const;
virtual bool discardable() const { return false; }
sha1_hash info_hash;
};
@ -195,7 +191,7 @@ namespace libtorrent
, size(0)
{}
TORRENT_DEFINE_ALERT(read_piece_alert);
TORRENT_DEFINE_ALERT(read_piece_alert, 5);
const static int static_category = alert::storage_notification;
virtual std::string message() const;
@ -218,7 +214,7 @@ namespace libtorrent
, index(idx)
{}
TORRENT_DEFINE_ALERT(file_completed_alert);
TORRENT_DEFINE_ALERT(file_completed_alert, 6);
const static int static_category = alert::progress_notification;
virtual std::string message() const;
@ -240,7 +236,7 @@ namespace libtorrent
, index(idx)
{}
TORRENT_DEFINE_ALERT(file_renamed_alert);
TORRENT_DEFINE_ALERT(file_renamed_alert, 7);
const static int static_category = alert::storage_notification;
virtual std::string message() const;
@ -266,7 +262,7 @@ namespace libtorrent
, error(ec)
{}
TORRENT_DEFINE_ALERT(file_rename_failed_alert);
TORRENT_DEFINE_ALERT(file_rename_failed_alert, 8);
const static int static_category = alert::storage_notification;
@ -287,7 +283,7 @@ namespace libtorrent
{
// This warning means that the number of bytes queued to be written to disk
// exceeds the max disk byte queue setting (``session_settings::max_queued_disk_bytes``).
// exceeds the max disk byte queue setting (``settings_pack::max_queued_disk_bytes``).
// This might restrict the download rate, by not queuing up enough write jobs
// to the disk I/O thread. When this alert is posted, peer connections are
// temporarily stopped from downloading, until the queued disk bytes have fallen
@ -296,9 +292,9 @@ namespace libtorrent
outstanding_disk_buffer_limit_reached,
// This is posted when libtorrent would like to send more requests to a peer,
// but it's limited by ``session_settings::max_out_request_queue``. The queue length
// but it's limited by ``settings_pack::max_out_request_queue``. The queue length
// libtorrent is trying to achieve is determined by the download rate and the
// assumed round-trip-time (``session_settings::request_queue_time``). The assumed
// assumed round-trip-time (``settings_pack::request_queue_time``). The assumed
// rount-trip-time is not limited to just the network RTT, but also the remote disk
// access time and message handling time. It defaults to 3 seconds. The target number
// of outstanding requests is set to fill the bandwidth-delay product (assumed RTT
@ -350,10 +346,11 @@ namespace libtorrent
// queue. Either lower ``max_queued_disk_bytes`` or increase ``cache_size``.
too_high_disk_queue_limit,
aio_limit_reached,
bittyrant_with_no_uplimit,
// This is generated if outgoing peer connections are failing because of *address in use*
// errors, indicating that ``session_settings::outgoing_ports`` is set and is too small of
// errors, indicating that ``settings_pack::outgoing_ports`` is set and is too small of
// a range. Consider not using the ``outgoing_ports`` setting at all, or widen the range to
// include more ports.
too_few_outgoing_ports,
@ -370,7 +367,7 @@ namespace libtorrent
, warning_code(w)
{}
TORRENT_DEFINE_ALERT(performance_alert);
TORRENT_DEFINE_ALERT(performance_alert, 9);
const static int static_category = alert::performance_warning;
@ -391,7 +388,7 @@ namespace libtorrent
, prev_state(prev_st)
{}
TORRENT_DEFINE_ALERT(state_changed_alert);
TORRENT_DEFINE_ALERT(state_changed_alert, 10);
const static int static_category = alert::status_notification;
@ -430,7 +427,7 @@ namespace libtorrent
TORRENT_ASSERT(!url.empty());
}
TORRENT_DEFINE_ALERT(tracker_error_alert);
TORRENT_DEFINE_ALERT(tracker_error_alert, 11);
const static int static_category = alert::tracker_notification | alert::error_notification;
virtual std::string message() const;
@ -454,7 +451,7 @@ namespace libtorrent
, msg(m)
{ TORRENT_ASSERT(!url.empty()); }
TORRENT_DEFINE_ALERT(tracker_warning_alert);
TORRENT_DEFINE_ALERT(tracker_warning_alert, 12);
const static int static_category = alert::tracker_notification | alert::error_notification;
virtual std::string message() const;
@ -476,7 +473,7 @@ namespace libtorrent
, complete(comp)
{ TORRENT_ASSERT(!url.empty()); }
TORRENT_DEFINE_ALERT(scrape_reply_alert);
TORRENT_DEFINE_ALERT(scrape_reply_alert, 13);
virtual std::string message() const;
@ -506,7 +503,7 @@ namespace libtorrent
, msg(m)
{ TORRENT_ASSERT(!url.empty()); }
TORRENT_DEFINE_ALERT(scrape_failed_alert);
TORRENT_DEFINE_ALERT(scrape_failed_alert, 14);
const static int static_category = alert::tracker_notification | alert::error_notification;
virtual std::string message() const;
@ -528,7 +525,7 @@ namespace libtorrent
, num_peers(np)
{ TORRENT_ASSERT(!url.empty()); }
TORRENT_DEFINE_ALERT(tracker_reply_alert);
TORRENT_DEFINE_ALERT(tracker_reply_alert, 15);
virtual std::string message() const;
@ -551,7 +548,7 @@ namespace libtorrent
, num_peers(np)
{}
TORRENT_DEFINE_ALERT(dht_reply_alert);
TORRENT_DEFINE_ALERT(dht_reply_alert, 16);
virtual std::string message() const;
@ -570,7 +567,7 @@ namespace libtorrent
, event(e)
{ TORRENT_ASSERT(!url.empty()); }
TORRENT_DEFINE_ALERT(tracker_announce_alert);
TORRENT_DEFINE_ALERT(tracker_announce_alert, 17);
virtual std::string message() const;
@ -595,7 +592,7 @@ namespace libtorrent
, piece_index(index)
{ TORRENT_ASSERT(index >= 0);}
TORRENT_DEFINE_ALERT(hash_failed_alert);
TORRENT_DEFINE_ALERT(hash_failed_alert, 18);
const static int static_category = alert::status_notification;
virtual std::string message() const;
@ -613,7 +610,7 @@ namespace libtorrent
: peer_alert(h, ep, peer_id)
{}
TORRENT_DEFINE_ALERT(peer_ban_alert);
TORRENT_DEFINE_ALERT(peer_ban_alert, 19);
virtual std::string message() const;
};
@ -628,7 +625,7 @@ namespace libtorrent
: peer_alert(h, ep, peer_id)
{}
TORRENT_DEFINE_ALERT(peer_unsnubbed_alert);
TORRENT_DEFINE_ALERT(peer_unsnubbed_alert, 20);
virtual std::string message() const;
};
@ -643,7 +640,7 @@ namespace libtorrent
: peer_alert(h, ep, peer_id)
{}
TORRENT_DEFINE_ALERT(peer_snubbed_alert);
TORRENT_DEFINE_ALERT(peer_snubbed_alert, 21);
virtual std::string message() const;
};
@ -654,8 +651,9 @@ namespace libtorrent
{
// internal
peer_error_alert(torrent_handle const& h, tcp::endpoint const& ep
, peer_id const& peer_id, error_code const& e)
, peer_id const& peer_id, int op, error_code const& e)
: peer_alert(h, ep, peer_id)
, operation(op)
, error(e)
{
#ifndef TORRENT_NO_DEPRECATE
@ -663,13 +661,14 @@ namespace libtorrent
#endif
}
TORRENT_DEFINE_ALERT(peer_error_alert);
TORRENT_DEFINE_ALERT(peer_error_alert, 22);
const static int static_category = alert::peer_notification;
virtual std::string message() const
{
return peer_alert::message() + " peer error: " + convert_from_native(error.message());
}
virtual std::string message() const;
// a NULL-terminated string of the low-level operation that failed, or NULL if
// there was no low level disk operation.
int operation;
// tells you what error caused this alert.
error_code error;
@ -689,7 +688,7 @@ namespace libtorrent
, socket_type(type)
{}
TORRENT_DEFINE_ALERT(peer_connect_alert);
TORRENT_DEFINE_ALERT(peer_connect_alert, 23);
const static int static_category = alert::debug_notification;
virtual std::string message() const;
@ -703,8 +702,9 @@ namespace libtorrent
{
// internal
peer_disconnected_alert(torrent_handle const& h, tcp::endpoint const& ep
, peer_id const& peer_id, error_code const& e)
, peer_id const& peer_id, int op, error_code const& e)
: peer_alert(h, ep, peer_id)
, operation(op)
, error(e)
{
#ifndef TORRENT_NO_DEPRECATE
@ -712,11 +712,15 @@ namespace libtorrent
#endif
}
TORRENT_DEFINE_ALERT(peer_disconnected_alert);
TORRENT_DEFINE_ALERT(peer_disconnected_alert, 24);
const static int static_category = alert::debug_notification;
virtual std::string message() const;
// a NULL-terminated string of the low-level operation that failed, or NULL if
// there was no low level disk operation.
int operation;
// tells you what error caused peer to disconnect.
error_code error;
@ -737,7 +741,7 @@ namespace libtorrent
, request(r)
{}
TORRENT_DEFINE_ALERT(invalid_request_alert);
TORRENT_DEFINE_ALERT(invalid_request_alert, 25);
virtual std::string message() const;
@ -755,7 +759,7 @@ namespace libtorrent
: torrent_alert(h)
{}
TORRENT_DEFINE_ALERT(torrent_finished_alert);
TORRENT_DEFINE_ALERT(torrent_finished_alert, 26);
const static int static_category = alert::status_notification;
virtual std::string message() const
@ -775,7 +779,7 @@ namespace libtorrent
, piece_index(piece_num)
{ TORRENT_ASSERT(piece_index >= 0);}
TORRENT_DEFINE_ALERT(piece_finished_alert);
TORRENT_DEFINE_ALERT(piece_finished_alert, 27);
const static int static_category = alert::progress_notification;
virtual std::string message() const;
@ -795,7 +799,7 @@ namespace libtorrent
, piece_index(piece_num)
{ TORRENT_ASSERT(block_index >= 0 && piece_index >= 0);}
TORRENT_DEFINE_ALERT(request_dropped_alert);
TORRENT_DEFINE_ALERT(request_dropped_alert, 28);
const static int static_category = alert::progress_notification
| alert::peer_notification;
@ -816,7 +820,7 @@ namespace libtorrent
, piece_index(piece_num)
{ TORRENT_ASSERT(block_index >= 0 && piece_index >= 0);}
TORRENT_DEFINE_ALERT(block_timeout_alert);
TORRENT_DEFINE_ALERT(block_timeout_alert, 29);
const static int static_category = alert::progress_notification
| alert::peer_notification;
@ -837,7 +841,7 @@ namespace libtorrent
, piece_index(piece_num)
{ TORRENT_ASSERT(block_index >= 0 && piece_index >= 0);}
TORRENT_DEFINE_ALERT(block_finished_alert);
TORRENT_DEFINE_ALERT(block_finished_alert, 30);
const static int static_category = alert::progress_notification;
virtual std::string message() const;
@ -858,7 +862,7 @@ namespace libtorrent
, piece_index(piece_num)
{ TORRENT_ASSERT(block_index >= 0 && piece_index >= 0); }
TORRENT_DEFINE_ALERT(block_downloading_alert);
TORRENT_DEFINE_ALERT(block_downloading_alert, 31);
const static int static_category = alert::progress_notification;
virtual std::string message() const;
@ -880,7 +884,7 @@ namespace libtorrent
, piece_index(piece_num)
{ TORRENT_ASSERT(block_index >= 0 && piece_index >= 0);}
TORRENT_DEFINE_ALERT(unwanted_block_alert);
TORRENT_DEFINE_ALERT(unwanted_block_alert, 32);
virtual std::string message() const;
@ -900,7 +904,7 @@ namespace libtorrent
, path(p)
{}
TORRENT_DEFINE_ALERT(storage_moved_alert);
TORRENT_DEFINE_ALERT(storage_moved_alert, 33);
const static int static_category = alert::storage_notification;
virtual std::string message() const
@ -917,21 +921,35 @@ namespace libtorrent
struct TORRENT_EXPORT storage_moved_failed_alert: torrent_alert
{
// internal
storage_moved_failed_alert(torrent_handle const& h, error_code const& e)
storage_moved_failed_alert(torrent_handle const& h
, error_code const& e
, std::string const& file
, char const* op)
: torrent_alert(h)
, error(e)
, file(file)
, operation(op)
{}
TORRENT_DEFINE_ALERT(storage_moved_failed_alert);
TORRENT_DEFINE_ALERT(storage_moved_failed_alert, 34);
const static int static_category = alert::storage_notification;
virtual std::string message() const
{
return torrent_alert::message() + " storage move failed: "
return torrent_alert::message() + " storage move failed. "
+ (operation?operation:"") + " (" + file + "): "
+ convert_from_native(error.message());
}
error_code error;
// If the error happened for a speific file, ``file`` is its path. If the error
// happened in a specific disk operation.
std::string file;
// a NULL terminated string
// naming which one, otherwise it's NULL.
char const* operation;
};
// This alert is generated when a request to delete the files of a torrent complete.
@ -950,7 +968,7 @@ namespace libtorrent
: torrent_alert(h)
{ info_hash = ih; }
TORRENT_DEFINE_ALERT(torrent_deleted_alert);
TORRENT_DEFINE_ALERT(torrent_deleted_alert, 35);
const static int static_category = alert::storage_notification;
virtual std::string message() const
@ -975,7 +993,7 @@ namespace libtorrent
#endif
}
TORRENT_DEFINE_ALERT(torrent_delete_failed_alert);
TORRENT_DEFINE_ALERT(torrent_delete_failed_alert, 36);
const static int static_category = alert::storage_notification
| alert::error_notification;
@ -1008,7 +1026,7 @@ namespace libtorrent
, resume_data(rd)
{}
TORRENT_DEFINE_ALERT(save_resume_data_alert);
TORRENT_DEFINE_ALERT(save_resume_data_alert, 37);
const static int static_category = alert::storage_notification;
virtual std::string message() const
@ -1034,7 +1052,7 @@ namespace libtorrent
#endif
}
TORRENT_DEFINE_ALERT(save_resume_data_failed_alert);
TORRENT_DEFINE_ALERT(save_resume_data_failed_alert, 38);
const static int static_category = alert::storage_notification
| alert::error_notification;
@ -1062,7 +1080,7 @@ namespace libtorrent
: torrent_alert(h)
{}
TORRENT_DEFINE_ALERT(torrent_paused_alert);
TORRENT_DEFINE_ALERT(torrent_paused_alert, 39);
const static int static_category = alert::status_notification;
virtual std::string message() const
@ -1077,7 +1095,7 @@ namespace libtorrent
torrent_resumed_alert(torrent_handle const& h)
: torrent_alert(h) {}
TORRENT_DEFINE_ALERT(torrent_resumed_alert);
TORRENT_DEFINE_ALERT(torrent_resumed_alert, 40);
const static int static_category = alert::status_notification;
virtual std::string message() const
@ -1093,7 +1111,7 @@ namespace libtorrent
: torrent_alert(h)
{}
TORRENT_DEFINE_ALERT(torrent_checked_alert);
TORRENT_DEFINE_ALERT(torrent_checked_alert, 41);
const static int static_category = alert::status_notification;
virtual std::string message() const
@ -1121,7 +1139,7 @@ namespace libtorrent
, msg(m)
{}
TORRENT_DEFINE_ALERT(url_seed_alert);
TORRENT_DEFINE_ALERT(url_seed_alert, 42);
const static int static_category = alert::peer_notification | alert::error_notification;
virtual std::string message() const
@ -1143,27 +1161,30 @@ namespace libtorrent
{
// internal
file_error_alert(
std::string const& f
, torrent_handle const& h
, error_code const& e)
error_code const& ec
, std::string const& file
, char const* op
, torrent_handle const& h)
: torrent_alert(h)
, file(f)
, error(e)
, file(file)
, error(ec)
, operation(op)
{
#ifndef TORRENT_NO_DEPRECATE
msg = convert_from_native(error.message());
#endif
}
TORRENT_DEFINE_ALERT(file_error_alert);
TORRENT_DEFINE_ALERT(file_error_alert, 43);
const static int static_category = alert::status_notification
| alert::error_notification
| alert::storage_notification;
virtual std::string message() const
{
return torrent_alert::message() + " file (" + file + ") error: "
+ convert_from_native(error.message());
return torrent_alert::message() + " "
+ (operation?operation:"") + " (" + file
+ ") error: " + convert_from_native(error.message());
}
// the path to the file that was accessed when the error occurred.
@ -1171,6 +1192,7 @@ namespace libtorrent
// the error code describing the error.
error_code error;
char const* operation;
#ifndef TORRENT_NO_DEPRECATE
std::string msg;
@ -1184,18 +1206,19 @@ namespace libtorrent
struct TORRENT_EXPORT metadata_failed_alert: torrent_alert
{
// internal
metadata_failed_alert(const torrent_handle& h, error_code e)
metadata_failed_alert(const torrent_handle& h, error_code const& ec)
: torrent_alert(h)
, error(e)
, error(ec)
{}
TORRENT_DEFINE_ALERT(metadata_failed_alert);
TORRENT_DEFINE_ALERT(metadata_failed_alert, 44);
const static int static_category = alert::error_notification;
virtual std::string message() const
{ return torrent_alert::message() + " invalid metadata received"; }
{ return torrent_alert::message() + " invalid metadata received: " + error.message(); }
// the error that occurred
// indicates what failed when parsing the metadata. This error is
// what's returned from lazy_bdecode().
error_code error;
};
@ -1211,7 +1234,7 @@ namespace libtorrent
//
// torrent_handle h = alert->handle();
// if (h.is_valid()) {
// boost::intrusive_ptr<torrent_info const> ti = h.torrent_file();
// boost::shared_ptr<torrent_info const> ti = h.torrent_file();
// create_torrent ct(*ti);
// entry te = ct.generate();
// std::vector<char> buffer;
@ -1231,7 +1254,7 @@ namespace libtorrent
: torrent_alert(h)
{}
TORRENT_DEFINE_ALERT(metadata_received_alert);
TORRENT_DEFINE_ALERT(metadata_received_alert, 45);
const static int static_category = alert::status_notification;
virtual std::string message() const
@ -1251,7 +1274,7 @@ namespace libtorrent
, error(ec)
{}
TORRENT_DEFINE_ALERT(udp_error_alert);
TORRENT_DEFINE_ALERT(udp_error_alert, 46);
const static int static_category = alert::error_notification;
virtual std::string message() const
@ -1278,7 +1301,7 @@ namespace libtorrent
: external_address(ip)
{}
TORRENT_DEFINE_ALERT(external_ip_alert);
TORRENT_DEFINE_ALERT(external_ip_alert, 47);
const static int static_category = alert::status_notification;
virtual std::string message() const
@ -1306,24 +1329,24 @@ namespace libtorrent
// internal
listen_failed_alert(
tcp::endpoint const& ep
std::string iface
, int op
, error_code const& ec
, socket_type_t t)
: endpoint(ep)
: interface(iface)
, error(ec)
, operation(op)
, sock_type(t)
{}
TORRENT_DEFINE_ALERT(listen_failed_alert);
TORRENT_DEFINE_ALERT(listen_failed_alert, 48);
const static int static_category = alert::status_notification | alert::error_notification;
virtual std::string message() const;
virtual bool discardable() const { return false; }
// the endpoint libtorrent attempted to listen on
tcp::endpoint endpoint;
// the interface libtorrent attempted to listen on
std::string interface;
// the error the system returned
error_code error;
@ -1353,7 +1376,7 @@ namespace libtorrent
, sock_type(t)
{}
TORRENT_DEFINE_ALERT(listen_succeeded_alert);
TORRENT_DEFINE_ALERT(listen_succeeded_alert, 49);
const static int static_category = alert::status_notification;
virtual std::string message() const;
@ -1384,7 +1407,7 @@ namespace libtorrent
#endif
}
TORRENT_DEFINE_ALERT(portmap_error_alert);
TORRENT_DEFINE_ALERT(portmap_error_alert, 50);
const static int static_category = alert::port_mapping_notification
| alert::error_notification;
@ -1415,7 +1438,7 @@ namespace libtorrent
: mapping(i), external_port(port), map_type(t)
{}
TORRENT_DEFINE_ALERT(portmap_alert);
TORRENT_DEFINE_ALERT(portmap_alert, 51);
const static int static_category = alert::port_mapping_notification;
virtual std::string message() const;
@ -1442,7 +1465,7 @@ namespace libtorrent
: map_type(t), msg(m)
{}
TORRENT_DEFINE_ALERT(portmap_log_alert);
TORRENT_DEFINE_ALERT(portmap_log_alert, 52);
const static int static_category = alert::port_mapping_notification;
virtual std::string message() const;
@ -1458,24 +1481,39 @@ namespace libtorrent
{
// internal
fastresume_rejected_alert(torrent_handle const& h
, error_code const& e)
, error_code const& ec
, std::string const& file
, char const* op)
: torrent_alert(h)
, error(e)
, error(ec)
, file(file)
, operation(op)
{
#ifndef TORRENT_NO_DEPRECATE
msg = convert_from_native(error.message());
#endif
}
TORRENT_DEFINE_ALERT(fastresume_rejected_alert);
TORRENT_DEFINE_ALERT(fastresume_rejected_alert, 53);
const static int static_category = alert::status_notification
| alert::error_notification;
virtual std::string message() const
{ return torrent_alert::message() + " fast resume rejected: " + convert_from_native(error.message()); }
{
return torrent_alert::message() + " fast resume rejected. "
+ (operation?operation:"") + "(" + file + "): " + convert_from_native(error.message());
}
error_code error;
// If the error happend to a specific file, ``file`` is the path to it. If the error happened
// in a disk operation.
std::string file;
// a NULL-terminated string of the name of that operation.
// ``operation`` is NULL otherwise.
char const* operation;
#ifndef TORRENT_NO_DEPRECATE
std::string msg;
#endif
@ -1499,7 +1537,7 @@ namespace libtorrent
, reason(r)
{}
TORRENT_DEFINE_ALERT(peer_blocked_alert);
TORRENT_DEFINE_ALERT(peer_blocked_alert, 54);
const static int static_category = alert::ip_block_notification;
virtual std::string message() const;
@ -1514,7 +1552,8 @@ namespace libtorrent
i2p_mixed,
privileged_ports,
utp_disabled,
tcp_disabled
tcp_disabled,
invalid_local_interface
};
int reason;
@ -1532,7 +1571,7 @@ namespace libtorrent
, info_hash(ih)
{}
TORRENT_DEFINE_ALERT(dht_announce_alert);
TORRENT_DEFINE_ALERT(dht_announce_alert, 55);
const static int static_category = alert::dht_notification;
virtual std::string message() const;
@ -1551,7 +1590,7 @@ namespace libtorrent
: info_hash(ih)
{}
TORRENT_DEFINE_ALERT(dht_get_peers_alert);
TORRENT_DEFINE_ALERT(dht_get_peers_alert, 56);
const static int static_category = alert::dht_notification;
virtual std::string message() const;
@ -1568,7 +1607,7 @@ namespace libtorrent
stats_alert(torrent_handle const& h, int interval
, stat const& s);
TORRENT_DEFINE_ALERT(stats_alert);
TORRENT_DEFINE_ALERT(stats_alert, 57);
const static int static_category = alert::stats_notification;
virtual std::string message() const;
@ -1579,14 +1618,12 @@ namespace libtorrent
upload_protocol,
download_payload,
download_protocol,
#ifndef TORRENT_DISABLE_FULL_STATS
upload_ip_protocol,
upload_dht_protocol,
upload_tracker_protocol,
download_ip_protocol,
download_dht_protocol,
download_tracker_protocol,
#endif
num_channels
};
@ -1611,7 +1648,7 @@ namespace libtorrent
// internal
cache_flushed_alert(torrent_handle const& h);
TORRENT_DEFINE_ALERT(cache_flushed_alert);
TORRENT_DEFINE_ALERT(cache_flushed_alert, 58);
const static int static_category = alert::storage_notification;
};
@ -1630,7 +1667,7 @@ namespace libtorrent
, str(s)
{}
TORRENT_DEFINE_ALERT(anonymous_mode_alert);
TORRENT_DEFINE_ALERT(anonymous_mode_alert, 59);
const static int static_category = alert::error_notification;
virtual std::string message() const;
@ -1658,7 +1695,7 @@ namespace libtorrent
: peer_alert(h, i, peer_id(0))
{}
TORRENT_DEFINE_ALERT(lsd_peer_alert);
TORRENT_DEFINE_ALERT(lsd_peer_alert, 60);
const static int static_category = alert::peer_notification;
virtual std::string message() const;
@ -1677,7 +1714,7 @@ namespace libtorrent
, trackerid(id)
{}
TORRENT_DEFINE_ALERT(trackerid_alert);
TORRENT_DEFINE_ALERT(trackerid_alert, 61);
const static int static_category = alert::status_notification;
virtual std::string message() const;
@ -1692,7 +1729,7 @@ namespace libtorrent
// internal
dht_bootstrap_alert() {}
TORRENT_DEFINE_ALERT(dht_bootstrap_alert);
TORRENT_DEFINE_ALERT(dht_bootstrap_alert, 62);
const static int static_category = alert::dht_notification;
virtual std::string message() const;
@ -1710,7 +1747,7 @@ namespace libtorrent
: handle(h), url(u), state(s), error(ec)
{}
TORRENT_DEFINE_ALERT(rss_alert);
TORRENT_DEFINE_ALERT(rss_alert, 63);
const static int static_category = alert::rss_notification;
virtual std::string message() const;
@ -1750,18 +1787,22 @@ namespace libtorrent
{
// internal
torrent_error_alert(torrent_handle const& h
, error_code const& e)
, error_code const& e, std::string const& f)
: torrent_alert(h)
, error(e)
, error_file(f)
{}
TORRENT_DEFINE_ALERT(torrent_error_alert);
TORRENT_DEFINE_ALERT(torrent_error_alert, 64);
const static int static_category = alert::error_notification | alert::status_notification;
virtual std::string message() const;
// specifies which error the torrent encountered.
error_code error;
// the filename (or object) the error occurred on.
std::string error_file;
};
// This is always posted for SSL torrents. This is a reminder to the client that
@ -1775,7 +1816,7 @@ namespace libtorrent
: torrent_alert(h)
{}
TORRENT_DEFINE_ALERT(torrent_need_cert_alert);
TORRENT_DEFINE_ALERT(torrent_need_cert_alert, 65);
const static int static_category = alert::status_notification;
virtual std::string message() const;
@ -1798,7 +1839,7 @@ namespace libtorrent
, ip(i)
{}
TORRENT_DEFINE_ALERT(incoming_connection_alert);
TORRENT_DEFINE_ALERT(incoming_connection_alert, 66);
const static int static_category = alert::peer_notification;
virtual std::string message() const;
@ -1836,7 +1877,7 @@ namespace libtorrent
, error(ec)
{}
TORRENT_DEFINE_ALERT(add_torrent_alert);
TORRENT_DEFINE_ALERT(add_torrent_alert, 67);
const static int static_category = alert::status_notification;
virtual std::string message() const;
@ -1856,7 +1897,7 @@ namespace libtorrent
// it's not subject to filtering, since it's only manually posted anyway.
struct TORRENT_EXPORT state_update_alert : alert
{
TORRENT_DEFINE_ALERT(state_update_alert);
TORRENT_DEFINE_ALERT(state_update_alert, 68);
const static int static_category = alert::status_notification;
virtual std::string message() const;
@ -1869,6 +1910,49 @@ namespace libtorrent
std::vector<torrent_status> status;
};
struct TORRENT_EXPORT mmap_cache_alert : alert
{
mmap_cache_alert(error_code const& ec): error(ec) {}
TORRENT_DEFINE_ALERT(mmap_cache_alert, 69);
const static int static_category = alert::error_notification;
virtual std::string message() const;
error_code error;
};
// The session_stats_alert is posted when the user requests session statistics by
// calling post_session_stats() on the session object. Its category is
// ``status_notification``, but it is not subject to filtering, since it's only
// manually posted anyway.
struct TORRENT_EXPORT session_stats_alert : alert
{
session_stats_alert() {}
TORRENT_DEFINE_ALERT(session_stats_alert, 70);
const static int static_category = alert::stats_notification;
virtual std::string message() const;
virtual bool discardable() const { return false; }
// the number of microseconds since the session was
// started. It represent the time when the snapshot of values was taken. When
// the network thread is under heavy load, the latency between calling
// post_session_stats() and receiving this alert may be significant, and
// the timestamp may help provide higher accuracy in measurements.
boost::uint64_t timestamp;
// An array are a mix of *counters* and *gauges*, which
// meanings can be queries via the session_stats_metrics() function on the session.
// The mapping from a specific metric to an index into this array is constant for a
// specific version of libtorrent, but may differ for other versions. The intended
// usage is to request the mapping, i.e. call session_stats_metrics(), once
// on startup, and then use that mapping to interpret these values throughout
// the process' runtime.
//
// For more information, see the session-statistics_ section.
std::vector<boost::uint64_t> values;
};
// When a torrent changes its info-hash, this alert is posted. This only happens in very
// specific cases. For instance, when a torrent is downloaded from a URL, the true info
// hash is not known immediately. First the .torrent file must be downloaded and parsed.
@ -1884,7 +1968,7 @@ namespace libtorrent
, new_ih(new_hash)
{}
TORRENT_DEFINE_ALERT(torrent_update_alert);
TORRENT_DEFINE_ALERT(torrent_update_alert, 71);
const static int static_category = alert::status_notification;
virtual std::string message() const;
@ -1908,7 +1992,7 @@ namespace libtorrent
, item(item)
{}
TORRENT_DEFINE_ALERT(rss_item_alert);
TORRENT_DEFINE_ALERT(rss_item_alert, 72);
const static int static_category = alert::rss_notification;
virtual std::string message() const;
@ -1925,7 +2009,7 @@ namespace libtorrent
dht_error_alert(int op, error_code const& ec)
: error(ec), operation(op_t(op)) {}
TORRENT_DEFINE_ALERT(dht_error_alert);
TORRENT_DEFINE_ALERT(dht_error_alert, 73);
const static int static_category = alert::error_notification
| alert::dht_notification;
@ -1951,7 +2035,7 @@ namespace libtorrent
dht_immutable_item_alert(sha1_hash const& t, entry const& i)
: target(t), item(i) {}
TORRENT_DEFINE_ALERT(dht_immutable_item_alert);
TORRENT_DEFINE_ALERT(dht_immutable_item_alert, 74);
const static int static_category = alert::error_notification
| alert::dht_notification;
@ -1977,7 +2061,7 @@ namespace libtorrent
, entry const& i)
: key(k), signature(sig), seq(sequence), salt(s), item(i) {}
TORRENT_DEFINE_ALERT(dht_mutable_item_alert);
TORRENT_DEFINE_ALERT(dht_mutable_item_alert, 75);
const static int static_category = alert::error_notification
| alert::dht_notification;
@ -2025,7 +2109,7 @@ namespace libtorrent
, seq(sequence_number)
{}
TORRENT_DEFINE_ALERT(dht_put_alert);
TORRENT_DEFINE_ALERT(dht_put_alert, 76);
const static int static_category = alert::dht_notification;
virtual std::string message() const;
@ -2047,7 +2131,7 @@ namespace libtorrent
{
i2p_alert(error_code const& ec) : error(ec) {}
TORRENT_DEFINE_ALERT(i2p_alert);
TORRENT_DEFINE_ALERT(i2p_alert, 77);
const static int static_category = alert::error_notification;
virtual std::string message() const;
@ -2058,7 +2142,9 @@ namespace libtorrent
#undef TORRENT_DEFINE_ALERT
enum { num_alert_types = 74 };
}
#endif

View File

@ -48,6 +48,9 @@ namespace libtorrent
static char* malloc(const size_type bytes);
static void free(char* block);
#ifdef TORRENT_DEBUG_BUFFERS
static bool in_use(char const* block);
#endif
};
struct TORRENT_EXTRA_EXPORT aligned_holder

View File

@ -46,25 +46,27 @@ TORRENT_EXPORT void print_backtrace(char* out, int len, int max_depth = 0);
extern char const* libtorrent_assert_log;
#endif
#if (defined __linux__ || defined __MACH__) && defined __GNUC__ && !TORRENT_USE_SYSTEM_ASSERT
#if !TORRENT_USE_SYSTEM_ASSERT
#if TORRENT_USE_IOSTREAM
#include <sstream>
#endif
TORRENT_EXPORT void assert_print(char const* fmt, ...);
TORRENT_EXPORT void assert_fail(const char* expr, int line, char const* file
, char const* function, char const* val, int kind = 0);
#define TORRENT_ASSERT_PRECOND(x) \
do { if (x) {} else assert_fail(#x, __LINE__, __FILE__, __PRETTY_FUNCTION__, "", 1); } while (false)
do { if (x) {} else assert_fail(#x, __LINE__, __FILE__, TORRENT_FUNCTION, 0, 1); } while (false)
#define TORRENT_ASSERT(x) \
do { if (x) {} else assert_fail(#x, __LINE__, __FILE__, __PRETTY_FUNCTION__, "", 0); } while (false)
do { if (x) {} else assert_fail(#x, __LINE__, __FILE__, TORRENT_FUNCTION, 0, 0); } while (false)
#if TORRENT_USE_IOSTREAM
#define TORRENT_ASSERT_VAL(x, y) \
do { if (x) {} else { std::stringstream __s__; __s__ << #y ": " << y; \
assert_fail(#x, __LINE__, __FILE__, __PRETTY_FUNCTION__, __s__.str().c_str(), 0); } } while (false)
assert_fail(#x, __LINE__, __FILE__, TORRENT_FUNCTION, __s__.str().c_str(), 0); } } while (false)
#else
#define TORRENT_ASSERT_VAL(x, y) TORRENT_ASSERT(x)
#endif

View File

@ -0,0 +1,131 @@
/*
Copyright (c) 2012-2013, Arvid Norberg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TORRENT_ATOMIC_HPP_INCLUDED
#define TORRENT_ATOMIC_HPP_INCLUDED
#include "libtorrent/config.hpp"
#if TORRENT_USE_OSATOMIC
#include <libkern/OSAtomic.h>
#endif
#if TORRENT_USE_INTERLOCKED_ATOMIC
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#endif
#if TORRENT_USE_BEOS_ATOMIC
#include <be/support/SupportDefs.h>
#endif
#if TORRENT_USE_SOLARIS_ATOMIC
#include <atomic.h>
#endif
namespace libtorrent
{
struct atomic_count
{
atomic_count() : m_value(0) {}
atomic_count(int v) : m_value(v) {}
#if TORRENT_USE_INTERLOCKED_ATOMIC
typedef LONG value_type;
#elif TORRENT_USE_SOLARIS_ATOMIC
typedef unsigned int value_type;
#else
typedef int value_type;
#endif
#if TORRENT_USE_OSATOMIC
operator value_type() const { return OSAtomicAdd32(0, const_cast<value_type*>(&m_value)); }
value_type operator-=(int v) { return OSAtomicAdd32Barrier(-v, &m_value); }
value_type operator+=(int v) { return OSAtomicAdd32Barrier(v, &m_value); }
// pre inc/dec operators
value_type operator++() { return OSAtomicAdd32Barrier(1, &m_value); }
value_type operator--() { return OSAtomicAdd32Barrier(-1, &m_value); }
// post inc/dec operators
value_type operator++(int) { return OSAtomicAdd32Barrier(1, &m_value)-1; }
value_type operator--(int) { return OSAtomicAdd32Barrier(-1, &m_value)+1; }
#elif TORRENT_USE_GCC_ATOMIC
operator value_type() const { return __sync_fetch_and_add(const_cast<value_type*>(&m_value), 0); }
value_type operator-=(value_type v) { return __sync_sub_and_fetch(&m_value, v); }
value_type operator+=(value_type v) { return __sync_add_and_fetch(&m_value, v); }
// pre inc/dec operators
value_type operator++() { return __sync_add_and_fetch(&m_value, 1); }
value_type operator--() { return __sync_add_and_fetch(&m_value, -1); }
// post inc/dec operators
value_type operator++(int) { return __sync_fetch_and_add(&m_value, 1); }
value_type operator--(int) { return __sync_fetch_and_add(&m_value, -1); }
#elif TORRENT_USE_INTERLOCKED_ATOMIC
operator value_type() const { return InterlockedExchangeAdd(const_cast<value_type*>(&m_value), 0); }
value_type operator-=(value_type v) { return InterlockedExchangeAdd(&m_value, -v); }
value_type operator+=(value_type v) { return InterlockedExchangeAdd(&m_value, v); }
// pre inc/dec operators
value_type operator++() { return InterlockedIncrement(&m_value); }
value_type operator--() { return InterlockedDecrement(&m_value); }
// post inc/dec operators
value_type operator++(int) { return InterlockedIncrement(&m_value) - 1; }
value_type operator--(int) { return InterlockedDecrement(&m_value) + 1; }
#elif TORRENT_USE_SOLARIS_ATOMIC
operator value_type() const { return atomic_add_32_nv(const_cast<value_type*>(&m_value), 0); }
value_type operator-=(value_type v) { return atomic_add_32(&m_value, -v); }
value_type operator+=(value_type v) { return atomic_add_32(&m_value, v); }
// pre inc/dec operators
value_type operator++() { return atomic_add_32_nv(&m_value, 1); }
value_type operator--() { return atomic_add_32_nv(&m_value, -1); }
// post inc/dec operators
value_type operator++(int) { return atomic_add_32_nv(&m_value, 1) - 1; }
value_type operator--(int) { return atomic_add_32_nv(&m_value, -1) + 1; }
#elif TORRENT_USE_BEOS_ATOMIC
operator value_type() const { return atomic_add(const_cast<value_type*>(&m_value), 0); }
value_type operator-=(value_type v) { return atomic_add(&m_value, -v) - v; }
value_type operator+=(value_type v) { return atomic_add(&m_value, v) + v; }
// pre inc/dec operators
value_type operator++() { return atomic_add(&m_value, 1) + 1; }
value_type operator--() { return atomic_add(&m_value, -1) - 1; }
// post inc/dec operators
value_type operator++(int) { return atomic_add(&m_value, 1); }
value_type operator--(int) { return atomic_add(&m_value, -1); }
#else
#error "don't know which atomic operations to use"
#endif
private:
volatile value_type m_value;
};
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,346 @@
/*
Copyright (c) 2012, Arvid Norberg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TORRENT_SESSION_INTERFACE_HPP_INCLUDED
#define TORRENT_SESSION_INTERFACE_HPP_INCLUDED
#include "libtorrent/config.hpp"
#include "libtorrent/peer_id.hpp"
#include <boost/weak_ptr.hpp>
#include <boost/function.hpp>
#include "libtorrent/address.hpp"
#include "libtorrent/io_service.hpp"
#include "libtorrent/disk_buffer_holder.hpp"
#ifndef TORRENT_DISABLE_DHT
#include "libtorrent/socket.hpp"
#endif
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
#include <boost/shared_ptr.hpp>
#endif
#ifdef TORRENT_USE_OPENSSL
#include <boost/asio/ssl/context.hpp>
#endif
#include "libtorrent/socket.hpp" // for tcp::endpoint
namespace libtorrent
{
class peer_connection;
class torrent;
struct proxy_settings;
struct socket_job;
#ifndef TORRENT_NO_DEPRECATE
struct pe_settings;
#endif
struct peer_class_set;
struct bandwidth_channel;
struct bandwidth_manager;
struct peer_class_pool;
struct disk_observer;
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
struct logger;
#endif
struct torrent_peer;
class alert_manager;
struct disk_interface;
struct tracker_request;
struct request_callback;
class connection_queue;
struct utp_socket_manager;
struct socket_type;
struct block_info;
struct external_ip;
struct torrent_handle;
struct ip_filter;
class port_filter;
struct settings_pack;
struct torrent_peer_allocator_interface;
struct counters;
struct resolver_interface;
#ifndef TORRENT_DISABLE_DHT
namespace dht
{
struct dht_tracker;
}
#endif
}
namespace libtorrent { namespace aux
{
// TOOD: make this interface a lot smaller
struct session_interface
: buffer_allocator_interface
{
// TODO: 2 the IP voting mechanism should be factored out
// to its own class, not part of the session
enum
{
source_dht = 1,
source_peer = 2,
source_tracker = 4,
source_router = 8
};
virtual void set_external_address(address const& ip
, int source_type, address const& source) = 0;
virtual external_ip const& external_address() const = 0;
virtual disk_interface& disk_thread() = 0;
virtual alert_manager& alerts() = 0;
virtual torrent_peer_allocator_interface* get_peer_allocator() = 0;
virtual io_service& get_io_service() = 0;
virtual resolver_interface& get_resolver() = 0;
virtual bool has_connection(peer_connection* p) const = 0;
virtual void insert_peer(boost::shared_ptr<peer_connection> const& c) = 0;
virtual void add_redundant_bytes(size_type b, int reason) = 0;
virtual void add_failed_bytes(size_type b) = 0;
virtual void queue_async_resume_data(boost::shared_ptr<torrent> const& t) = 0;
virtual void done_async_resume() = 0;
virtual void evict_torrent(torrent* t) = 0;
virtual void remove_torrent(torrent_handle const& h, int options = 0) = 0;
virtual void remove_torrent_impl(boost::shared_ptr<torrent> tptr, int options) = 0;
// ip and port filter
virtual ip_filter const& get_ip_filter() const = 0;
virtual port_filter const& get_port_filter() const = 0;
virtual boost::int64_t session_time() const = 0;
virtual bool is_paused() const = 0;
virtual bool is_aborted() const = 0;
virtual int num_uploads() const = 0;
virtual bool preemptive_unchoke() const = 0;
virtual void unchoke_peer(peer_connection& c) = 0;
virtual void choke_peer(peer_connection& c) = 0;
virtual void trigger_optimistic_unchoke() = 0;
virtual void trigger_unchoke() = 0;
virtual boost::weak_ptr<torrent> find_torrent(sha1_hash const& info_hash) const = 0;
virtual boost::weak_ptr<torrent> find_disconnect_candidate_torrent() const = 0;
virtual boost::shared_ptr<torrent> delay_load_torrent(sha1_hash const& info_hash
, peer_connection* pc) = 0;
virtual void insert_torrent(sha1_hash const& ih, boost::shared_ptr<torrent> const& t
, std::string uuid) = 0;
virtual void insert_uuid_torrent(std::string uuid, boost::shared_ptr<torrent> const& t) = 0;
virtual void set_queue_position(torrent* t, int p) = 0;
virtual int num_torrents() const = 0;
virtual peer_id const& get_peer_id() const = 0;
// cork a peer and schedule a delayed uncork
// does nothing if the peer is already corked
virtual void cork_burst(peer_connection* p) = 0;
virtual void close_connection(peer_connection* p, error_code const& ec, bool cancel_with_cq) = 0;
virtual int num_connections() const = 0;
virtual char* allocate_buffer() = 0;
virtual void free_buffer(char* buf) = 0;
virtual int send_buffer_size() const = 0;
virtual void deferred_submit_jobs() = 0;
virtual boost::uint16_t listen_port() const = 0;
virtual boost::uint16_t ssl_listen_port() const = 0;
// used to (potentially) issue socket write calls onto multiple threads
virtual void post_socket_job(socket_job& j) = 0;
// load the specified torrent. also evict one torrent, except
// for the one specified, if we are at the limit of loaded torrents
virtual bool load_torrent(torrent* t) = 0;
// bump the specified torrent to make it the most recently used one
// in the torrent LRU (i.e. the least likely to get unloaded)
virtual void bump_torrent(torrent* t, bool back = true) = 0;
// ask for which interface and port to bind outgoing peer connections on
virtual tcp::endpoint bind_outgoing_socket(socket_type& s, address const&
remote_address, error_code& ec) const = 0;
virtual bool verify_bound_address(address const& addr, bool utp
, error_code& ec) = 0;
// TODO: it would be nice to not have this be part of session_interface
virtual proxy_settings proxy() const = 0;
#if TORRENT_USE_I2P
virtual proxy_settings i2p_proxy() const = 0;
virtual char const* i2p_session() const = 0;
#endif
virtual void prioritize_connections(boost::weak_ptr<torrent> t) = 0;
virtual tcp::endpoint get_ipv6_interface() const = 0;
virtual tcp::endpoint get_ipv4_interface() const = 0;
virtual void trigger_auto_manage() = 0;
virtual void apply_settings_pack(settings_pack* pack) = 0;
virtual session_settings const& settings() const = 0;
virtual void queue_tracker_request(tracker_request& req
, std::string login, boost::weak_ptr<request_callback> c
, boost::uint32_t key) = 0;
// peer-classes
virtual void set_peer_classes(peer_class_set* s, address const& a, int st) = 0;
virtual peer_class_pool const& peer_classes() const = 0;
virtual peer_class_pool& peer_classes() = 0;
virtual bool ignore_unchoke_slots_set(peer_class_set const& set) const = 0;
virtual int copy_pertinent_channels(peer_class_set const& set
, int channel, bandwidth_channel** dst, int max) = 0;
virtual int use_quota_overhead(peer_class_set& set, int amount_down, int amount_up) = 0;
virtual bandwidth_manager* get_bandwidth_manager(int channel) = 0;
virtual void sent_bytes(int bytes_payload, int bytes_protocol) = 0;
virtual void received_bytes(int bytes_payload, int bytes_protocol) = 0;
virtual void trancieve_ip_packet(int bytes, bool ipv6) = 0;
virtual void sent_syn(bool ipv6) = 0;
virtual void received_synack(bool ipv6) = 0;
// half-open
virtual bool half_open_done(int ticket) = 0;
virtual int peak_up_rate() const = 0;
enum torrent_list_index
{
// this is the set of (subscribed) torrents that have changed
// their states since the last time the user requested updates.
torrent_state_updates,
// all torrents that want to be ticked every second
torrent_want_tick,
// all torrents that want more peers and are still downloading
// these typically have higher priority when connecting peers
torrent_want_peers_download,
// all torrents that want more peers and are finished downloading
torrent_want_peers_finished,
// torrents that want auto-scrape (only paused auto-managed ones)
torrent_want_scrape,
// all torrents that have resume data to save
// torrent_want_save_resume,
num_torrent_lists,
};
virtual std::vector<torrent*>& torrent_list(int i) = 0;
virtual bool has_lsd() const = 0;
virtual void announce_lsd(sha1_hash const& ih, int port, bool broadcast = false) = 0;
virtual connection_queue& half_open() = 0;
virtual libtorrent::utp_socket_manager* utp_socket_manager() = 0;
virtual void inc_boost_connections() = 0;
virtual void setup_socket_buffers(socket_type& s) = 0;
virtual std::vector<block_info>& block_info_storage() = 0;
#ifdef TORRENT_USE_OPENSSL
virtual boost::asio::ssl::context* ssl_ctx() = 0 ;
#endif
#ifndef TORRENT_DISABLE_ENCRYPTION
virtual torrent const* find_encrypted_torrent(
sha1_hash const& info_hash, sha1_hash const& xor_mask) = 0;
virtual void add_obfuscated_hash(sha1_hash const& obfuscated
, boost::weak_ptr<torrent> const& t) = 0;
#endif
#ifndef TORRENT_DISABLE_DHT
virtual bool announce_dht() const = 0;
virtual void add_dht_node(udp::endpoint n) = 0;
virtual bool has_dht() const = 0;
virtual int external_udp_port() const = 0;
virtual dht::dht_tracker* dht() = 0;
virtual void prioritize_dht(boost::weak_ptr<torrent> t) = 0;
#endif
#ifndef TORRENT_DISABLE_GEO_IP
virtual bool has_asnum_db() const = 0;
virtual bool has_country_db() const = 0;
virtual char const* country_for_ip(address const& a) = 0;
virtual std::string as_name_for_ip(address const& a) = 0;
virtual int as_for_ip(address const& a) = 0;
virtual std::pair<const int, int>* lookup_as(int as) = 0;
#endif
#if TORRENT_USE_ASSERTS
virtual bool is_single_thread() const = 0;
virtual bool has_peer(peer_connection const* p) const = 0;
virtual bool any_torrent_has_peer(peer_connection const* p) const = 0;
virtual bool is_posting_torrent_updates() const = 0;
#endif
#ifdef TORRENT_REQUEST_LOGGING
virtual FILE* get_request_log() = 0;
#endif
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
virtual boost::shared_ptr<logger> create_log(std::string const& name
, int instance, bool append = true) = 0;
virtual void session_log(char const* fmt, ...) const = 0;
virtual void session_vlog(char const* fmt, va_list& va) const = 0;
virtual std::string get_log_path() const = 0;
#if defined TORRENT_VERBOSE_LOGGING
virtual void log_all_torrents(peer_connection* p) = 0;
#endif
#endif
#ifdef TORRENT_BUFFER_STATS
virtual void log_buffer_usage() = 0;
virtual std::ofstream& buffer_usage_logger() = 0;
#endif
virtual boost::uint64_t inc_stats_counter(int c, int value = 1) = 0;
virtual counters& stats_counters() = 0;
virtual void received_buffer(int size) = 0;
virtual void sent_buffer(int size) = 0;
};
}}
#endif

View File

@ -0,0 +1,82 @@
/*
Copyright (c) 2012, Arvid Norberg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TORRENT_AUX_SESSION_SETTINGS_HPP_INCLUDED
#define TORRENT_AUX_SESSION_SETTINGS_HPP_INCLUDED
#include "libtorrent/version.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/settings_pack.hpp"
#include "libtorrent/assert.hpp"
#include <string>
namespace libtorrent { namespace aux
{
#define SET(type) \
TORRENT_ASSERT((name & settings_pack::type_mask) == settings_pack:: type ## _type_base); \
if ((name & settings_pack::type_mask) != settings_pack:: type ## _type_base) return; \
m_ ## type ## s[name - settings_pack:: type ## _type_base] = value
#define GET(type, default_val) \
TORRENT_ASSERT((name & settings_pack::type_mask) == settings_pack:: type ## _type_base); \
if ((name & settings_pack::type_mask) != settings_pack:: type ## _type_base) return default_val; \
return m_ ## type ## s[name - settings_pack:: type ## _type_base]
struct session_settings
{
friend void libtorrent::save_settings_to_dict(
aux::session_settings const& s, entry::dictionary_type& sett);
void set_str(int name, std::string const& value) { SET(string); }
std::string const& get_str(int name) const { GET(string, m_strings[0]); }
void set_int(int name, int value) { SET(int); }
int get_int(int name) const { GET(int, 0); }
void set_bool(int name, bool value) { SET(bool); }
bool get_bool(int name) const { GET(bool, false); }
session_settings() { initialize_default_settings(*this); }
private:
std::string m_strings[settings_pack::num_string_settings];
int m_ints[settings_pack::num_int_settings];
bool m_bools[settings_pack::num_bool_settings];
};
#undef GET
#undef SET
} }
#endif

View File

@ -33,7 +33,7 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef TORRENT_BANDWIDTH_MANAGER_HPP_INCLUDED
#define TORRENT_BANDWIDTH_MANAGER_HPP_INCLUDED
#include <boost/intrusive_ptr.hpp>
#include <boost/shared_ptr.hpp>
#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT
#include <fstream>
@ -47,10 +47,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/bandwidth_queue_entry.hpp"
#include "libtorrent/thread.hpp"
#include "libtorrent/bandwidth_socket.hpp"
#include "libtorrent/ptime.hpp"
using boost::intrusive_ptr;
#include "libtorrent/time.hpp"
namespace libtorrent {
@ -76,13 +73,8 @@ struct TORRENT_EXTRA_EXPORT bandwidth_manager
// this is used by web seeds
// returns the number of bytes to assign to the peer, or 0
// if the peer's 'assign_bandwidth' callback will be called later
int request_bandwidth(intrusive_ptr<bandwidth_socket> const& peer
, int blk, int priority
, bandwidth_channel* chan1 = 0
, bandwidth_channel* chan2 = 0
, bandwidth_channel* chan3 = 0
, bandwidth_channel* chan4 = 0
, bandwidth_channel* chan5 = 0);
int request_bandwidth(boost::shared_ptr<bandwidth_socket> const& peer
, int blk, int priority, bandwidth_channel** chan, int num_channels);
#if TORRENT_USE_INVARIANT_CHECKS
void check_invariant() const;

View File

@ -33,7 +33,7 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef TORRENT_BANDWIDTH_QUEUE_ENTRY_HPP_INCLUDED
#define TORRENT_BANDWIDTH_QUEUE_ENTRY_HPP_INCLUDED
#include <boost/intrusive_ptr.hpp>
#include <boost/shared_ptr.hpp>
#include "libtorrent/bandwidth_limit.hpp"
#include "libtorrent/bandwidth_socket.hpp"
@ -41,10 +41,10 @@ namespace libtorrent {
struct TORRENT_EXTRA_EXPORT bw_request
{
bw_request(boost::intrusive_ptr<bandwidth_socket> const& pe
bw_request(boost::shared_ptr<bandwidth_socket> const& pe
, int blk, int prio);
boost::intrusive_ptr<bandwidth_socket> peer;
boost::shared_ptr<bandwidth_socket> peer;
// 1 is normal prio
int priority;
// the number of bytes assigned to this request so far
@ -62,8 +62,8 @@ struct TORRENT_EXTRA_EXPORT bw_request
// from the most limiting one
int assign_bandwidth();
enum { max_bandwidth_channels = 5 };
// we don't actually support more than 5 channels per peer
enum { max_bandwidth_channels = 10 };
// we don't actually support more than 10 channels per peer
bandwidth_channel* channel[max_bandwidth_channels];
};

View File

@ -34,12 +34,9 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef TORRENT_BANDWIDTH_SOCKET_HPP_INCLUDED
#define TORRENT_BANDWIDTH_SOCKET_HPP_INCLUDED
#include "libtorrent/intrusive_ptr_base.hpp"
namespace libtorrent
{
struct bandwidth_socket
: public intrusive_ptr_base<bandwidth_socket>
{
virtual void assign_bandwidth(int channel, int amount) = 0;
virtual bool is_disconnecting() const = 0;

View File

@ -35,11 +35,18 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/assert.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/byteswap.hpp"
#include "libtorrent/cpuid.hpp"
#include <cstring> // for memset and memcpy
#include <cstdlib> // for malloc, free and realloc
#include <boost/cstdint.hpp> // uint32_t
#include <algorithm> // for min()
#ifdef _MSC_VER
#include <intrin.h>
#endif
namespace libtorrent
{
// The bitfiled type stores any number of bits as a bitfield
@ -54,95 +61,102 @@ namespace libtorrent
// The constructor taking a pointer ``b`` and ``bits`` copies a bitfield
// from the specified buffer, and ``bits`` number of bits (rounded up to
// the nearest byte boundry).
bitfield(): m_bytes(0), m_size(0), m_own(false) {}
bitfield(int bits): m_bytes(0), m_size(0), m_own(false)
bitfield(): m_buf(NULL) {}
bitfield(int bits): m_buf(NULL)
{ resize(bits); }
bitfield(int bits, bool val): m_bytes(0), m_size(0), m_own(false)
bitfield(int bits, bool val): m_buf(NULL)
{ resize(bits, val); }
bitfield(char const* b, int bits): m_bytes(0), m_size(0), m_own(false)
bitfield(char const* b, int bits): m_buf(NULL)
{ assign(b, bits); }
bitfield(bitfield const& rhs): m_bytes(0), m_size(0), m_own(false)
bitfield(bitfield const& rhs): m_buf(NULL)
{ assign(rhs.bytes(), rhs.size()); }
#if __cplusplus > 199711L
bitfield(bitfield&& rhs): m_bytes(rhs.m_bytes), m_size(rhs.m_size), m_own(rhs.m_own)
{ rhs.m_bytes = NULL; }
bitfield(bitfield&& rhs): m_buf(rhs.m_buf)
{ rhs.m_buf = NULL; }
#endif
// assigns a bitfield pointed to ``b`` of ``bits`` number of bits, without
// taking ownership of the buffer. This is a way to avoid copying data and
// yet provide a raw buffer to functions that may operate on the bitfield
// type. It is the user's responsibility to make sure the passed-in buffer's
// life time exceeds all uses of the bitfield.
void borrow_bytes(char* b, int bits)
{
dealloc();
m_bytes = (unsigned char*)b;
m_size = bits;
m_own = false;
}
// hidden
~bitfield() { dealloc(); }
// copy bitfield from buffer ``b`` of ``bits`` number of bits, rounded up to
// the nearest byte boundary.
void assign(char const* b, int bits)
{ resize(bits); std::memcpy(m_bytes, b, (bits + 7) / 8); clear_trailing_bits(); }
{
resize(bits);
if (bits > 0)
{
std::memcpy(m_buf, b, ((bits + 7) / 8));
clear_trailing_bits();
}
}
// query bit at ``index``. Returns true if bit is 1, otherwise false.
bool operator[](int index) const
{ return get_bit(index); }
bool get_bit(int index) const
{
TORRENT_ASSERT(index >= 0);
TORRENT_ASSERT(index < m_size);
return (m_bytes[index / 8] & (0x80 >> (index & 7))) != 0;
TORRENT_ASSERT(index < size());
return (m_buf[index / 32] & htonl((0x80000000 >> (index & 31)))) != 0;
}
// set bit at ``index`` to 0 (clear_bit) or 1 (set_bit).
void clear_bit(int index)
{
TORRENT_ASSERT(index >= 0);
TORRENT_ASSERT(index < m_size);
m_bytes[index / 8] &= ~(0x80 >> (index & 7));
TORRENT_ASSERT(index < size());
m_buf[index / 32] &= htonl(~(0x80000000 >> (index & 31)));
}
void set_bit(int index)
{
TORRENT_ASSERT(index >= 0);
TORRENT_ASSERT(index < m_size);
m_bytes[index / 8] |= (0x80 >> (index & 7));
TORRENT_ASSERT(index < size());
m_buf[index / 32] |= htonl((0x80000000 >> (index & 31)));
}
// returns true if all bits in the bitfield are set
bool all_set() const
{
const int num_words = m_size / 32;
const int num_bytes = m_size / 8;
boost::uint32_t* bits = (boost::uint32_t*)m_bytes;
for (int i = 0; i < num_words; ++i)
const int words = size() / 32;
for (int i = 0; i < words; ++i)
{
if (bits[i] != 0xffffffff) return false;
if (m_buf[i] != 0xffffffff) return false;
}
for (int i = num_words * 4; i < num_bytes; ++i)
{
if (m_bytes[i] != 0xff) return false;
}
int rest = m_size - num_bytes * 8;
boost::uint8_t mask = (0xff << (8-rest)) & 0xff;
if (rest > 0 && (m_bytes[num_bytes] & mask) != mask)
int rest = size() & 31;
boost::uint32_t mask = htonl(0xffffffff << (32-rest));
if (rest > 0 && (m_buf[words] & mask) != mask)
return false;
return true;
}
bool none_set() const
{
const int words = num_words();
for (int i = 0; i < words; ++i)
{
if (m_buf[i] != 0) return false;
}
return true;
}
// returns the size of the bitfield in bits.
std::size_t size() const { return m_size; }
int size() const
{
return m_buf == NULL ? 0 : m_buf[-1];
}
int num_words() const
{
return (size() + 31) / 32;
}
// returns true if the bitfield has zero size.
bool empty() const { return m_size == 0; }
bool empty() const { return m_buf == NULL ? true : m_buf[-1] == 0; }
// returns a pointer to the internal buffer of the bitfield.
char const* bytes() const { return (char*)m_bytes; }
// TODO: rename to data() ?
char const* bytes() const { return (char const*)m_buf; }
// copy operator
bitfield& operator=(bitfield const& rhs)
@ -154,27 +168,43 @@ namespace libtorrent
// count the number of bits in the bitfield that are set to 1.
int count() const
{
// 0000, 0001, 0010, 0011, 0100, 0101, 0110, 0111,
// 1000, 1001, 1010, 1011, 1100, 1101, 1110, 1111
const static char num_bits[] =
{
0, 1, 1, 2, 1, 2, 2, 3,
1, 2, 2, 3, 2, 3, 3, 4
};
int ret = 0;
const int num_bytes = m_size / 8;
for (int i = 0; i < num_bytes; ++i)
const int words = num_words();
#if TORRENT_HAS_SSE
unsigned int cpui[4];
cpuid(cpui, 1);
if (cpui[2] & (1 << 23))
{
ret += num_bits[m_bytes[i] & 0xf] + num_bits[m_bytes[i] >> 4];
for (int i = 0; i < words; ++i)
{
#ifdef __GNUC__
ret += __builtin_popcount(m_buf[i]);
#else
ret += _mm_popcnt_u32(m_buf[i]);
#endif
}
int rest = m_size - num_bytes * 8;
for (int i = 0; i < rest; ++i)
{
ret += (m_bytes[num_bytes] >> (7-i)) & 1;
return ret;
}
TORRENT_ASSERT(ret <= m_size);
#endif // TORRENT_HAS_SSE
for (int i = 0; i < words; ++i)
{
boost::uint32_t v = m_buf[i];
// from:
// http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
static const int S[] = {1, 2, 4, 8, 16}; // Magic Binary Numbers
static const int B[] = {0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF, 0x0000FFFF};
boost::uint32_t c = v - ((v >> 1) & B[0]);
c = ((c >> S[1]) & B[1]) + (c & B[1]);
c = ((c >> S[2]) + c) & B[2];
c = ((c >> S[3]) + c) & B[3];
c = ((c >> S[4]) + c) & B[4];
ret += c;
}
TORRENT_ASSERT(ret <= size());
TORRENT_ASSERT(ret >= 0);
return ret;
}
@ -189,7 +219,7 @@ namespace libtorrent
typedef bool& reference;
typedef std::forward_iterator_tag iterator_category;
bool operator*() { return (*byte & bit) != 0; }
bool operator*() { return (*buf & htonl(bit)) != 0; }
const_iterator& operator++() { inc(); return *this; }
const_iterator operator++(int)
{ const_iterator ret(*this); inc(); return ret; }
@ -197,21 +227,21 @@ namespace libtorrent
const_iterator operator--(int)
{ const_iterator ret(*this); dec(); return ret; }
const_iterator(): byte(0), bit(0x80) {}
const_iterator(): buf(0), bit(0x80000000) {}
bool operator==(const_iterator const& rhs) const
{ return byte == rhs.byte && bit == rhs.bit; }
{ return buf == rhs.buf && bit == rhs.bit; }
bool operator!=(const_iterator const& rhs) const
{ return byte != rhs.byte || bit != rhs.bit; }
{ return buf != rhs.buf || bit != rhs.bit; }
private:
void inc()
{
TORRENT_ASSERT(byte);
TORRENT_ASSERT(buf);
if (bit == 0x01)
{
bit = 0x80;
++byte;
bit = 0x80000000;
++buf;
}
else
{
@ -220,103 +250,115 @@ namespace libtorrent
}
void dec()
{
TORRENT_ASSERT(byte);
if (bit == 0x80)
TORRENT_ASSERT(buf);
if (bit == 0x80000000)
{
bit = 0x01;
--byte;
--buf;
}
else
{
bit <<= 1;
}
}
const_iterator(unsigned char const* ptr, int offset)
: byte(ptr), bit(0x80 >> offset) {}
unsigned char const* byte;
int bit;
const_iterator(boost::uint32_t const* ptr, int offset)
: buf(ptr), bit(0x80000000 >> offset) {}
boost::uint32_t const* buf;
boost::uint32_t bit;
};
const_iterator begin() const { return const_iterator(m_bytes, 0); }
const_iterator end() const { return const_iterator(m_bytes + m_size / 8, m_size & 7); }
const_iterator begin() const { return const_iterator(m_buf, 0); }
const_iterator end() const { return const_iterator(
m_buf + num_words() - (((size() & 31) == 0) ? 0 : 1), size() & 31); }
// set the size of the bitfield to ``bits`` length. If the bitfield is extended,
// the new bits are initialized to ``val``.
void resize(int bits, bool val)
{
int s = m_size;
int b = m_size & 7;
if (bits == size()) return;
int s = size();
int b = size() & 31;
resize(bits);
if (s >= m_size) return;
int old_size_bytes = (s + 7) / 8;
int new_size_bytes = (m_size + 7) / 8;
if (s >= size()) return;
int old_size_words = (s + 31) / 32;
int new_size_words = num_words();
if (val)
{
if (old_size_bytes && b) m_bytes[old_size_bytes - 1] |= (0xff >> b);
if (old_size_bytes < new_size_bytes)
std::memset(m_bytes + old_size_bytes, 0xff, new_size_bytes - old_size_bytes);
if (old_size_words && b) m_buf[old_size_words - 1] |= htonl((0xffffffff >> b));
if (old_size_words < new_size_words)
std::memset(m_buf + old_size_words, 0xff, (new_size_words - old_size_words) * 4);
clear_trailing_bits();
}
else
{
if (old_size_bytes < new_size_bytes)
std::memset(m_bytes + old_size_bytes, 0x00, new_size_bytes - old_size_bytes);
if (old_size_words < new_size_words)
std::memset(m_buf + old_size_words, 0x00, (new_size_words - old_size_words) * 4);
}
TORRENT_ASSERT(size() == bits);
}
void resize(int bits)
{
if (bits == size()) return;
TORRENT_ASSERT(bits >= 0);
const int b = (bits + 7) / 8;
if (m_bytes)
// +1 because the first word is the size (in bits)
const int b = (bits + 31) / 32;
if (m_buf)
{
if (m_own)
{
m_bytes = (unsigned char*)std::realloc(m_bytes, b);
m_own = true;
}
else if (bits > m_size)
{
unsigned char* tmp = (unsigned char*)std::malloc(b);
std::memcpy(tmp, m_bytes, (std::min)(int(m_size + 7)/ 8, b));
m_bytes = tmp;
m_own = true;
}
m_buf = (boost::uint32_t*)std::realloc(m_buf-1, (b+1) * 4);
m_buf = m_buf + 1;
m_buf[-1] = bits;
}
else if (bits > 0)
{
m_bytes = (unsigned char*)std::malloc(b);
m_own = true;
m_buf = (boost::uint32_t*)std::malloc((b+1) * 4);
m_buf = m_buf + 1;
m_buf[-1] = bits;
}
else if (m_buf != NULL)
{
std::free(m_buf-1);
m_buf = NULL;
}
m_size = bits;
clear_trailing_bits();
TORRENT_ASSERT(size() == bits);
}
// set all bits in the bitfield to 1 (set_all) or 0 (clear_all).
void set_all()
{
std::memset(m_bytes, 0xff, (m_size + 7) / 8);
std::memset(m_buf, 0xff, num_words() * 4);
clear_trailing_bits();
}
void clear_all()
{
std::memset(m_bytes, 0x00, (m_size + 7) / 8);
std::memset(m_buf, 0x00, num_words() * 4);
}
// make the bitfield empty, of zero size.
void clear() { dealloc(); m_size = 0; }
void clear() { dealloc(); }
private:
void clear_trailing_bits()
{
// clear the tail bits in the last byte
if (m_size & 7) m_bytes[(m_size + 7) / 8 - 1] &= 0xff << (8 - (m_size & 7));
if (size() & 31) m_buf[num_words() - 1] &= htonl(0xffffffff << (32 - (size() & 31)));
}
void dealloc() { if (m_own) std::free(m_bytes); m_bytes = 0; }
unsigned char* m_bytes;
int m_size:31; // in bits
bool m_own:1;
void dealloc()
{
if (m_buf) std::free(m_buf-1);
m_buf = NULL;
}
// the first element is not part of the bitfield, it's the
// number of bits. For this purpose, the m_buf actually points
// the element 1, not 0. To access the size (in bits), access
// m_buf[-1]
boost::uint32_t* m_buf;
};
}

View File

@ -0,0 +1,535 @@
/*
Copyright (c) 2010-2013, Arvid Norberg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TORRENT_BLOCK_CACHE
#define TORRENT_BLOCK_CACHE
#include <boost/unordered_set.hpp>
#include <boost/cstdint.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/shared_array.hpp>
#include <list>
#include <vector>
#include "libtorrent/time.hpp"
#include "libtorrent/error_code.hpp"
#include "libtorrent/io_service_fwd.hpp"
#include "libtorrent/hasher.hpp"
#include "libtorrent/sliding_average.hpp"
#include "libtorrent/time.hpp"
#include "libtorrent/tailqueue.hpp"
#include "libtorrent/linked_list.hpp"
#include "libtorrent/disk_buffer_pool.hpp"
#include "libtorrent/file.hpp" // for iovec_t
#if TORRENT_USE_ASSERTS
#include "libtorrent/disk_io_job.hpp"
#endif
namespace libtorrent
{
struct disk_io_job;
class piece_manager;
struct disk_buffer_pool;
struct cache_status;
struct block_cache_reference;
struct counters;
namespace aux { struct session_settings; }
struct alert_dispatcher;
#if TORRENT_USE_ASSERTS
class file_storage;
#endif
#if TORRENT_USE_ASSERTS
struct piece_log_t
{
piece_log_t(int j, int b= -1): job(j), block(b) {}
int job;
int block;
// these are "jobs" thar cause piece_refcount
// to be incremented
enum artificial_jobs
{
flushing = disk_io_job::num_job_ids, // 20
flush_expired,
try_flush_write_blocks,
try_flush_write_blocks2,
flush_range,
clear_outstanding_jobs,
set_outstanding_jobs,
last_job
};
static char const* job_names[7];
};
char const* job_name(int j);
void print_piece_log(std::vector<piece_log_t> const& piece_log);
#endif
struct TORRENT_EXTRA_EXPORT partial_hash
{
partial_hash(): offset(0) {}
// the number of bytes in the piece that has been hashed
int offset;
// the sha-1 context
hasher h;
};
struct cached_block_entry
{
cached_block_entry()
: buf(0)
, refcount(0)
, dirty(false)
, hitcount(0)
, pending(false)
{
#if TORRENT_USE_ASSERTS
hashing_count = 0;
reading_count = 0;
flushing_count = 0;
#endif
}
char* buf;
enum { max_refcount = (1 << 15) -1 };
// the number of references to this buffer. These references
// might be in outstanding asyncronous requests or in peer
// connection send buffers. We can't free the buffer until
// all references are gone and refcount reaches 0. The buf
// pointer in this struct doesn't count as a reference and
// is always the last to be cleared
boost::uint16_t refcount:15;
// if this is true, this block needs to be written to
// disk before it's freed. Typically all blocks in a piece
// would either be dirty (write coalesce cache) or not dirty
// (read-ahead cache). Once blocks are written to disk, the
// dirty flag is cleared and effectively turns the block
// into a read cache block
boost::uint16_t dirty:1;
// the number of times this block has been copied out of
// the cache, serving a request.
boost::uint16_t hitcount:15;
// pending means that this buffer has not yet been filled in
// with valid data. There's an outstanding read job for this.
// If the dirty flag is set, it means there's an outstanding
// write job to write this block.
boost::uint16_t pending:1;
#if TORRENT_USE_ASSERTS
// this many of the references are held by hashing operations
int hashing_count;
// this block is being used in this many peer's send buffers currently
int reading_count;
// the number of references held by flushing operations
int flushing_count;
#endif
};
// list_node is here to be able to link this cache entry
// into one of the LRU lists
struct TORRENT_EXTRA_EXPORT cached_piece_entry : list_node
{
cached_piece_entry();
~cached_piece_entry();
bool ok_to_evict(bool ignore_hash = false) const
{
return refcount == 0
&& piece_refcount == 0
&& num_blocks == 0
&& !hashing
&& read_jobs.size() == 0
&& (ignore_hash || !hash || hash->offset == 0);
}
// storage this piece belongs to
boost::shared_ptr<piece_manager> storage;
// write jobs hanging off of this piece
tailqueue jobs;
// read jobs waiting for the read job currently outstanding
// on this piece to complete. These are executed at that point.
tailqueue read_jobs;
int get_piece() const { return piece; }
void* get_storage() const { return storage.get(); }
bool operator==(cached_piece_entry const& rhs) const
{ return storage.get() == rhs.storage.get() && piece == rhs.piece; }
// if this is set, we'll be calculating the hash
// for this piece. This member stores the interim
// state while we're calulcating the hash.
partial_hash* hash;
// set to a unique identifier of a peer that last
// requested from this piece.
void* last_requester;
// the pointers to the block data. If this is a ghost
// cache entry, there won't be any data here
// TODO: 3 could this be a scoped_array instead? does cached_piece_entry really need to be copyable?
// cached_piece_entry does need to be copyable since it's part of a container, but it's possible
// it could be a raw pointer or boost::unique_ptr perhaps
boost::shared_array<cached_block_entry> blocks;
// the last time a block was written to this piece
// plus the minimum amount of time the block is guaranteed
// to stay in the cache
//TODO: make this 32 bits and to count seconds since the block cache was created
ptime expire;
boost::uint64_t piece:22;
// the number of dirty blocks in this piece
boost::uint64_t num_dirty:14;
// the number of blocks in the cache for this piece
boost::uint64_t num_blocks:14;
// the total number of blocks in this piece (and the number
// of elements in the blocks array)
boost::uint64_t blocks_in_piece:14;
// ---- 64 bit boundary ----
// while we have an outstanding async hash operation
// working on this piece, 'hashing' is set to 1
// When the operation returns, this is set to 0.
boost::uint32_t hashing:1;
// if we've completed at least one hash job on this
// piece, and returned it. This is set to one
boost::uint32_t hashing_done:1;
// if this is true, whenever refcount hits 0,
// this piece should be deleted
boost::uint32_t marked_for_deletion:1;
// this is set to true once we flush blocks past
// the hash cursor. Once this happens, there's
// no point in keeping cache blocks around for
// it in avoid_readback mode
boost::uint32_t need_readback:1;
// indicates which LRU list this piece is chained into
enum cache_state_t
{
// this is the LRU list for pieces with dirty blocks
write_lru,
// this is the LRU list for volatile pieces. i.e.
// pieces with very low cache priority. These are
// always the first ones to be evicted.
volatile_read_lru,
// this is the LRU list for read blocks that have
// been requested once
read_lru1,
// the is the LRU list for read blocks that have
// been requested once recently, but then was evicted.
// if these are requested again, they will be moved
// to list 2, the frequently requested pieces
read_lru1_ghost,
// this is the LRU of frequently used pieces. Any
// piece that has been requested by a second peer
// while pulled in to list 1 by a different peer
// is moved into this list
read_lru2,
// this is the LRU of frequently used pieces but
// that has been recently evicted. If a piece in
// this list is requested, it's moved back into list 2.
read_lru2_ghost,
num_lrus
};
boost::uint32_t cache_state:3;
// this is the number of threads that are currently holding
// a reference to this piece. A piece may not be removed from
// the cache while this is > 0
boost::uint32_t piece_refcount:7;
// if this is set to one, it means there is an outstanding
// flush_hashed job for this piece, and there's no need to
// issue another one.
boost::uint32_t outstanding_flush:1;
// as long as there is a read operation outstanding on this
// piece, this is set to 1. Otherwise 0.
// the purpose is to make sure not two threads are reading
// the same blocks at the same time. If a new read job is
// added when this is 1, that new job should be hung on the
// read job queue (read_jobs).
boost::uint32_t outstanding_read:1;
// the number of blocks that have >= 1 refcount
boost::uint32_t pinned:16;
// ---- 32 bit boundary ---
// the sum of all refcounts in all blocks
boost::uint32_t refcount;
#if TORRENT_USE_ASSERTS
// the number of times this piece has finished hashing
int hash_passes;
// this is a debug facility to keep a log
// of which operations have been run on this piece
std::vector<piece_log_t> piece_log;
bool in_storage;
bool in_use;
#endif
};
inline std::size_t hash_value(cached_piece_entry const& p)
{
return std::size_t(p.storage.get()) + p.piece;
}
struct TORRENT_EXTRA_EXPORT block_cache : disk_buffer_pool
{
block_cache(int block_size, io_service& ios
, boost::function<void()> const& trigger_trim
, alert_dispatcher* alert_disp);
private:
typedef boost::unordered_set<cached_piece_entry> cache_t;
public:
typedef cache_t::iterator iterator;
typedef cache_t::const_iterator const_iterator;
// returns the number of blocks this job would cause to be read in
int pad_job(disk_io_job const* j, int blocks_in_piece
, int read_ahead) const;
int allocate_iovec(file::iovec_t* iov, int iov_len);
void free_iovec(file::iovec_t* iov, int iov_len);
void reclaim_block(block_cache_reference const& ref);
// returns a range of all pieces. This migh be a very
// long list, use carefully
std::pair<iterator, iterator> all_pieces() const;
int num_pieces() const { return m_pieces.size(); }
list_iterator write_lru_pieces() const
{ return m_lru[cached_piece_entry::write_lru].iterate(); }
int num_write_lru_pieces() const { return m_lru[cached_piece_entry::write_lru].size(); }
// mark this piece for deletion. If there are no outstanding
// requests to this piece, it's removed immediately, and the
// passed in iterator will be invalidated
void mark_for_deletion(cached_piece_entry* p);
// similar to mark_for_deletion, except for actually marking the
// piece for deletion. If the piece was actually deleted,
// the function returns true
bool evict_piece(cached_piece_entry* p, tailqueue& jobs);
// if this piece is in L1 or L2 proper, move it to
// its respective ghost list
void move_to_ghost(cached_piece_entry* p);
// returns the number of bytes read on success (cache hit)
// -1 on cache miss
int try_read(disk_io_job* j, bool count_stats = true, bool expect_no_fail = false);
// called when we're reading and we found the piece we're
// reading from in the hash table (not necessarily that we
// hit the block we needed)
void cache_hit(cached_piece_entry* p, void* requester, bool volatile_read);
// free block from piece entry
void free_block(cached_piece_entry* pe, int block);
// erase a piece (typically from the ghost list). Reclaim all
// its blocks and unlink it and free it.
void erase_piece(cached_piece_entry* p);
// bump the piece 'p' to the back of the LRU list it's
// in (back == MRU)
// this is only used for the write cache
void bump_lru(cached_piece_entry* p);
// move p into the correct lru queue
void update_cache_state(cached_piece_entry* p);
// if the piece is marked for deletion and has a refcount
// of 0, this function will post any sync jobs and
// delete the piece from the cache
bool maybe_free_piece(cached_piece_entry* p);
// either returns the piece in the cache, or allocates
// a new empty piece and returns it.
// cache_state is one of cache_state_t enum
cached_piece_entry* allocate_piece(disk_io_job const* j, int cache_state);
// looks for this piece in the cache. If it's there, returns a pointer
// to it, otherwise 0.
cached_piece_entry* find_piece(block_cache_reference const& ref);
cached_piece_entry* find_piece(disk_io_job const* j);
cached_piece_entry* find_piece(piece_manager* st, int piece);
// clear free all buffers marked as dirty with
// refcount of 0.
void abort_dirty(cached_piece_entry* p);
// used to convert dirty blocks into non-dirty ones
// i.e. from being part of the write cache to being part
// of the read cache. it's used when flushing blocks to disk
void blocks_flushed(cached_piece_entry* pe, int const* flushed, int num_flushed);
// adds a block to the cache, marks it as dirty and
// associates the job with it. When the block is
// flushed, the callback is posted
cached_piece_entry* add_dirty_block(disk_io_job* j);
enum { blocks_inc_refcount = 1 };
void insert_blocks(cached_piece_entry* pe, int block, file::iovec_t *iov
, int iov_len, disk_io_job* j, int flags = 0);
#if TORRENT_USE_INVARIANT_CHECKS
void check_invariant() const;
#endif
// try to remove num number of read cache blocks from the cache
// pick the least recently used ones first
// return the number of blocks that was requested to be evicted
// that couldn't be
int try_evict_blocks(int num, cached_piece_entry* ignore = 0);
// if there are any dirty blocks
void clear(tailqueue& jobs);
void update_stats_counters(counters& c) const;
void get_stats(cache_status* ret) const;
void set_settings(aux::session_settings const& sett);
enum reason_t { ref_hashing = 0, ref_reading = 1, ref_flushing = 2 };
bool inc_block_refcount(cached_piece_entry* pe, int block, int reason);
void dec_block_refcount(cached_piece_entry* pe, int block, int reason);
int pinned_blocks() const { return m_pinned_blocks; }
#if TORRENT_USE_ASSERTS
void mark_deleted(file_storage const& fs);
#endif
private:
// returns number of bytes read on success, -1 on cache miss
// (just because the piece is in the cache, doesn't mean all
// the blocks are there)
int copy_from_piece(cached_piece_entry* p, disk_io_job* j, bool expect_no_fail = false);
void free_piece(cached_piece_entry* p);
int drain_piece_bufs(cached_piece_entry& p, std::vector<char*>& buf);
// block container
cache_t m_pieces;
// linked list of all elements in m_pieces, in usage order
// the most recently used are in the tail. iterating from head
// to tail gives the least recently used entries first
// the read-list is for read blocks and the write-list is for
// dirty blocks that needs flushing before being evicted
// [0] = write-LRU
// [1] = read-LRU1
// [2] = read-LRU1-ghost
// [3] = read-LRU2
// [4] = read-LRU2-ghost
linked_list m_lru[cached_piece_entry::num_lrus];
// this is used to determine whether to evict blocks from
// L1 or L2.
enum cache_op_t
{
cache_miss,
ghost_hit_lru1,
ghost_hit_lru2
};
int m_last_cache_op;
// the number of pieces to keep in the ARC ghost lists
// this is determined by being a fraction of the cache size
int m_ghost_size;
// the number of blocks in the cache
// that are in the read cache
boost::uint32_t m_read_cache_size;
// the number of blocks in the cache
// that are in the write cache
boost::uint32_t m_write_cache_size;
// the number of blocks that are currently sitting
// in peer's send buffers. If two peers are sending
// the same block, it counts as 2, even though there're
// no buffer duplication
boost::uint32_t m_send_buffer_blocks;
boost::uint32_t m_blocks_read_hit;
// the number of blocks with a refcount > 0, i.e.
// they may not be evicted
int m_pinned_blocks;
#if TORRENT_USE_ASSERTS
std::vector<std::pair<std::string, void const*> > m_deleted_storages;
#endif
};
}
#endif // TORRENT_BLOCK_CACHE

View File

@ -86,13 +86,15 @@ namespace libtorrent
// The peer_conenction should handshake and verify that the
// other end has the correct id
bt_peer_connection(
aux::session_impl& ses
aux::session_interface& ses
, aux::session_settings const& sett
, buffer_allocator_interface& allocator
, disk_interface& disk_thread
, boost::shared_ptr<socket_type> s
, tcp::endpoint const& remote
, policy::peer* peerinfo
, torrent_peer* peerinfo
, peer_id const& pid
, boost::weak_ptr<torrent> t = boost::weak_ptr<torrent>()
, bool outgoing = false);
, boost::weak_ptr<torrent> t = boost::weak_ptr<torrent>());
void start();
@ -225,8 +227,9 @@ namespace libtorrent
void write_cancel(peer_request const& r);
void write_bitfield();
void write_have(int index);
void write_dont_have(int index);
void write_piece(peer_request const& r, disk_buffer_holder& buffer);
void write_handshake();
void write_handshake(bool plain_handshake = false);
#ifndef TORRENT_DISABLE_EXTENSIONS
void write_extensions();
void write_upload_only();
@ -299,22 +302,22 @@ public:
// these functions encrypt the send buffer if m_rc4_encrypted
// is true, otherwise it passes the call to the
// peer_connection functions of the same names
virtual void append_const_send_buffer(char const* buffer, int size);
virtual void append_const_send_buffer(char const* buffer, int size
, chained_buffer::free_buffer_fun destructor = &nop
, void* userdata = NULL, block_cache_reference ref
= block_cache_reference());
virtual void send_buffer(char const* begin, int size, int flags = 0
, void (*fun)(char*, int, void*) = 0, void* userdata = 0);
template <class Destructor>
void bt_append_send_buffer(char* buffer, int size, Destructor const& destructor)
{
#ifndef TORRENT_DISABLE_ENCRYPTION
if (m_rc4_encrypted)
m_enc_handler->encrypt(buffer, size);
#endif
peer_connection::append_send_buffer(buffer, size, destructor, true);
}
virtual void append_send_buffer(char* buffer, int size
, chained_buffer::free_buffer_fun destructor = &nop
, void* userdata = NULL, block_cache_reference ref
= block_cache_reference(), bool encrypted = false);
private:
enum state
enum state_t
{
#ifndef TORRENT_DISABLE_ENCRYPTION
read_pe_dhkey = 0,
@ -345,7 +348,7 @@ private:
};
#endif
// state of on_receive
// state of on_receive. one of the enums in state_t
boost::uint8_t m_state;
// this is set to true if the handshake from
@ -355,15 +358,15 @@ private:
bool m_supports_dht_port:1;
bool m_supports_fast:1;
#if TORRENT_USE_ASSERTS
// this is set to true when the client's
// bitfield is sent to this peer
// this is set to true when we send the bitfield message.
// for magnet links we can't do that right away,
// since we don't know how many pieces there are in
// the torrent.
bool m_sent_bitfield:1;
bool m_in_constructor:1;
// true if we're done sending the bittorrent handshake,
// and can send bittorrent messages
bool m_sent_handshake:1;
#endif
#ifndef TORRENT_DISABLE_ENCRYPTION
// this is set to true after the encryption method has been
@ -375,19 +378,8 @@ private:
bool m_rc4_encrypted:1;
#endif
#ifndef TORRENT_DISABLE_EXTENSIONS
// the message ID for upload only message
// 0 if not supported
boost::uint8_t m_upload_only_id;
// the message ID for holepunch messages
boost::uint8_t m_holepunch_id;
#endif
std::string m_client_version;
static const message_handler m_message_handler[num_supported_messages];
// the peer ID we advertise for ourself
peer_id m_our_peer_id;
@ -408,13 +400,8 @@ private:
int start;
int length;
};
static bool range_below_zero(const range& r)
{ return r.start < 0; }
std::vector<range> m_payloads;
// we have suggested these pieces to the peer
// don't suggest it again
bitfield m_sent_suggested_pieces;
std::vector<range> m_payloads;
#ifndef TORRENT_DISABLE_ENCRYPTION
// initialized during write_pe1_2_dhkey, and destroyed on
@ -436,13 +423,24 @@ private:
// the sync hash (hash("req1",secret)). Destroyed after the
// sync step.
boost::scoped_ptr<sha1_hash> m_sync_hash;
#endif // #ifndef TORRENT_DISABLE_ENCRYPTION
static const message_handler m_message_handler[num_supported_messages];
#ifndef TORRENT_DISABLE_ENCRYPTION
// used to disconnect peer if sync points are not found within
// the maximum number of bytes
int m_sync_bytes_read;
#endif // #ifndef TORRENT_DISABLE_ENCRYPTION
#endif
#ifndef TORRENT_DISABLE_EXTENSIONS
// the message ID for upload only message
// 0 if not supported
boost::uint8_t m_upload_only_id;
// the message ID for holepunch messages
boost::uint8_t m_holepunch_id;
// the message ID for don't-have message
boost::uint8_t m_dont_have_id;
@ -450,10 +448,13 @@ private:
// 0 if not supported
boost::uint8_t m_share_mode_id;
// the reserved bits received from the other peer
// in the bittorrent handshake
char m_reserved_bits[8];
#endif
#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
bool m_in_constructor;
#endif
};
}

View File

@ -36,6 +36,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/invariant_check.hpp"
#include "libtorrent/assert.hpp"
#include <cstdlib> // malloc/free/realloc
#include <boost/cstdint.hpp>
namespace libtorrent {
@ -98,16 +99,16 @@ public:
buffer(std::size_t n = 0)
: m_begin(0)
, m_end(0)
, m_last(0)
, m_size(0)
, m_capacity(0)
{
if (n) resize(n);
}
buffer(buffer const& b)
: m_begin(0)
, m_end(0)
, m_last(0)
, m_size(0)
, m_capacity(0)
{
if (b.size() == 0) return;
resize(b.size());
@ -115,8 +116,14 @@ public:
}
#if __cplusplus > 199711L
buffer(buffer&& b): m_begin(b.m_begin), m_end(b.m_end), m_last(b.m_last)
{ b.m_begin = b.m_end = b.m_last = NULL; }
buffer(buffer&& b)
: m_begin(b.m_begin)
, m_size(b.m_size)
, m_capacity(b.m_capacity)
{
b.m_begin = NULL;
b.m_size = b.m_capacity = 0;
}
#endif
buffer& operator=(buffer const& b)
@ -133,19 +140,21 @@ public:
std::free(m_begin);
}
buffer::interval data() { return interval(m_begin, m_end); }
buffer::const_interval data() const { return const_interval(m_begin, m_end); }
buffer::interval data()
{ return interval(m_begin, m_begin + m_size); }
buffer::const_interval data() const
{ return const_interval(m_begin, m_begin + m_size); }
void resize(std::size_t n)
{
reserve(n);
m_end = m_begin + n;
m_size = n;
}
void insert(char* point, char const* first, char const* last)
{
std::size_t p = point - m_begin;
if (point == m_end)
if (point == m_begin + m_size)
{
resize(size() + last - first);
std::memcpy(m_begin + p, first, last - first);
@ -159,52 +168,51 @@ public:
void erase(char* b, char* e)
{
TORRENT_ASSERT(e <= m_end);
TORRENT_ASSERT(e <= m_begin + m_size);
TORRENT_ASSERT(b >= m_begin);
TORRENT_ASSERT(b <= e);
if (e == m_end)
if (e == m_begin + m_size)
{
resize(b - m_begin);
return;
}
std::memmove(b, e, m_end - e);
m_end = b + (m_end - e);
std::memmove(b, e, m_begin + m_size - e);
TORRENT_ASSERT(e - b <= m_size);
m_size -= e - b;
}
void clear() { m_end = m_begin; }
std::size_t size() const { return m_end - m_begin; }
std::size_t capacity() const { return m_last - m_begin; }
void clear() { m_size = 0; }
std::size_t size() const { return m_size; }
std::size_t capacity() const { return m_capacity; }
void reserve(std::size_t n)
{
if (n <= capacity()) return;
TORRENT_ASSERT(n > 0);
std::size_t s = size();
m_begin = (char*)std::realloc(m_begin, n);
m_end = m_begin + s;
m_last = m_begin + n;
m_capacity = n;
}
bool empty() const { return m_begin == m_end; }
bool empty() const { return m_size == 0; }
char& operator[](std::size_t i) { TORRENT_ASSERT(i < size()); return m_begin[i]; }
char const& operator[](std::size_t i) const { TORRENT_ASSERT(i < size()); return m_begin[i]; }
char* begin() { return m_begin; }
char const* begin() const { return m_begin; }
char* end() { return m_end; }
char const* end() const { return m_end; }
char* end() { return m_begin + m_size; }
char const* end() const { return m_begin + m_size; }
void swap(buffer& b)
{
using std::swap;
swap(m_begin, b.m_begin);
swap(m_end, b.m_end);
swap(m_last, b.m_last);
swap(m_size, b.m_size);
swap(m_capacity, b.m_capacity);
}
private:
char* m_begin; // first
char* m_end; // one passed end of size
char* m_last; // one passed end of allocation
char* m_begin;
boost::uint32_t m_size;
boost::uint32_t m_capacity;
};

View File

@ -0,0 +1,50 @@
/*
Copyright (c) 2013, Arvid Norberg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TORRENT_BYTESWAP_HPP_INCLUDED
#define TORRENT_BYTESWAP_HPP_INCLUDED
// this header makes sure htonl(), nothl(), htons() and ntohs()
// are available
#include "libtorrent/config.hpp"
#ifdef TORRENT_WINDOWS
#include <Winsock2.h>
#else
// posix header
// for ntohl and htonl
#include <arpa/inet.h>
#endif
#endif // TORRENT_BYTESWAP_HPP_INCLUDED

View File

@ -35,37 +35,47 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/config.hpp"
#include <boost/function/function1.hpp>
#include <boost/version.hpp>
#if BOOST_VERSION < 103500
#include <asio/buffer.hpp>
#else
#include <boost/asio/buffer.hpp>
#endif
#include <list>
#include <deque>
#include <vector>
#include <string.h> // for memcpy
#include "libtorrent/disk_io_job.hpp" // for block_cache_reference
#include "libtorrent/debug.hpp"
namespace libtorrent
{
#if BOOST_VERSION >= 103500
namespace asio = boost::asio;
#endif
struct TORRENT_EXTRA_EXPORT chained_buffer
struct TORRENT_EXTRA_EXPORT chained_buffer : private single_threaded
{
chained_buffer(): m_bytes(0), m_capacity(0)
{
thread_started();
#if TORRENT_USE_ASSERTS
m_destructed = false;
#endif
}
// destructs/frees the buffer (1st arg) with
// 2nd argument as userdata
typedef void (*free_buffer_fun)(char*, void*, block_cache_reference ref);
struct buffer_t
{
boost::function<void(char*)> free; // destructs the buffer
free_buffer_fun free_fun;
void* userdata;
char* buf; // the first byte of the buffer
char* start; // the first byte to send/receive in the buffer
int size; // the total size of the buffer
int used_size; // this is the number of bytes to send/receive
block_cache_reference ref;
};
bool empty() const { return m_bytes == 0; }
@ -75,7 +85,8 @@ namespace libtorrent
void pop_front(int bytes_to_pop);
void append_buffer(char* buffer, int s, int used_size
, boost::function<void(char*)> const& destructor);
, free_buffer_fun destructor, void* userdata
, block_cache_reference ref = block_cache_reference());
// returns the number of bytes available at the
// end of the last chained buffer.
@ -91,7 +102,9 @@ namespace libtorrent
// enough room, returns 0
char* allocate_appendix(int s);
std::list<asio::const_buffer> const& build_iovec(int to_send);
std::vector<asio::const_buffer> const& build_iovec(int to_send);
void clear();
~chained_buffer();
@ -99,11 +112,7 @@ namespace libtorrent
// this is the list of all the buffers we want to
// send
std::list<buffer_t> m_vec;
// this is the vector of buffers used when
// invoking the async write call
std::list<asio::const_buffer> m_tmp_vec;
std::deque<buffer_t> m_vec;
// this is the number of bytes in the send buf.
// this will always be equal to the sum of the
@ -114,6 +123,10 @@ namespace libtorrent
// including unused space
int m_capacity;
// this is the vector of buffers used when
// invoking the async write call
std::vector<asio::const_buffer> m_tmp_vec;
#if TORRENT_USE_ASSERTS
bool m_destructed;
#endif

Some files were not shown because too many files have changed in this diff Show More