land libtorrent_aio branch in trunk
|
@ -24,7 +24,7 @@ build_features:
|
|||
|
||||
project: libtorrent
|
||||
|
||||
branch: trunk
|
||||
branch: aio
|
||||
|
||||
clean:
|
||||
- test_tmp_*
|
||||
|
|
|
@ -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}
|
||||
|
|
29
ChangeLog
|
@ -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
|
@ -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 ] ;
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
@ -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>(
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
|
||||
session_settings sett;
|
||||
for (int i = 0; i < len; ++i)
|
||||
settings_pack p;
|
||||
list iterkeys = (list)sett_dict.iterkeys();
|
||||
for (int i = 0; i < boost::python::len(iterkeys); i++)
|
||||
{
|
||||
if (!sett_dict.has_key(map[i].name)) continue;
|
||||
std::string key = extract<std::string>(iterkeys[i]);
|
||||
|
||||
void* dest = ((char*)&sett) + map[i].offset;
|
||||
char const* name = map[i].name;
|
||||
switch (map[i].type)
|
||||
int sett = setting_by_name(key);
|
||||
if (sett == 0) continue;
|
||||
|
||||
TORRENT_TRY
|
||||
{
|
||||
case std_string:
|
||||
*((std::string*)dest) = extract<std::string>(sett_dict[name]);
|
||||
break;
|
||||
case character:
|
||||
*((char*)dest) = extract<char>(sett_dict[name]);
|
||||
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]);
|
||||
break;
|
||||
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 settings_pack::int_type_base:
|
||||
p.set_int(sett, extract<int>(value));
|
||||
break;
|
||||
case settings_pack::bool_type_base:
|
||||
p.set_bool(sett, extract<bool>(value));
|
||||
break;
|
||||
}
|
||||
}
|
||||
TORRENT_CATCH(...) {}
|
||||
}
|
||||
|
||||
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"]);
|
||||
allow_threading_guard guard;
|
||||
|
||||
ses.set_settings(sett);
|
||||
ses.apply_settings(p);
|
||||
}
|
||||
|
||||
dict session_get_settings(session const& ses)
|
||||
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)
|
||||
{
|
||||
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_str(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;
|
||||
|
||||
for (int i = settings_pack::int_type_base;
|
||||
i < settings_pack::max_int_setting_internal; ++i)
|
||||
{
|
||||
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);
|
||||
}
|
||||
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,45 +419,47 @@ 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;
|
||||
std::vector<cached_piece_info> ret;
|
||||
|
||||
{
|
||||
allow_threading_guard guard;
|
||||
ses.get_cache_info(ih, ret);
|
||||
}
|
||||
{
|
||||
allow_threading_guard guard;
|
||||
ses.get_cache_info(ih, ret);
|
||||
}
|
||||
|
||||
list pieces;
|
||||
ptime now = time_now();
|
||||
for (std::vector<cached_piece_info>::iterator i = ret.begin()
|
||||
, end(ret.end()); i != end; ++i)
|
||||
{
|
||||
dict d;
|
||||
d["piece"] = i->piece;
|
||||
d["last_use"] = total_milliseconds(now - i->last_use) / 1000.f;
|
||||
d["next_to_hash"] = i->next_to_hash;
|
||||
d["kind"] = i->kind;
|
||||
pieces.append(d);
|
||||
}
|
||||
return pieces;
|
||||
list pieces;
|
||||
ptime now = time_now();
|
||||
for (std::vector<cached_piece_info>::iterator i = ret.begin()
|
||||
, end(ret.end()); i != end; ++i)
|
||||
{
|
||||
dict d;
|
||||
d["piece"] = i->piece;
|
||||
d["last_use"] = total_milliseconds(now - i->last_use) / 1000.f;
|
||||
d["next_to_hash"] = i->next_to_hash;
|
||||
d["kind"] = i->kind;
|
||||
pieces.append(d);
|
||||
}
|
||||
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)() = <::session::start_dht;
|
||||
void (lt::session::*start_dht1)(entry const&) = <::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(<::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(<::session::is_listening))
|
||||
.def("listen_port", allow_threads(<::session::listen_port))
|
||||
.def("status", allow_threads(<::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(<::session::is_dht_running))
|
||||
.def("set_dht_settings", allow_threads(<::session::set_dht_settings))
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
.def("start_dht", allow_threads(start_dht0))
|
||||
.def("stop_dht", allow_threads(<::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(<::session::dht_state))
|
||||
.def("set_dht_proxy", allow_threads(<::session::set_dht_proxy))
|
||||
.def("dht_proxy", allow_threads(<::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(<::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(<::session::set_local_download_rate_limit))
|
||||
.def("local_download_rate_limit", allow_threads(<::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(<::session::set_local_upload_rate_limit))
|
||||
.def("local_upload_rate_limit", allow_threads(<::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(<::session::set_download_rate_limit))
|
||||
.def("download_rate_limit", allow_threads(<::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(<::session::set_upload_rate_limit))
|
||||
.def("upload_rate_limit", allow_threads(<::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(<::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("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(<::session::set_pe_settings))
|
||||
.def("get_pe_settings", allow_threads(<::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(<::session::set_severity_level))
|
||||
.def("set_alert_queue_size_limit", allow_threads(<::session::set_alert_queue_size_limit))
|
||||
.def("set_alert_mask", allow_threads(<::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(<::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))
|
||||
#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(<::session::set_i2p_proxy))
|
||||
.def("i2p_proxy", allow_threads(<::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(<::session::set_proxy))
|
||||
.def("proxy", allow_threads(<::session::proxy))
|
||||
.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("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(<::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_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(<::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("get_cache_status", &get_cache_status)
|
||||
.def("get_cache_info", &get_cache_info2)
|
||||
#endif
|
||||
.def("set_peer_id", allow_threads(<::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";
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
info.prioritize_pieces(result);
|
||||
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))
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
15
configure.ac
|
@ -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 "
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
<tr><th class="docinfo-name">Author:</th>
|
||||
<td>Arvid Norberg, <a class="last reference external" href="mailto:arvid@rasterbar.com">arvid@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&package_id=8041&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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
<tr><th class="docinfo-name">Author:</th>
|
||||
<td>Arvid Norberg, <a class="last reference external" href="mailto:arvid@rasterbar.com">arvid@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">
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
<tr><th class="docinfo-name">Author:</th>
|
||||
<td>Arvid Norberg, <a class="last reference external" href="mailto:arvid@rasterbar.com">arvid@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">
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
<tr><th class="docinfo-name">Author:</th>
|
||||
<td>Arvid Norberg, <a class="last reference external" href="mailto:arvid@rasterbar.com">arvid@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">
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
<tr><th class="docinfo-name">Author:</th>
|
||||
<td>Arvid Norberg, <a class="last reference external" href="mailto:arvid@rasterbar.com">arvid@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">
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -178,40 +178,40 @@ int main(int argc, char* argv[])
|
|||
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";
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
try
|
||||
#endif
|
||||
if (argc != 2)
|
||||
{
|
||||
session s;
|
||||
s.listen_on(std::make_pair(6881, 6889));
|
||||
add_torrent_params p;
|
||||
p.save_path = "./";
|
||||
p.ti = new torrent_info(argv[1]);
|
||||
s.add_torrent(p);
|
||||
fputs("usage: ./simple_client torrent-file\n"
|
||||
"to stop the client, press return.\n", stderr);
|
||||
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)
|
||||
session s;
|
||||
error_code ec;
|
||||
s.listen_on(std::make_pair(6881, 6889), ec);
|
||||
if (ec)
|
||||
{
|
||||
std::cout << e.what() << "\n";
|
||||
fprintf(stderr, "failed to open listen socket: %s\n", ec.message().c_str());
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
add_torrent_params p;
|
||||
p.save_path = "./";
|
||||
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;
|
||||
scanf("%c\n", &a);
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
|
|
|
@ -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";
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
try
|
||||
#endif
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
session s;
|
||||
s.listen_on(std::make_pair(6881, 6889));
|
||||
add_torrent_params p;
|
||||
p.save_path = "./";
|
||||
p.ti = new torrent_info(argv[1]);
|
||||
s.add_torrent(p);
|
||||
|
||||
// wait for the user to end
|
||||
char a;
|
||||
std::cin.unsetf(std::ios_base::skipws);
|
||||
std::cin >> a;
|
||||
fputs("usage: ./simple_client torrent-file\n"
|
||||
"to stop the client, press return.\n", stderr);
|
||||
return 1;
|
||||
}
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
catch (std::exception& e)
|
||||
|
||||
session s;
|
||||
error_code ec;
|
||||
s.listen_on(std::make_pair(6881, 6889), ec);
|
||||
if (ec)
|
||||
{
|
||||
std::cout << e.what() << "\n";
|
||||
fprintf(stderr, "failed to open listen socket: %s\n", ec.message().c_str());
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
add_torrent_params p;
|
||||
p.save_path = "./";
|
||||
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;
|
||||
scanf("%c\n", &a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
<tr><th class="docinfo-name">Author:</th>
|
||||
<td>Arvid Norberg, <a class="last reference external" href="mailto:arvid@rasterbar.com">arvid@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 > 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
|
||||
|
|
|
@ -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
|
||||
|
|
BIN
docs/folx.png
Before Width: | Height: | Size: 14 KiB |
|
@ -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 = []
|
||||
|
|
|
@ -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()
|
||||
|
|
@ -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:
|
||||
|
|
|
@ -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@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@rasterbar.com">arvid@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> | ---------> | aux::session_impl |
|
||||
+=========+ +-------------------+
|
||||
m_torrents[] | |
|
||||
+================+ | |
|
||||
| <strong>torrent_handle</strong> | ------+ | |
|
||||
+================+ | | |
|
||||
| | | m_connections[]
|
||||
| | |
|
||||
| | +---------------------+
|
||||
m_picker v v |
|
||||
+--------------+ +---------+---------+-- . . |
|
||||
| piece_picker | <--+-| torrent | torrent | to |
|
||||
+--------------+ | +---------+---------+-- . . |
|
||||
m_torrent_file | | m_connections[] |
|
||||
+==============+ | | |
|
||||
| <strong>torrent_info</strong> | <--+ v v
|
||||
+==============+ | +-----------------+-----------------+-- . .
|
||||
m_policy | | peer_connection | peer_connection | pe
|
||||
+--------+ | +-----------------+-----------------+-- . .
|
||||
| policy | <--------+ | | m_socket
|
||||
+--------+ | |
|
||||
| m_peers[] | v
|
||||
| | +-----------------------+
|
||||
| | | socket_type (variant) |
|
||||
v | +-----------------------+
|
||||
+--------------+ |
|
||||
| policy::peer | |
|
||||
+--------------+ |
|
||||
| policy::peer | |
|
||||
+--------------+ m_peer_info|
|
||||
| policy::peer | <----------+
|
||||
+--------------+
|
||||
. .
|
||||
+ - - - - - - -+
|
||||
</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>
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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@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@rasterbar.com">arvid@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"><libtorrent/socket.hpp></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& 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[] =
|
||||
{
|
||||
"inget fel",
|
||||
"en fil i torrenten kolliderar med en fil fran en annan torrent",
|
||||
"hash check misslyckades",
|
||||
"torrentfilen ar inte en dictionary",
|
||||
"'info'-nyckeln saknas eller ar korrupt i torrentfilen",
|
||||
"'info'-faltet ar inte en dictionary",
|
||||
"'piece length' faltet saknas eller ar korrupt i torrentfilen",
|
||||
"torrentfilen saknar namnfaltet",
|
||||
"ogiltigt namn i torrentfilen (kan vara en attack)",
|
||||
// ... more strings here
|
||||
};
|
||||
|
||||
// use the default error string in case we don't have it
|
||||
// in our translated list
|
||||
if (code < 0 || code >= 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>&dn=</strong> <em>name of download</em> ] [ <strong>&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: "libtorrent resume file"</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> >= <strong>s</strong> then allocate a new slot and put the piece there.</li>
|
||||
<li>if <strong>n</strong> < <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: "LT_metadata"</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: "lt_dont_have"</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 ("*"), 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 "star cert").</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 <peer-certificate>.pem -key <peer-private-key>.pem -CAfile \
|
||||
<torrent-cert>.pem -debug -connect 127.0.0.1:4433 -tls1 -servername <info-hash>
|
||||
</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>
|
205
docs/manual.rst
|
@ -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"
|
||||
|
||||
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.
|
||||
.. 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.
|
||||
|
||||
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
|
||||
|
||||
|
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 14 KiB |
|
@ -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@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@rasterbar.com">arvid@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 "<a class="reference external" href="../include/libtorrent/bencode.hpp">libtorrent/bencode.hpp</a>"</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 "<a class="reference external" href="../include/libtorrent/entry.hpp">libtorrent/entry.hpp</a>"</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 "<a class="reference external" href="../include/libtorrent/entry.hpp">libtorrent/entry.hpp</a>"</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&);
|
||||
<strong>entry</strong> (integer_type const&);
|
||||
<strong>entry</strong> (dictionary_type const&);
|
||||
<strong>entry</strong> (string_type const&);
|
||||
<strong>entry</strong> (data_type t);
|
||||
void <strong>operator=</strong> (string_type const&);
|
||||
void <strong>operator=</strong> (entry const&);
|
||||
void <strong>operator=</strong> (integer_type const&);
|
||||
void <strong>operator=</strong> (lazy_entry const&);
|
||||
void <strong>operator=</strong> (dictionary_type const&);
|
||||
void <strong>operator=</strong> (list_type const&);
|
||||
const integer_type& <strong>integer</strong> () const;
|
||||
const string_type& <strong>string</strong> () const;
|
||||
const dictionary_type& <strong>dict</strong> () const;
|
||||
string_type& <strong>string</strong> ();
|
||||
list_type& <strong>list</strong> ();
|
||||
dictionary_type& <strong>dict</strong> ();
|
||||
integer_type& <strong>integer</strong> ();
|
||||
const list_type& <strong>list</strong> () const;
|
||||
void <strong>swap</strong> (entry& e);
|
||||
entry& <strong>operator[]</strong> (std::string const& key);
|
||||
const entry& <strong>operator[]</strong> (std::string const& key) const;
|
||||
entry& <strong>operator[]</strong> (char const* key);
|
||||
const entry& <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& key);
|
||||
entry const* <strong>find_key</strong> (std::string const& 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&);
|
||||
<strong>entry</strong> (integer_type const&);
|
||||
<strong>entry</strong> (dictionary_type const&);
|
||||
<strong>entry</strong> (string_type const&);
|
||||
</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&);
|
||||
void <strong>operator=</strong> (entry const&);
|
||||
void <strong>operator=</strong> (integer_type const&);
|
||||
void <strong>operator=</strong> (lazy_entry const&);
|
||||
void <strong>operator=</strong> (dictionary_type const&);
|
||||
void <strong>operator=</strong> (list_type const&);
|
||||
</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& <strong>integer</strong> () const;
|
||||
const string_type& <strong>string</strong> () const;
|
||||
const dictionary_type& <strong>dict</strong> () const;
|
||||
string_type& <strong>string</strong> ();
|
||||
list_type& <strong>list</strong> ();
|
||||
dictionary_type& <strong>dict</strong> ();
|
||||
integer_type& <strong>integer</strong> ();
|
||||
const list_type& <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& dict = torrent_file.dict();
|
||||
entry::dictionary_type::const_iterator i;
|
||||
i = dict.find("announce");
|
||||
if (i != dict.end())
|
||||
{
|
||||
std::string tracker_url = i->second.string();
|
||||
std::cout << tracker_url << "\n";
|
||||
}
|
||||
</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("announce"))
|
||||
{
|
||||
std::string tracker_url = i->string();
|
||||
std::cout << tracker_url << "\n";
|
||||
}
|
||||
</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& 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& <strong>operator[]</strong> (std::string const& key);
|
||||
const entry& <strong>operator[]</strong> (std::string const& key) const;
|
||||
entry& <strong>operator[]</strong> (char const* key);
|
||||
const entry& <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& key);
|
||||
entry const* <strong>find_key</strong> (std::string const& 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 "<a class="reference external" href="../include/libtorrent/entry.hpp">libtorrent/entry.hpp</a>"</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> </td>
|
||||
</tr>
|
||||
<tr><td>string_t</td>
|
||||
<td>1</td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
<tr><td>list_t</td>
|
||||
<td>2</td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
<tr><td>dictionary_t</td>
|
||||
<td>3</td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
<tr><td>undefined_t</td>
|
||||
<td>4</td>
|
||||
<td> </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 "<a class="reference external" href="../include/libtorrent/lazy_entry.hpp">libtorrent/lazy_entry.hpp</a>"</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<</strong> (pascal_string const& 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<()</h2>
|
||||
<pre class="literal-block">
|
||||
bool <strong>operator<</strong> (pascal_string const& 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 "<a class="reference external" href="../include/libtorrent/lazy_entry.hpp">libtorrent/lazy_entry.hpp</a>"</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 -> <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<std::string, lazy_entry const*> <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<char const*, int> <strong>data_section</strong> () const;
|
||||
void <strong>swap</strong> (lazy_entry& 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->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<std::string, lazy_entry const*> <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->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->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<char const*, int> <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& 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 "<a class="reference external" href="../include/libtorrent/lazy_entry.hpp">libtorrent/lazy_entry.hpp</a>"</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> </td>
|
||||
</tr>
|
||||
<tr><td>dict_t</td>
|
||||
<td>1</td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
<tr><td>list_t</td>
|
||||
<td>2</td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
<tr><td>string_t</td>
|
||||
<td>3</td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
<tr><td>int_t</td>
|
||||
<td>4</td>
|
||||
<td> </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 "<a class="reference external" href="../include/libtorrent/bencode.hpp">libtorrent/bencode.hpp</a>"</p>
|
||||
<pre class="literal-block">
|
||||
template<class InIt> entry <strong>bdecode</strong> (InIt start, InIt end);
|
||||
template<class OutIt> int <strong>bencode</strong> (OutIt out, const entry& e);
|
||||
template<class InIt> entry <strong>bdecode</strong> (InIt start, InIt end, int& 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<char> 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<char> 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<<()</h2>
|
||||
<p>Declared in "<a class="reference external" href="../include/libtorrent/entry.hpp">libtorrent/entry.hpp</a>"</p>
|
||||
<pre class="literal-block">
|
||||
inline std::ostream& <strong>operator<<</strong> (std::ostream& os, const entry& 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 "<a class="reference external" href="../include/libtorrent/lazy_entry.hpp">libtorrent/lazy_entry.hpp</a>"</p>
|
||||
<pre class="literal-block">
|
||||
int <strong>lazy_bdecode</strong> (char const* start, char const* end
|
||||
, lazy_entry& ret, error_code& 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 "<a class="reference external" href="../include/libtorrent/lazy_entry.hpp">libtorrent/lazy_entry.hpp</a>"</p>
|
||||
<pre class="literal-block">
|
||||
std::string <strong>print_entry</strong> (lazy_entry const& 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>
|
|
@ -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@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@rasterbar.com">arvid@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, "./my_torrent");
|
||||
|
||||
create_torrent t(fs);
|
||||
t.add_tracker("http://my.tracker.com/announce");
|
||||
t.set_creator("libtorrent example");
|
||||
|
||||
// reads the files and calculates the hashes
|
||||
set_piece_hashes(t, ".");
|
||||
|
||||
ofstream out("my_torrent.torrent", std::ios_base::binary);
|
||||
bencode(std::ostream_iterator<char>(out), t.generate());
|
||||
</pre>
|
||||
<a name="create_torrent"></a><div class="section" id="create-torrent">
|
||||
<h1>create_torrent</h1>
|
||||
<p>Declared in "<a class="reference external" href="../include/libtorrent/create_torrent.hpp">libtorrent/create_torrent.hpp</a>"</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& fs, int piece_size = 0
|
||||
, int pad_file_limit = -1, int flags = optimize, int alignment = -1);
|
||||
<strong>create_torrent</strong> (torrent_info const& ti);
|
||||
entry <strong>generate</strong> () const;
|
||||
file_storage const& <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& h);
|
||||
void <strong>set_file_hash</strong> (int index, sha1_hash const& h);
|
||||
void <strong>add_url_seed</strong> (std::string const& url);
|
||||
void <strong>add_http_seed</strong> (std::string const& url);
|
||||
void <strong>add_node</strong> (std::pair<std::string, int> const& node);
|
||||
void <strong>add_tracker</strong> (std::string const& url, int tier = 0);
|
||||
void <strong>set_root_cert</strong> (std::string const& 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<sha1_hash> const& <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& fs, int piece_size = 0
|
||||
, int pad_file_limit = -1, int flags = optimize, int alignment = -1);
|
||||
<strong>create_torrent</strong> (torrent_info const& 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& <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& 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& 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& url);
|
||||
void <strong>add_http_seed</strong> (std::string const& 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<std::string, int> const& 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& 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& 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<sha1_hash> const& <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 "<a class="reference external" href="../include/libtorrent/create_torrent.hpp">libtorrent/create_torrent.hpp</a>"</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 "<a class="reference external" href="../include/libtorrent/create_torrent.hpp">libtorrent/create_torrent.hpp</a>"</p>
|
||||
<pre class="literal-block">
|
||||
template <class Pred> void <strong>add_files</strong> (file_storage& fs, std::string const& file, Pred p, boost::uint32_t flags = 0);
|
||||
inline void <strong>add_files</strong> (file_storage& fs, std::string const& 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& 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 ".." 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 "<a class="reference external" href="../include/libtorrent/create_torrent.hpp">libtorrent/create_torrent.hpp</a>"</p>
|
||||
<pre class="literal-block">
|
||||
void <strong>set_piece_hashes</strong> (create_torrent& t, std::string const& p
|
||||
, boost::function<void(int)> f, error_code& ec);
|
||||
inline void <strong>set_piece_hashes</strong> (create_torrent& t, std::string const& p);
|
||||
inline void <strong>set_piece_hashes</strong> (create_torrent& t, std::string const& p, error_code& 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&</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>
|
|
@ -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@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@rasterbar.com">arvid@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& fs) : m_files(fs) {}
|
||||
void set_file_priority(std::vector<boost::uint8_t> const& 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<int, std::vector<char> >::const_iterator i = m_file_data.find(slot);
|
||||
if (i == m_file_data.end()) return 0;
|
||||
int available = i->second.size() - offset;
|
||||
if (available <= 0) return 0;
|
||||
if (available > size) available = size;
|
||||
memcpy(buf, &i->second[offset], available);
|
||||
return available;
|
||||
}
|
||||
virtual int write(const char* buf, int slot, int offset, int size)
|
||||
{
|
||||
std::vector<char>& data = m_file_data[slot];
|
||||
if (data.size() < offset + size) data.resize(offset + size);
|
||||
std::memcpy(&data[offset], buf, size);
|
||||
return size;
|
||||
}
|
||||
virtual bool rename_file(int file, std::string const& new_name)
|
||||
{ assert(false); return false; }
|
||||
virtual bool move_storage(std::string const& save_path) { return false; }
|
||||
virtual bool verify_resume_data(lazy_entry const& rd, error_code& error) { return false; }
|
||||
virtual bool write_resume_data(entry& 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& ph, int piece_size)
|
||||
{
|
||||
int left = piece_size - ph.offset;
|
||||
assert(left >= 0);
|
||||
if (left > 0)
|
||||
{
|
||||
std::vector<char>& 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() < piece_size) data.resize(piece_size, 0);
|
||||
ph.h.update(&data[ph.offset], left);
|
||||
}
|
||||
return ph.h.final();
|
||||
}
|
||||
virtual bool release_files() { return false; }
|
||||
virtual bool delete_files() { return false; }
|
||||
|
||||
std::map<int, std::vector<char> > m_file_data;
|
||||
file_storage m_files;
|
||||
};
|
||||
|
||||
storage_interface* temp_storage_constructor(
|
||||
file_storage const& fs, file_storage const* mapped
|
||||
, std::string const& path, file_pool& fp
|
||||
, std::vector<boost::uint8_t> const& 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 "<a class="reference external" href="../include/libtorrent/file_pool.hpp">libtorrent/file_pool.hpp</a>"</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<file> <strong>open_file</strong> (void* st, std::string const& p
|
||||
, int file_index, file_storage const& fs, int m, error_code& 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<file> <strong>open_file</strong> (void* st, std::string const& p
|
||||
, int file_index, file_storage const& fs, int m, error_code& 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 "<a class="reference external" href="../include/libtorrent/storage.hpp">libtorrent/storage.hpp</a>"</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<boost::uint8_t> const& 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& save_path, int flags) = 0;
|
||||
virtual bool <strong>verify_resume_data</strong> (lazy_entry const& rd, error_code& error) = 0;
|
||||
virtual bool <strong>write_resume_data</strong> (entry& 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& new_filename) = 0;
|
||||
virtual bool <strong>delete_files</strong> () = 0;
|
||||
disk_buffer_pool* <strong>disk_pool</strong> ();
|
||||
session_settings const& <strong>settings</strong> () const;
|
||||
void <strong>set_error</strong> (std::string const& file, error_code const& ec) const;
|
||||
error_code const& <strong>error</strong> () const;
|
||||
std::string const& <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<boost::uint8_t> const& 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& 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& rd, error_code& 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& 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& 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& <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& file, error_code const& 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& <strong>error</strong> () const;
|
||||
std::string const& <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 "<a class="reference external" href="../include/libtorrent/storage.hpp">libtorrent/storage.hpp</a>"</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& fs, file_storage const* mapped
|
||||
, std::string const& path, file_pool& fp
|
||||
, std::vector<boost::uint8_t> const& 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& new_filename);
|
||||
void <strong>set_file_priority</strong> (std::vector<boost::uint8_t> const& prio);
|
||||
bool <strong>has_any_file</strong> ();
|
||||
int <strong>move_storage</strong> (std::string const& save_path, int flags);
|
||||
bool <strong>write_resume_data</strong> (entry& 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& rd, error_code& 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& <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& fs, file_storage const* mapped
|
||||
, std::string const& path, file_pool& fp
|
||||
, std::vector<boost::uint8_t> const& 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& <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 "<a class="reference external" href="../include/libtorrent/storage.hpp">libtorrent/storage.hpp</a>"</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>
|
|
@ -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@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@rasterbar.com">arvid@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 "<a class="reference external" href="../include/libtorrent/ip_filter.hpp">libtorrent/ip_filter.hpp</a>"</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& 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() && 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& 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 "<a class="reference external" href="../include/libtorrent/ip_filter.hpp">libtorrent/ip_filter.hpp</a>"</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 "<a class="reference external" href="../include/libtorrent/ip_filter.hpp">libtorrent/ip_filter.hpp</a>"</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 "<a class="reference external" href="../include/libtorrent/ip_filter.hpp">libtorrent/ip_filter.hpp</a>"</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>
|
|
@ -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@rasterbar.com">arvid@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"><libtorrent/extensions.hpp></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<torrent_plugin> (*)(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<torrent_plugin></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><unique alert ID></em>;
|
||||
virtual int type() const { return alert_type; }
|
||||
|
||||
virtual std::string message() const;
|
||||
|
||||
virtual std::auto_ptr<alert> clone() const
|
||||
{ return std::auto_ptr<alert>(new name(*this)); }
|
||||
|
||||
const static int static_category = <em><bitmask of alert::category_t flags></em>;
|
||||
virtual int category() const { return static_category; }
|
||||
|
||||
virtual char const* what() const { return <em><string literal of the name of this alert></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 "<a class="reference external" href="../include/libtorrent/extensions.hpp">libtorrent/extensions.hpp</a>"</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<torrent_plugin> <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<policy::peer*>& <em>/* peers */</em>);
|
||||
virtual void <strong>save_state</strong> (entry&) const;
|
||||
virtual void <strong>load_state</strong> (lazy_entry const&);
|
||||
};
|
||||
</pre>
|
||||
<a name="new_torrent()"></a><div class="section" id="new-torrent">
|
||||
<h3>new_torrent()</h3>
|
||||
<pre class="literal-block">
|
||||
virtual boost::shared_ptr<torrent_plugin> <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<policy::peer*>& <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&) 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&);
|
||||
</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 "<a class="reference external" href="../include/libtorrent/extensions.hpp">libtorrent/extensions.hpp</a>"</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<peer_plugin> <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&,
|
||||
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<peer_plugin> <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&,
|
||||
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 "<a class="reference external" href="../include/libtorrent/extensions.hpp">libtorrent/extensions.hpp</a>"</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&);
|
||||
virtual void <strong>on_disconnect</strong> (error_code const& <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&);
|
||||
virtual bool <strong>on_have</strong> (int <em>/*index*/</em>);
|
||||
virtual bool <strong>on_bitfield</strong> (bitfield const& <em>/*bitfield*/</em>);
|
||||
virtual bool <strong>on_have_all</strong> ();
|
||||
virtual bool <strong>on_reject</strong> (peer_request const&);
|
||||
virtual bool <strong>on_request</strong> (peer_request const&);
|
||||
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& <em>/*piece*/</em>
|
||||
, disk_buffer_holder& <em>/*data*/</em>);
|
||||
virtual bool <strong>on_suggest</strong> (int <em>/*index*/</em>);
|
||||
virtual bool <strong>on_cancel</strong> (peer_request const&);
|
||||
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& <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&);
|
||||
};
|
||||
</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&);
|
||||
</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& <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&);
|
||||
</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& <em>/*bitfield*/</em>);
|
||||
virtual bool <strong>on_have_all</strong> ();
|
||||
virtual bool <strong>on_reject</strong> (peer_request const&);
|
||||
virtual bool <strong>on_request</strong> (peer_request const&);
|
||||
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& <em>/*piece*/</em>
|
||||
, disk_buffer_holder& <em>/*data*/</em>);
|
||||
virtual bool <strong>on_suggest</strong> (int <em>/*index*/</em>);
|
||||
virtual bool <strong>on_cancel</strong> (peer_request const&);
|
||||
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& <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&);
|
||||
</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 "<a class="reference external" href="../include/libtorrent/extensions/lt_trackers.hpp">libtorrent/extensions/lt_trackers.hpp</a>"</p>
|
||||
<pre class="literal-block">
|
||||
boost::shared_ptr<torrent_plugin> <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 "<a class="reference external" href="../include/libtorrent/extensions/smart_ban.hpp">libtorrent/extensions/smart_ban.hpp</a>"</p>
|
||||
<pre class="literal-block">
|
||||
boost::shared_ptr<torrent_plugin> <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 "<a class="reference external" href="../include/libtorrent/extensions/ut_metadata.hpp">libtorrent/extensions/ut_metadata.hpp</a>"</p>
|
||||
<pre class="literal-block">
|
||||
boost::shared_ptr<torrent_plugin> <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 "<a class="reference external" href="../include/libtorrent/extensions/ut_pex.hpp">libtorrent/extensions/ut_pex.hpp</a>"</p>
|
||||
<pre class="literal-block">
|
||||
boost::shared_ptr<torrent_plugin> <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>
|
|
@ -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@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@rasterbar.com">arvid@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 "<a class="reference external" href="../include/libtorrent/rss.hpp">libtorrent/rss.hpp</a>"</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 "<a class="reference external" href="../include/libtorrent/rss.hpp">libtorrent/rss.hpp</a>"</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"><ttl></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 "<a class="reference external" href="../include/libtorrent/rss.hpp">libtorrent/rss.hpp</a>"</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<feed_item> 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 "<a class="reference external" href="../include/libtorrent/rss.hpp">libtorrent/rss.hpp</a>"</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& 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& 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 "<a class="reference external" href="../include/libtorrent/rss.hpp">libtorrent/rss.hpp</a>"</p>
|
||||
<pre class="literal-block">
|
||||
torrent_handle <strong>add_feed_item</strong> (session& s, feed_item const& fi
|
||||
, add_torrent_params const& p);
|
||||
torrent_handle <strong>add_feed_item</strong> (session& s, feed_item const& fi
|
||||
, add_torrent_params const& p, error_code& 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 "<a class="reference external" href="../include/libtorrent/rss.hpp">libtorrent/rss.hpp</a>"</p>
|
||||
<pre class="literal-block">
|
||||
boost::shared_ptr<feed> <strong>new_feed</strong> (aux::session_impl& ses, feed_settings const& sett);
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -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@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@rasterbar.com">arvid@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 "<a class="reference external" href="../include/libtorrent/file_storage.hpp">libtorrent/file_storage.hpp</a>"</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 "unselected" 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 "<a class="reference external" href="../include/libtorrent/file_storage.hpp">libtorrent/file_storage.hpp</a>"</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 "<a class="reference external" href="../include/libtorrent/file_storage.hpp">libtorrent/file_storage.hpp</a>"</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& p, size_type size, int flags = 0
|
||||
, std::time_t mtime = 0, std::string const& s_p = "");
|
||||
void <strong>add_file</strong> (file_entry const& e, char const* filehash = 0);
|
||||
void <strong>rename_file</strong> (int index, std::string const& new_filename);
|
||||
void <strong>rename_file_borrow</strong> (int index, char const* new_filename, int len);
|
||||
std::vector<file_slice> <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& n);
|
||||
const std::string& <strong>name</strong> () const;
|
||||
void <strong>swap</strong> (file_storage& 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& <strong>symlink</strong> (int index) const;
|
||||
std::string <strong>file_path</strong> (int index, std::string const& save_path = "") 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& p, size_type size, int flags = 0
|
||||
, std::time_t mtime = 0, std::string const& s_p = "");
|
||||
void <strong>add_file</strong> (file_entry const& 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& 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<file_slice> <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& n);
|
||||
const std::string& <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& 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 >= 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& <strong>symlink</strong> (int index) const;
|
||||
std::string <strong>file_path</strong> (int index, std::string const& save_path = "") 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 "<a class="reference external" href="../include/libtorrent/file_storage.hpp">libtorrent/file_storage.hpp</a>"</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 "<a class="reference external" href="../include/libtorrent/file_storage.hpp">libtorrent/file_storage.hpp</a>"</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 "<a class="reference external" href="../include/libtorrent/storage_defs.hpp">libtorrent/storage_defs.hpp</a>"</p>
|
||||
<pre class="literal-block">
|
||||
storage_interface* <strong>default_storage_constructor</strong> (
|
||||
file_storage const&, file_storage const* mapped, std::string const&, file_pool&
|
||||
, std::vector<boost::uint8_t> const&);
|
||||
</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 "<a class="reference external" href="../include/libtorrent/storage_defs.hpp">libtorrent/storage_defs.hpp</a>"</p>
|
||||
<pre class="literal-block">
|
||||
storage_interface* <strong>disabled_storage_constructor</strong> (
|
||||
file_storage const&, file_storage const* mapped, std::string const&, file_pool&
|
||||
, std::vector<boost::uint8_t> const&);
|
||||
</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 "<a class="reference external" href="../include/libtorrent/storage_defs.hpp">libtorrent/storage_defs.hpp</a>"</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>
|
|
@ -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@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@rasterbar.com">arvid@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 "<a class="reference external" href="../include/libtorrent/escape_string.hpp">libtorrent/escape_string.hpp</a>"</p>
|
||||
<pre class="literal-block">
|
||||
std::string <strong>to_hex</strong> (std::string const& 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 "<a class="reference external" href="../include/libtorrent/escape_string.hpp">libtorrent/escape_string.hpp</a>"</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 "<a class="reference external" href="../include/libtorrent/escape_string.hpp">libtorrent/escape_string.hpp</a>"</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 "<a class="reference external" href="../include/libtorrent/string_util.hpp">libtorrent/string_util.hpp</a>"</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 "<a class="reference external" href="../include/libtorrent/utf8.hpp">libtorrent/utf8.hpp</a>"</p>
|
||||
<pre class="literal-block">
|
||||
utf8_conv_result_t <strong>wchar_utf8</strong> (
|
||||
const std::wstring &wide, std::string &utf8);
|
||||
utf8_conv_result_t <strong>utf8_wchar</strong> (
|
||||
const std::string &utf8, std::wstring &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 "<a class="reference external" href="../include/libtorrent/utf8.hpp">libtorrent/utf8.hpp</a>"</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>
|
|
@ -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@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@rasterbar.com">arvid@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 "<a class="reference external" href="../include/libtorrent/ptime.hpp">libtorrent/ptime.hpp</a>"</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& <strong>operator-=</strong> (time_duration const& c);
|
||||
time_duration <strong>operator+</strong> (time_duration const& c);
|
||||
time_duration& <strong>operator+=</strong> (time_duration const& 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& c);
|
||||
time_duration& <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& <strong>operator-=</strong> (time_duration const& c);
|
||||
time_duration <strong>operator+</strong> (time_duration const& c);
|
||||
time_duration& <strong>operator+=</strong> (time_duration const& 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& c);
|
||||
time_duration& <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 "<a class="reference external" href="../include/libtorrent/ptime.hpp">libtorrent/ptime.hpp</a>"</p>
|
||||
<p>This type represents a point in time.</p>
|
||||
<pre class="literal-block">
|
||||
struct ptime
|
||||
{
|
||||
ptime& <strong>operator-=</strong> (time_duration rhs);
|
||||
ptime& <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& <strong>operator-=</strong> (time_duration rhs);
|
||||
ptime& <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 "<a class="reference external" href="../include/libtorrent/ptime.hpp">libtorrent/ptime.hpp</a>"</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>=() operator!=() operator>() operator<() operator==() operator+() operator<=() operator-()</h2>
|
||||
<p>Declared in "<a class="reference external" href="../include/libtorrent/ptime.hpp">libtorrent/ptime.hpp</a>"</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<=</strong> (time_duration lhs, time_duration rhs);
|
||||
inline bool <strong>operator==</strong> (ptime lhs, ptime rhs);
|
||||
inline bool <strong>operator>=</strong> (time_duration lhs, time_duration rhs);
|
||||
inline bool <strong>operator<</strong> (time_duration lhs, time_duration rhs);
|
||||
inline bool <strong>operator></strong> (time_duration lhs, time_duration rhs);
|
||||
inline bool <strong>operator></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<=</strong> (ptime lhs, ptime rhs);
|
||||
inline bool <strong>operator!=</strong> (ptime lhs, ptime rhs);
|
||||
inline bool <strong>operator<</strong> (ptime lhs, ptime rhs);
|
||||
inline bool <strong>operator>=</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 "<a class="reference external" href="../include/libtorrent/time.hpp">libtorrent/time.hpp</a>"</p>
|
||||
<pre class="literal-block">
|
||||
ptime const& <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 "<a class="reference external" href="../include/libtorrent/time.hpp">libtorrent/time.hpp</a>"</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 "<a class="reference external" href="../include/libtorrent/time.hpp">libtorrent/time.hpp</a>"</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 "<a class="reference external" href="../include/libtorrent/time.hpp">libtorrent/time.hpp</a>"</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 "<a class="reference external" href="../include/libtorrent/time.hpp">libtorrent/time.hpp</a>"</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>
|
|
@ -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@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@rasterbar.com">arvid@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 "<a class="reference external" href="../include/libtorrent/bitfield.hpp">libtorrent/bitfield.hpp</a>"</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& rhs);
|
||||
<strong>bitfield</strong> (bitfield&& 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& <strong>operator=</strong> (bitfield const& 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& rhs);
|
||||
<strong>bitfield</strong> (bitfield&& 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& <strong>operator=</strong> (bitfield const& 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 "<a class="reference external" href="../include/libtorrent/sha1_hash.hpp">libtorrent/sha1_hash.hpp</a>"</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& s);
|
||||
void <strong>assign</strong> (std::string const& s);
|
||||
void <strong>clear</strong> ();
|
||||
bool <strong>is_all_zeros</strong> () const;
|
||||
sha1_hash& <strong>operator<<=</strong> (int n);
|
||||
sha1_hash& <strong>operator>>=</strong> (int n);
|
||||
bool <strong>operator!=</strong> (sha1_hash const& n) const;
|
||||
bool <strong>operator<</strong> (sha1_hash const& n) const;
|
||||
bool <strong>operator==</strong> (sha1_hash const& n) const;
|
||||
sha1_hash <strong>operator~</strong> ();
|
||||
sha1_hash <strong>operator^</strong> (sha1_hash const& n) const;
|
||||
sha1_hash& <strong>operator^=</strong> (sha1_hash const& n);
|
||||
sha1_hash <strong>operator&</strong> (sha1_hash const& n) const;
|
||||
sha1_hash& <strong>operator&=</strong> (sha1_hash const& n);
|
||||
sha1_hash& <strong>operator|=</strong> (sha1_hash const& n);
|
||||
unsigned char& <strong>operator[]</strong> (int i);
|
||||
unsigned char const& <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& s);
|
||||
void <strong>assign</strong> (std::string const& 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<<=()</h2>
|
||||
<pre class="literal-block">
|
||||
sha1_hash& <strong>operator<<=</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>>=()</h2>
|
||||
<pre class="literal-block">
|
||||
sha1_hash& <strong>operator>>=</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<() operator==()</h2>
|
||||
<pre class="literal-block">
|
||||
bool <strong>operator!=</strong> (sha1_hash const& n) const;
|
||||
bool <strong>operator<</strong> (sha1_hash const& n) const;
|
||||
bool <strong>operator==</strong> (sha1_hash const& 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& 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& <strong>operator^=</strong> (sha1_hash const& 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&()</h2>
|
||||
<pre class="literal-block">
|
||||
sha1_hash <strong>operator&</strong> (sha1_hash const& 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&=()</h2>
|
||||
<pre class="literal-block">
|
||||
sha1_hash& <strong>operator&=</strong> (sha1_hash const& 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& <strong>operator|=</strong> (sha1_hash const& 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& <strong>operator[]</strong> (int i);
|
||||
unsigned char const& <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 "<a class="reference external" href="../include/libtorrent/identify_client.hpp">libtorrent/identify_client.hpp</a>"</p>
|
||||
<pre class="literal-block">
|
||||
std::string <strong>identify_client</strong> (const peer_id& 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 "<a class="reference external" href="../include/libtorrent/identify_client.hpp">libtorrent/identify_client.hpp</a>"</p>
|
||||
<pre class="literal-block">
|
||||
boost::optional<fingerprint> <strong>client_fingerprint</strong> (peer_id const& 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<<()</h2>
|
||||
<p>Declared in "<a class="reference external" href="../include/libtorrent/sha1_hash.hpp">libtorrent/sha1_hash.hpp</a>"</p>
|
||||
<pre class="literal-block">
|
||||
inline std::ostream& <strong>operator<<</strong> (std::ostream& os, sha1_hash const& 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>>()</h2>
|
||||
<p>Declared in "<a class="reference external" href="../include/libtorrent/sha1_hash.hpp">libtorrent/sha1_hash.hpp</a>"</p>
|
||||
<pre class="literal-block">
|
||||
inline std::istream& <strong>operator>></strong> (std::istream& is, sha1_hash& 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 "<a class="reference external" href="../include/libtorrent/thread.hpp">libtorrent/thread.hpp</a>"</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>
|
|
@ -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>=()">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>()">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==()">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<=()">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#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<<()">operator<<()</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<<()">operator<<()</a></div>
|
||||
<div class="line"><a class="reference external" href="reference-Utility.html#operator>>()">operator>>()</a></div>
|
||||
<div class="line"><a class="reference external" href="reference-Utility.html#sleep()">sleep()</a></div>
|
||||
</div>
|
||||
</div></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -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
|
||||
|
3505
docs/todo.html
Before Width: | Height: | Size: 488 KiB After Width: | Height: | Size: 272 KiB |
|
@ -49,7 +49,7 @@
|
|||
<tr><th class="docinfo-name">Author:</th>
|
||||
<td>Arvid Norberg, <a class="last reference external" href="mailto:arvid@rasterbar.com">arvid@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>
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
<tr><th class="docinfo-name">Author:</th>
|
||||
<td>Arvid Norberg, <a class="last reference external" href="mailto:arvid@rasterbar.com">arvid@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">
|
||||
|
|
|
@ -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
|
||||
|
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 14 KiB |
|
@ -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>. ;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
@ -861,17 +965,19 @@ int main(int argc, char* argv[])
|
|||
fprintf(stderr, "ERROR LOADING .TORRENT: %s\n", ec.message().c_str());
|
||||
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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
if resource.getrlimit(resource.RLIMIT_NOFILE)[0] < 4000:
|
||||
print 'please set ulimit -n to at least 4000'
|
||||
sys.exit(1)
|
||||
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
|
||||
|
||||
global test_duration
|
||||
if config['build'] == 'utorrent':
|
||||
try: os.mkdir('utorrent_session')
|
||||
except: pass
|
||||
cfg = open('utorrent_session/settings.dat', 'w+')
|
||||
|
||||
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'])
|
||||
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'
|
||||
|
||||
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
|
||||
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)
|
||||
if config['build'] != 'rtorrent' and config['build'] != 'utorrent':
|
||||
print >>client.stdin, 'x',
|
||||
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 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)
|
||||
run_test(config)
|
||||
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 b in builds:
|
||||
for test in ['upload', 'download']:
|
||||
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)
|
||||
run_test(config)
|
||||
for test in ['upload', 'download']:
|
||||
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)
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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();
|
||||
|
|
|
@ -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')
|
||||
|
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
@ -1868,6 +1909,49 @@ namespace libtorrent
|
|||
// by the torrent_handle or hashed by it, for efficient updates.
|
||||
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
|
||||
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#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;
|
||||
}
|
||||
|
||||
int rest = m_size - num_bytes * 8;
|
||||
for (int i = 0; i < rest; ++i)
|
||||
{
|
||||
ret += (m_bytes[num_bytes] >> (7-i)) & 1;
|
||||
}
|
||||
TORRENT_ASSERT(ret <= m_size);
|
||||
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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|