Merge branch 'develop' of openspace.itn.liu.se:/openspace into develop

This commit is contained in:
Anton Arbring
2015-06-25 20:29:27 -04:00
348 changed files with 144886 additions and 1330 deletions

View File

@@ -43,10 +43,7 @@ set_build_output_directories()
configure_openspace_version(0 1 0 "prerelease-5")
option(OPENSPACE_WARNINGS_AS_ERRORS "Treat warnings as errors" OFF)
option(OPENSPACE_DISABLE_EXTERNAL_WARNINGS "Disable warnings in external libraries" ON)
option(OPENSPACE_BUILD_GUI_APPLICATIONS "Build GUI Applications" OFF)
include(src/CMakeLists.txt)
create_openspace_target()

View File

@@ -25,24 +25,32 @@
set(APPLICATION_NAME Launcher)
set(APPLICATION_LINK_TO_OPENSPACE ON)
include (${OPENSPACE_CMAKE_EXT_DIR}/handle_external_library.cmake)
set(application_path ${OPENSPACE_APPS_DIR}/Launcher)
set(SOURCE_FILES
${OPENSPACE_APPS_DIR}/Launcher/main.cpp
${OPENSPACE_APPS_DIR}/Launcher/mainwindow.cpp
${OPENSPACE_APPS_DIR}/Launcher/shortcutwidget.cpp
${OPENSPACE_APPS_DIR}/Launcher/syncwidget.cpp
${application_path}/main.cpp
${application_path}/infowidget.cpp
${application_path}/mainwindow.cpp
${application_path}/shortcutwidget.cpp
${application_path}/syncwidget.cpp
)
set(HEADER_FILES
${OPENSPACE_APPS_DIR}/Launcher/mainwindow.h
${OPENSPACE_APPS_DIR}/Launcher/shortcutwidget.h
${OPENSPACE_APPS_DIR}/Launcher/syncwidget.h
${application_path}/infowidget.h
${application_path}/mainwindow.h
${application_path}/shortcutwidget.h
${application_path}/syncwidget.h
)
find_package(Qt5Widgets)
find_package(Qt5Network)
set(MOC_FILES "")
qt5_wrap_cpp(MOC_FILES ${HEADER_FILES})
qt5_add_resources(RESOURCE_FILES ${OPENSPACE_APPS_DIR}/Launcher/files.qrc)
set(RESOURCE_FILES "")
qt5_add_resources(RESOURCE_FILES ${application_path}/files.qrc)
add_executable(${APPLICATION_NAME} MACOSX_BUNDLE
${SOURCE_FILES}
@@ -57,8 +65,12 @@ target_link_libraries(${APPLICATION_NAME}
)
if (APPLE)
INSTALL(CODE "
include(BundleUtilities)
fixup_bundle(\"/Users/alex/Development/OpenSpace/bin/openspace/Debug/Launcher.app/Contents/MacOS/Launcher\" \"/Users/alex/Development/OpenSpace/bin/openspace/Debug/TimelineView.app/Contents/plugins/platforms/libqcocoa.dylib\" \"\")
" COMPONENT Runtime)
INSTALL(CODE "
include(BundleUtilities)
fixup_bundle(\"/Users/alex/Development/OpenSpace/bin/openspace/Debug/Launcher.app/Contents/MacOS/Launcher\" \"/Users/alex/Development/OpenSpace/bin/openspace/Debug/TimelineView.app/Contents/plugins/platforms/libqcocoa.dylib\" \"\")
" COMPONENT Runtime)
endif ()
# Libtorrent
include_external_library(${APPLICATION_NAME} libtorrent ${application_path}/ext/libtorrent)
target_include_directories(${APPLICATION_NAME} PUBLIC SYSTEM ${application_path}/ext/libtorrent/include)

View File

@@ -0,0 +1,26 @@
Written by Arvid Norberg. Copyright (c) 2003-2014
Contributions by:
Andrei Kurushin
Steven Siloti
Thomas Fischer
Massaroddel
Tianhao Qiu.
Shyam
Magnus Jonsson
Daniel Wallin
Cory Nelson
Stas Khirman
Ryan Norton
Andrew Resch
Building and maintainance of the autotools scripts:
Michael Wojciechowski
Peter Koeleman
Thanks to Reimond Retz for bugfixes, suggestions and testing
Thanks to University of UmeŒ for providing development and test hardware.
Project is hosted by sourceforge.

View File

@@ -0,0 +1,239 @@
cmake_minimum_required(VERSION 2.6)
project(libtorrent)
set (SOVERSION "8")
set (VERSION "1.0.5")
set(sources
web_connection_base
alert
alert_manager
allocator
asio
assert
bandwidth_limit
bandwidth_manager
bandwidth_queue_entry
bloom_filter
chained_buffer
connection_queue
create_torrent
disk_buffer_holder
entry
error_code
file_storage
lazy_bdecode
escape_string
string_util
file
gzip
hasher
http_connection
http_stream
http_parser
i2p_stream
identify_client
ip_filter
ip_voter
peer_connection
bt_peer_connection
web_peer_connection
http_seed_connection
instantiate_connection
natpmp
packet_buffer
piece_picker
policy
puff
random
rss
session
session_impl
settings
socket_io
socket_type
socks5_stream
stat
storage
time
timestamp_history
torrent
torrent_handle
torrent_info
tracker_manager
http_tracker_connection
utf8
udp_tracker_connection
udp_socket
upnp
utp_socket_manager
utp_stream
logger
file_pool
lsd
disk_buffer_pool
disk_io_thread
enum_net
broadcast_socket
magnet_uri
parse_url
ConvertUTF
thread
xml_parse
# -- extensions --
metadata_transfer
ut_pex
ut_metadata
smart_ban
lt_trackers
)
# -- kademlia --
set(kademlia_sources
dht_tracker
node
refresh
rpc_manager
find_data
node_id
routing_table
traversal_algorithm
logging
item
get_peers
get_item
)
# -- ed25519 --
set(ed25519_sources
add_scalar
fe
ge
key_exchange
keypair
sc
seed
sha512
sign
verify
)
set(includes include ed25519/src)
option(LIBTORRENT_pool-allocators "Uses a pool allocator for disk and piece buffers" ON)
option(LIBTORRENT_dht "enable support for Mainline DHT" OFF)
option(LIBTORRENT_unicode "enable unicode support" ON)
set(CMAKE_CONFIGURATION_TYPES Debug Release RelWithDebInfo)
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release FORCE)
endif ()
# add_definitions() doesn't seem to let you say wich build type to apply it to
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DTORRENT_DEBUG")
if (UNIX)
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-Os -g")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
endif ()
list(APPEND sources sha1)
foreach(s ${sources})
list(APPEND sources2 src/${s})
endforeach ()
if (LIBTORRENT_dht)
foreach(s ${kademlia_sources})
list(APPEND sources2 src/kademlia/${s})
endforeach(s)
foreach(s ${ed25519_sources})
list(APPEND sources2 ed25519/src/${s})
endforeach(s)
endif ()
add_library(libtorrent STATIC ${sources2})
target_include_directories(libtorrent PUBLIC ${includes})
target_compile_definitions(libtorrent PUBLIC
TORRENT_DISABLE_ENCRYPTION
TORRENT_DISABLE_RESOLVE_COUNTRIES
TORRENT_DISABLE_GEO_IP
BOOST_ASIO_SEPARATE_COMPILATION
BOOST_EXCEPTION_DISABLE
BOOST_ASIO_ENABLE_CANCELIO
_FILE_OFFSET_BITS=64
)
if (NOT LIBTORRENT_dht)
target_compile_definitions(libtorrent PUBLIC TORRENT_DISABLE_DHT)
endif ()
if (NOT LIBTORRENT_pool-allocators)
target_compile_definitions(libtorrent PUBLIC TORRENT_DISABLE_POOL_ALLOCATOR)
endif()
if (LIBTORRENT_unicode)
add_definitions(-DUNICODE -D_UNICODE)
endif()
if (NOT MSVC)
target_compile_options(libtorrent PUBLIC "-fvisibility=hidden" "-fvisibility-inlines-hidden")
# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden")
# set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -fvisibility-inlines-hidden")
endif ()
# Boost
set(Boost_USE_STATIC_LIBS ON)
if (NOT DEFINED Boost_INCLUDE_DIR OR NOT DEFINED Boost_LIBRARIES)
find_package(Boost COMPONENTS system thread date_time chrono)
endif ()
target_include_directories(libtorrent PUBLIC ${Boost_INCLUDE_DIR})
target_link_libraries(libtorrent ${Boost_LIBRARIES})
if (WIN32)
target_link_libraries(libtorrent wsock32 ws2_32 Iphlpapi.lib)
target_compile_definitions(libtorrent PUBLIC "_WIN32_WINNT=0x0600")
endif ()
# this works around a bug in asio in boost-1.39
#add_definitions(-DBOOST_ASIO_HASH_MAP_BUCKETS=1021 -D__USE_W32_SOCKETS -DWIN32_LEAN_AND_MEAN )
if (MSVC)
target_compile_options(libtorrent PUBLIC "/EHsc" "/Zc:wchar_t" "/Zc:forScope" "/MP")
target_compile_definitions(libtorrent PUBLIC _SCL_SECURE_NO_DEPRECATE _CRT_SECURE_NO_DEPRECATE)
else ()
target_compile_options(libtorrent PUBLIC "-fexceptions" "-Wno-c++11-extensions")
endif ()
if (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
target_compile_options(libtorrent PUBLIC "-fcolor-diagnostics")
endif ()
set_target_properties(libtorrent PROPERTIES
SOVERSION ${SOVERSION})
get_property(COMPILETIME_OPTIONS_LIST
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIRECTORY}
PROPERTY COMPILE_DEFINITIONS
)
foreach (s ${COMPILETIME_OPTIONS_LIST})
set (COMPILETIME_OPTIONS "${COMPILETIME_OPTIONS} -D${s}")
endforeach ()
configure_file(libtorrent-rasterbar-cmake.pc.in libtorrent-rasterbar.pc)
string (COMPARE EQUAL "${CMAKE_SIZEOF_VOID_P}" "8" IS64BITS)
if (IS64BITS AND RESPECTLIB64)
set(LIBDIR "lib64")
else()
set(LIBDIR "lib")
endif()
install(TARGETS libtorrent DESTINATION ${LIBDIR})
install(DIRECTORY include/libtorrent
DESTINATION include
PATTERN ".svn" EXCLUDE)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libtorrent-rasterbar.pc DESTINATION ${LIBDIR}/pkgconfig)

View File

@@ -0,0 +1,28 @@
Copyright (c) 2003-2014, 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 Rasterbar Software 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.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,103 @@
Copyright (c) 2003-2014, 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.
------------------------------------------------------------------------------
puff.c
Copyright (C) 2002, 2003 Mark Adler
For conditions of distribution and use, see copyright notice in puff.h
version 1.7, 3 Mar 2003
puff.c is a simple inflate written to be an unambiguous way to specify the
deflate format. It is not written for speed but rather simplicity. As a
side benefit, this code might actually be useful when small code is more
important than speed, such as bootstrap applications. For typical deflate
data, zlib's inflate() is about four times as fast as puff(). zlib's
inflate compiles to around 20K on my machine, whereas puff.c compiles to
around 4K on my machine (a PowerPC using GNU cc). If the faster decode()
function here is used, then puff() is only twice as slow as zlib's
inflate().
All dynamically allocated memory comes from the stack. The stack required
is less than 2K bytes. This code is compatible with 16-bit int's and
assumes that long's are at least 32 bits. puff.c uses the short data type,
assumed to be 16 bits, for arrays in order to to conserve memory. The code
works whether integers are stored big endian or little endian.
In the comments below are "Format notes" that describe the inflate process
and document some of the less obvious aspects of the format. This source
code is meant to supplement RFC 1951, which formally describes the deflate
format:
http://www.zlib.org/rfc-deflate.html
------------------------------------------------------------------------------
GeoIP.c
Copyright (C) 2006 MaxMind LLC
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
------------------------------------------------------------------------------
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1 @@
See ChangeLog

View File

@@ -0,0 +1,16 @@
libtorrent is an open source C++ library implementing the BitTorrent protocol,
along with most popular extensions, making it suitable for real world
deployment. It is configurable to be able to fit both servers and embedded
devices.
The main goals of libtorrent are to be efficient and easy to use.
See docs/index.html for more detailed build and usage instructions.
To build with boost-build, run:
b2
See docs/building.html for more details on how to build and which configuration
options are available.

View File

@@ -0,0 +1,165 @@
Ed25519
=======
This is a portable implementation of [Ed25519](http://ed25519.cr.yp.to/) based
on the SUPERCOP "ref10" implementation. Additionally there is key exchanging
and scalar addition included to further aid building a PKI using Ed25519. All
code is in the public domain.
All code is pure ANSI C without any dependencies, except for the random seed
generation which uses standard OS cryptography APIs (`CryptGenRandom` on
Windows, `/dev/urandom` on nix). If you wish to be entirely portable define
`ED25519_NO_SEED`. This disables the `ed25519_create_seed` function, so if your
application requires key generation you must supply your own seeding function
(which is simply a 256 bit (32 byte) cryptographic random number generator).
Performance
-----------
On a Windows machine with an Intel Pentium B970 @ 2.3GHz I got the following
speeds (running on only one a single core):
Seed generation: 64us (15625 per second)
Key generation: 88us (11364 per second)
Message signing (short message): 87us (11494 per second)
Message verifying (short message): 228us (4386 per second)
Scalar addition: 100us (10000 per second)
Key exchange: 220us (4545 per second)
The speeds on other machines may vary. Sign/verify times will be higher with
longer messages. The implementation significantly benefits from 64 bit
architectures, if possible compile as 64 bit.
Usage
-----
Simply add all .c and .h files in the `src/` folder to your project and include
`ed25519.h` in any file you want to use the API. If you prefer to use a shared
library, only copy `ed25519.h` and define `ED25519_DLL` before importing. A
windows DLL is pre-built.
There are no defined types for seeds, private keys, public keys, shared secrets
or signatures. Instead simple `unsigned char` buffers are used with the
following sizes:
```c
unsigned char seed[32];
unsigned char signature[64];
unsigned char public_key[32];
unsigned char private_key[64];
unsigned char scalar[32];
unsigned char shared_secret[32];
```
API
---
```c
int ed25519_create_seed(unsigned char *seed);
```
Creates a 32 byte random seed in `seed` for key generation. `seed` must be a
writable 32 byte buffer. Returns 0 on success, and nonzero on failure.
```c
void ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed);
```
Creates a new key pair from the given seed. `public_key` must be a writable 32
byte buffer, `private_key` must be a writable 64 byte buffer and `seed` must be
a 32 byte buffer.
```c
void ed25519_sign(unsigned char *signature,
const unsigned char *message, size_t message_len,
const unsigned char *public_key, const unsigned char *private_key);
```
Creates a signature of the given message with the given key pair. `signature`
must be a writable 64 byte buffer. `message` must have at least `message_len`
bytes to be read.
```c
int ed25519_verify(const unsigned char *signature,
const unsigned char *message, size_t message_len,
const unsigned char *public_key);
```
Verifies the signature on the given message using `public_key`. `signature`
must be a readable 64 byte buffer. `message` must have at least `message_len`
bytes to be read. Returns 1 if the signature matches, 0 otherwise.
```c
void ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key,
const unsigned char *scalar);
```
Adds `scalar` to the given key pair where scalar is a 32 byte buffer (possibly
generated with `ed25519_create_seed`), generating a new key pair. You can
calculate the public key sum without knowing the private key and vice versa by
passing in `NULL` for the key you don't know. This is useful for enforcing
randomness on a key pair by a third party while only knowing the public key,
among other things. Warning: the last bit of the scalar is ignored - if
comparing scalars make sure to clear it with `scalar[31] &= 127`.
```c
void ed25519_key_exchange(unsigned char *shared_secret,
const unsigned char *public_key, const unsigned char *private_key);
```
Performs a key exchange on the given public key and private key, producing a
shared secret. It is recommended to hash the shared secret before using it.
`shared_secret` must be a 32 byte writable buffer where the shared secret will
be stored.
Example
-------
```c
unsigned char seed[32], public_key[32], private_key[64], signature[64];
unsigned char other_public_key[32], other_private_key[64], shared_secret[32];
const unsigned char message[] = "TEST MESSAGE";
/* create a random seed, and a key pair out of that seed */
if (ed25519_create_seed(seed)) {
printf("error while generating seed\n");
exit(1);
}
ed25519_create_keypair(public_key, private_key, seed);
/* create signature on the message with the key pair */
ed25519_sign(signature, message, strlen(message), public_key, private_key);
/* verify the signature */
if (ed25519_verify(signature, message, strlen(message), public_key)) {
printf("valid signature\n");
} else {
printf("invalid signature\n");
}
/* create a dummy keypair to use for a key exchange, normally you'd only have
the public key and receive it through some communication channel */
if (ed25519_create_seed(seed)) {
printf("error while generating seed\n");
exit(1);
}
ed25519_create_keypair(other_public_key, other_private_key, seed);
/* do a key exchange with other_public_key */
ed25519_key_exchange(shared_secret, other_public_key, private_key);
/*
the magic here is that ed25519_key_exchange(shared_secret, public_key,
other_private_key); would result in the same shared_secret
*/
```
License
-------
All code is in the public domain.

View File

@@ -0,0 +1,56 @@
#include "libtorrent/ed25519.hpp"
#include "ge.h"
#include "sc.h"
/* see http://crypto.stackexchange.com/a/6215/4697 */
void ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar) {
const unsigned char SC_1[32] = {1}; /* scalar with value 1 */
unsigned char n[32];
ge_p3 nB;
ge_p1p1 A_p1p1;
ge_p3 A;
ge_p3 public_key_unpacked;
ge_cached T;
int i;
/* copy the scalar and clear highest bit */
for (i = 0; i < 31; ++i) {
n[i] = scalar[i];
}
n[31] = scalar[31] & 127;
/* private key: a = n + t */
if (private_key) {
sc_muladd(private_key, SC_1, n, private_key);
}
/* public key: A = nB + T */
if (public_key) {
/* if we know the private key we don't need a point addition, which is faster */
/* using a "timing attack" you could find out wether or not we know the private
key, but this information seems rather useless - if this is important pass
public_key and private_key seperately in 2 function calls */
if (private_key) {
ge_scalarmult_base(&A, private_key);
} else {
/* unpack public key into T */
ge_frombytes_negate_vartime(&public_key_unpacked, public_key);
fe_neg(public_key_unpacked.X, public_key_unpacked.X); // undo negate
fe_neg(public_key_unpacked.T, public_key_unpacked.T); // undo negate
ge_p3_to_cached(&T, &public_key_unpacked);
/* calculate n*B */
ge_scalarmult_base(&nB, n);
/* A = n*B + T */
ge_add(&A_p1p1, &nB, &T);
ge_p1p1_to_p3(&A, &A_p1p1);
}
/* pack public key */
ge_p3_tobytes(public_key, &A);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,41 @@
#ifndef FE_H
#define FE_H
#include "fixedint.h"
/*
fe means field element.
Here the field is \Z/(2^255-19).
An element t, entries t[0]...t[9], represents the integer
t[0]+2^26 t[1]+2^51 t[2]+2^77 t[3]+2^102 t[4]+...+2^230 t[9].
Bounds on each t[i] vary depending on context.
*/
typedef int32_t fe[10];
void fe_0(fe h);
void fe_1(fe h);
void fe_frombytes(fe h, const unsigned char *s);
void fe_tobytes(unsigned char *s, const fe h);
void fe_copy(fe h, const fe f);
int fe_isnegative(const fe f);
int fe_isnonzero(const fe f);
void fe_cmov(fe f, const fe g, unsigned int b);
void fe_cswap(fe f, fe g, unsigned int b);
void fe_neg(fe h, const fe f);
void fe_add(fe h, const fe f, const fe g);
void fe_invert(fe out, const fe z);
void fe_sq(fe h, const fe f);
void fe_sq2(fe h, const fe f);
void fe_mul(fe h, const fe f, const fe g);
void fe_mul121666(fe h, fe f);
void fe_pow22523(fe out, const fe z);
void fe_sub(fe h, const fe f, const fe g);
#endif

View File

@@ -0,0 +1,6 @@
#include <boost/cstdint.hpp>
using boost::uint64_t;
using boost::int64_t;
using boost::int32_t;

View File

@@ -0,0 +1,467 @@
#include "ge.h"
#include "precomp_data.h"
/*
r = p + q
*/
void ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) {
fe t0;
fe_add(r->X, p->Y, p->X);
fe_sub(r->Y, p->Y, p->X);
fe_mul(r->Z, r->X, q->YplusX);
fe_mul(r->Y, r->Y, q->YminusX);
fe_mul(r->T, q->T2d, p->T);
fe_mul(r->X, p->Z, q->Z);
fe_add(t0, r->X, r->X);
fe_sub(r->X, r->Z, r->Y);
fe_add(r->Y, r->Z, r->Y);
fe_add(r->Z, t0, r->T);
fe_sub(r->T, t0, r->T);
}
static void slide(signed char *r, const unsigned char *a) {
int i;
int b;
int k;
for (i = 0; i < 256; ++i) {
r[i] = 1 & (a[i >> 3] >> (i & 7));
}
for (i = 0; i < 256; ++i)
if (r[i]) {
for (b = 1; b <= 6 && i + b < 256; ++b) {
if (r[i + b]) {
if (r[i] + (r[i + b] << b) <= 15) {
r[i] += r[i + b] << b;
r[i + b] = 0;
} else if (r[i] - (r[i + b] << b) >= -15) {
r[i] -= r[i + b] << b;
for (k = i + b; k < 256; ++k) {
if (!r[k]) {
r[k] = 1;
break;
}
r[k] = 0;
}
} else {
break;
}
}
}
}
}
/*
r = a * A + b * B
where a = a[0]+256*a[1]+...+256^31 a[31].
and b = b[0]+256*b[1]+...+256^31 b[31].
B is the Ed25519 base point (x,4/5) with x positive.
*/
void ge_double_scalarmult_vartime(ge_p2 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b) {
signed char aslide[256];
signed char bslide[256];
ge_cached Ai[8]; /* A,3A,5A,7A,9A,11A,13A,15A */
ge_p1p1 t;
ge_p3 u;
ge_p3 A2;
int i;
slide(aslide, a);
slide(bslide, b);
ge_p3_to_cached(&Ai[0], A);
ge_p3_dbl(&t, A);
ge_p1p1_to_p3(&A2, &t);
ge_add(&t, &A2, &Ai[0]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[1], &u);
ge_add(&t, &A2, &Ai[1]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[2], &u);
ge_add(&t, &A2, &Ai[2]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[3], &u);
ge_add(&t, &A2, &Ai[3]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[4], &u);
ge_add(&t, &A2, &Ai[4]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[5], &u);
ge_add(&t, &A2, &Ai[5]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[6], &u);
ge_add(&t, &A2, &Ai[6]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[7], &u);
ge_p2_0(r);
for (i = 255; i >= 0; --i) {
if (aslide[i] || bslide[i]) {
break;
}
}
for (; i >= 0; --i) {
ge_p2_dbl(&t, r);
if (aslide[i] > 0) {
ge_p1p1_to_p3(&u, &t);
ge_add(&t, &u, &Ai[aslide[i] / 2]);
} else if (aslide[i] < 0) {
ge_p1p1_to_p3(&u, &t);
ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]);
}
if (bslide[i] > 0) {
ge_p1p1_to_p3(&u, &t);
ge_madd(&t, &u, &Bi[bslide[i] / 2]);
} else if (bslide[i] < 0) {
ge_p1p1_to_p3(&u, &t);
ge_msub(&t, &u, &Bi[(-bslide[i]) / 2]);
}
ge_p1p1_to_p2(r, &t);
}
}
static const fe d = {
-10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116
};
static const fe sqrtm1 = {
-32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482
};
int ge_frombytes_negate_vartime(ge_p3 *h, const unsigned char *s) {
fe u;
fe v;
fe v3;
fe vxx;
fe check;
fe_frombytes(h->Y, s);
fe_1(h->Z);
fe_sq(u, h->Y);
fe_mul(v, u, d);
fe_sub(u, u, h->Z); /* u = y^2-1 */
fe_add(v, v, h->Z); /* v = dy^2+1 */
fe_sq(v3, v);
fe_mul(v3, v3, v); /* v3 = v^3 */
fe_sq(h->X, v3);
fe_mul(h->X, h->X, v);
fe_mul(h->X, h->X, u); /* x = uv^7 */
fe_pow22523(h->X, h->X); /* x = (uv^7)^((q-5)/8) */
fe_mul(h->X, h->X, v3);
fe_mul(h->X, h->X, u); /* x = uv^3(uv^7)^((q-5)/8) */
fe_sq(vxx, h->X);
fe_mul(vxx, vxx, v);
fe_sub(check, vxx, u); /* vx^2-u */
if (fe_isnonzero(check)) {
fe_add(check, vxx, u); /* vx^2+u */
if (fe_isnonzero(check)) {
return -1;
}
fe_mul(h->X, h->X, sqrtm1);
}
if (fe_isnegative(h->X) == (s[31] >> 7)) {
fe_neg(h->X, h->X);
}
fe_mul(h->T, h->X, h->Y);
return 0;
}
/*
r = p + q
*/
void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) {
fe t0;
fe_add(r->X, p->Y, p->X);
fe_sub(r->Y, p->Y, p->X);
fe_mul(r->Z, r->X, q->yplusx);
fe_mul(r->Y, r->Y, q->yminusx);
fe_mul(r->T, q->xy2d, p->T);
fe_add(t0, p->Z, p->Z);
fe_sub(r->X, r->Z, r->Y);
fe_add(r->Y, r->Z, r->Y);
fe_add(r->Z, t0, r->T);
fe_sub(r->T, t0, r->T);
}
/*
r = p - q
*/
void ge_msub(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) {
fe t0;
fe_add(r->X, p->Y, p->X);
fe_sub(r->Y, p->Y, p->X);
fe_mul(r->Z, r->X, q->yminusx);
fe_mul(r->Y, r->Y, q->yplusx);
fe_mul(r->T, q->xy2d, p->T);
fe_add(t0, p->Z, p->Z);
fe_sub(r->X, r->Z, r->Y);
fe_add(r->Y, r->Z, r->Y);
fe_sub(r->Z, t0, r->T);
fe_add(r->T, t0, r->T);
}
/*
r = p
*/
void ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p) {
fe_mul(r->X, p->X, p->T);
fe_mul(r->Y, p->Y, p->Z);
fe_mul(r->Z, p->Z, p->T);
}
/*
r = p
*/
void ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p) {
fe_mul(r->X, p->X, p->T);
fe_mul(r->Y, p->Y, p->Z);
fe_mul(r->Z, p->Z, p->T);
fe_mul(r->T, p->X, p->Y);
}
void ge_p2_0(ge_p2 *h) {
fe_0(h->X);
fe_1(h->Y);
fe_1(h->Z);
}
/*
r = 2 * p
*/
void ge_p2_dbl(ge_p1p1 *r, const ge_p2 *p) {
fe t0;
fe_sq(r->X, p->X);
fe_sq(r->Z, p->Y);
fe_sq2(r->T, p->Z);
fe_add(r->Y, p->X, p->Y);
fe_sq(t0, r->Y);
fe_add(r->Y, r->Z, r->X);
fe_sub(r->Z, r->Z, r->X);
fe_sub(r->X, t0, r->Y);
fe_sub(r->T, r->T, r->Z);
}
void ge_p3_0(ge_p3 *h) {
fe_0(h->X);
fe_1(h->Y);
fe_1(h->Z);
fe_0(h->T);
}
/*
r = 2 * p
*/
void ge_p3_dbl(ge_p1p1 *r, const ge_p3 *p) {
ge_p2 q;
ge_p3_to_p2(&q, p);
ge_p2_dbl(r, &q);
}
/*
r = p
*/
static const fe d2 = {
-21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199
};
void ge_p3_to_cached(ge_cached *r, const ge_p3 *p) {
fe_add(r->YplusX, p->Y, p->X);
fe_sub(r->YminusX, p->Y, p->X);
fe_copy(r->Z, p->Z);
fe_mul(r->T2d, p->T, d2);
}
/*
r = p
*/
void ge_p3_to_p2(ge_p2 *r, const ge_p3 *p) {
fe_copy(r->X, p->X);
fe_copy(r->Y, p->Y);
fe_copy(r->Z, p->Z);
}
void ge_p3_tobytes(unsigned char *s, const ge_p3 *h) {
fe recip;
fe x;
fe y;
fe_invert(recip, h->Z);
fe_mul(x, h->X, recip);
fe_mul(y, h->Y, recip);
fe_tobytes(s, y);
s[31] ^= fe_isnegative(x) << 7;
}
static unsigned char equal(signed char b, signed char c) {
unsigned char ub = b;
unsigned char uc = c;
unsigned char x = ub ^ uc; /* 0: yes; 1..255: no */
uint64_t y = x; /* 0: yes; 1..255: no */
y -= 1; /* large: yes; 0..254: no */
y >>= 63; /* 1: yes; 0: no */
return (unsigned char) y;
}
static unsigned char negative(signed char b) {
uint64_t x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */
x >>= 63; /* 1: yes; 0: no */
return (unsigned char) x;
}
static void cmov(ge_precomp *t, ge_precomp *u, unsigned char b) {
fe_cmov(t->yplusx, u->yplusx, b);
fe_cmov(t->yminusx, u->yminusx, b);
fe_cmov(t->xy2d, u->xy2d, b);
}
static void select(ge_precomp *t, int pos, signed char b) {
ge_precomp minust;
unsigned char bnegative = negative(b);
unsigned char babs = b - (((-bnegative) & b) << 1);
fe_1(t->yplusx);
fe_1(t->yminusx);
fe_0(t->xy2d);
cmov(t, &base[pos][0], equal(babs, 1));
cmov(t, &base[pos][1], equal(babs, 2));
cmov(t, &base[pos][2], equal(babs, 3));
cmov(t, &base[pos][3], equal(babs, 4));
cmov(t, &base[pos][4], equal(babs, 5));
cmov(t, &base[pos][5], equal(babs, 6));
cmov(t, &base[pos][6], equal(babs, 7));
cmov(t, &base[pos][7], equal(babs, 8));
fe_copy(minust.yplusx, t->yminusx);
fe_copy(minust.yminusx, t->yplusx);
fe_neg(minust.xy2d, t->xy2d);
cmov(t, &minust, bnegative);
}
/*
h = a * B
where a = a[0]+256*a[1]+...+256^31 a[31]
B is the Ed25519 base point (x,4/5) with x positive.
Preconditions:
a[31] <= 127
*/
void ge_scalarmult_base(ge_p3 *h, const unsigned char *a) {
signed char e[64];
signed char carry;
ge_p1p1 r;
ge_p2 s;
ge_precomp t;
int i;
for (i = 0; i < 32; ++i) {
e[2 * i + 0] = (a[i] >> 0) & 15;
e[2 * i + 1] = (a[i] >> 4) & 15;
}
/* each e[i] is between 0 and 15 */
/* e[63] is between 0 and 7 */
carry = 0;
for (i = 0; i < 63; ++i) {
e[i] += carry;
carry = e[i] + 8;
carry >>= 4;
e[i] -= carry << 4;
}
e[63] += carry;
/* each e[i] is between -8 and 8 */
ge_p3_0(h);
for (i = 1; i < 64; i += 2) {
select(&t, i / 2, e[i]);
ge_madd(&r, h, &t);
ge_p1p1_to_p3(h, &r);
}
ge_p3_dbl(&r, h);
ge_p1p1_to_p2(&s, &r);
ge_p2_dbl(&r, &s);
ge_p1p1_to_p2(&s, &r);
ge_p2_dbl(&r, &s);
ge_p1p1_to_p2(&s, &r);
ge_p2_dbl(&r, &s);
ge_p1p1_to_p3(h, &r);
for (i = 0; i < 64; i += 2) {
select(&t, i / 2, e[i]);
ge_madd(&r, h, &t);
ge_p1p1_to_p3(h, &r);
}
}
/*
r = p - q
*/
void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) {
fe t0;
fe_add(r->X, p->Y, p->X);
fe_sub(r->Y, p->Y, p->X);
fe_mul(r->Z, r->X, q->YminusX);
fe_mul(r->Y, r->Y, q->YplusX);
fe_mul(r->T, q->T2d, p->T);
fe_mul(r->X, p->Z, q->Z);
fe_add(t0, r->X, r->X);
fe_sub(r->X, r->Z, r->Y);
fe_add(r->Y, r->Z, r->Y);
fe_sub(r->Z, t0, r->T);
fe_add(r->T, t0, r->T);
}
void ge_tobytes(unsigned char *s, const ge_p2 *h) {
fe recip;
fe x;
fe y;
fe_invert(recip, h->Z);
fe_mul(x, h->X, recip);
fe_mul(y, h->Y, recip);
fe_tobytes(s, y);
s[31] ^= fe_isnegative(x) << 7;
}

View File

@@ -0,0 +1,74 @@
#ifndef GE_H
#define GE_H
#include "fe.h"
/*
ge means group element.
Here the group is the set of pairs (x,y) of field elements (see fe.h)
satisfying -x^2 + y^2 = 1 + d x^2y^2
where d = -121665/121666.
Representations:
ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z
ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT
ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T
ge_precomp (Duif): (y+x,y-x,2dxy)
*/
typedef struct {
fe X;
fe Y;
fe Z;
} ge_p2;
typedef struct {
fe X;
fe Y;
fe Z;
fe T;
} ge_p3;
typedef struct {
fe X;
fe Y;
fe Z;
fe T;
} ge_p1p1;
typedef struct {
fe yplusx;
fe yminusx;
fe xy2d;
} ge_precomp;
typedef struct {
fe YplusX;
fe YminusX;
fe Z;
fe T2d;
} ge_cached;
void ge_p3_tobytes(unsigned char *s, const ge_p3 *h);
void ge_tobytes(unsigned char *s, const ge_p2 *h);
int ge_frombytes_negate_vartime(ge_p3 *h, const unsigned char *s);
void ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q);
void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q);
void ge_double_scalarmult_vartime(ge_p2 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b);
void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q);
void ge_msub(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q);
void ge_scalarmult_base(ge_p3 *h, const unsigned char *a);
void ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p);
void ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p);
void ge_p2_0(ge_p2 *h);
void ge_p2_dbl(ge_p1p1 *r, const ge_p2 *p);
void ge_p3_0(ge_p3 *h);
void ge_p3_dbl(ge_p1p1 *r, const ge_p3 *p);
void ge_p3_to_cached(ge_cached *r, const ge_p3 *p);
void ge_p3_to_p2(ge_p2 *r, const ge_p3 *p);
#endif

View File

@@ -0,0 +1,80 @@
#include "libtorrent/ed25519.hpp"
#include "fe.h"
void ed25519_key_exchange(unsigned char *shared_secret
, const unsigned char *public_key, const unsigned char *private_key) {
unsigned char e[32];
unsigned int i;
fe x1;
fe x2;
fe z2;
fe x3;
fe z3;
fe tmp0;
fe tmp1;
int pos;
unsigned int swap;
unsigned int b;
/* copy the private key and make sure it's valid */
for (i = 0; i < 32; ++i) {
e[i] = private_key[i];
}
e[0] &= 248;
e[31] &= 63;
e[31] |= 64;
/* unpack the public key and convert edwards to montgomery */
/* due to CodesInChaos: montgomeryX = (edwardsY + 1)*inverse(1 - edwardsY) mod p */
fe_frombytes(x1, public_key);
fe_1(tmp1);
fe_add(tmp0, x1, tmp1);
fe_sub(tmp1, tmp1, x1);
fe_invert(tmp1, tmp1);
fe_mul(x1, tmp0, tmp1);
fe_1(x2);
fe_0(z2);
fe_copy(x3, x1);
fe_1(z3);
swap = 0;
for (pos = 254; pos >= 0; --pos) {
b = e[pos / 8] >> (pos & 7);
b &= 1;
swap ^= b;
fe_cswap(x2, x3, swap);
fe_cswap(z2, z3, swap);
swap = b;
/* from montgomery.h */
fe_sub(tmp0, x3, z3);
fe_sub(tmp1, x2, z2);
fe_add(x2, x2, z2);
fe_add(z2, x3, z3);
fe_mul(z3, tmp0, x2);
fe_mul(z2, z2, tmp1);
fe_sq(tmp0, tmp1);
fe_sq(tmp1, x2);
fe_add(x3, z3, z2);
fe_sub(z2, z3, z2);
fe_mul(x2, tmp1, tmp0);
fe_sub(tmp1, tmp1, tmp0);
fe_sq(z2, z2);
fe_mul121666(z3, tmp1);
fe_sq(x3, x3);
fe_add(tmp0, tmp0, z3);
fe_mul(z3, x1, z2);
fe_mul(z2, tmp1, tmp0);
}
fe_cswap(x2, x3, swap);
fe_cswap(z2, z3, swap);
fe_invert(z2, z2);
fe_mul(x2, x2, z2);
fe_tobytes(shared_secret, x2);
}

View File

@@ -0,0 +1,16 @@
#include "libtorrent/ed25519.hpp"
#include "sha512.h"
#include "ge.h"
void ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed) {
ge_p3 A;
sha512(seed, 32, private_key);
private_key[0] &= 248;
private_key[31] &= 63;
private_key[31] |= 64;
ge_scalarmult_base(&A, private_key);
ge_p3_tobytes(public_key, &A);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,809 @@
#include "fixedint.h"
#include "sc.h"
static uint64_t load_3(const unsigned char *in) {
uint64_t result;
result = (uint64_t) in[0];
result |= ((uint64_t) in[1]) << 8;
result |= ((uint64_t) in[2]) << 16;
return result;
}
static uint64_t load_4(const unsigned char *in) {
uint64_t result;
result = (uint64_t) in[0];
result |= ((uint64_t) in[1]) << 8;
result |= ((uint64_t) in[2]) << 16;
result |= ((uint64_t) in[3]) << 24;
return result;
}
/*
Input:
s[0]+256*s[1]+...+256^63*s[63] = s
Output:
s[0]+256*s[1]+...+256^31*s[31] = s mod l
where l = 2^252 + 27742317777372353535851937790883648493.
Overwrites s in place.
*/
void sc_reduce(unsigned char *s) {
int64_t s0 = 2097151 & load_3(s);
int64_t s1 = 2097151 & (load_4(s + 2) >> 5);
int64_t s2 = 2097151 & (load_3(s + 5) >> 2);
int64_t s3 = 2097151 & (load_4(s + 7) >> 7);
int64_t s4 = 2097151 & (load_4(s + 10) >> 4);
int64_t s5 = 2097151 & (load_3(s + 13) >> 1);
int64_t s6 = 2097151 & (load_4(s + 15) >> 6);
int64_t s7 = 2097151 & (load_3(s + 18) >> 3);
int64_t s8 = 2097151 & load_3(s + 21);
int64_t s9 = 2097151 & (load_4(s + 23) >> 5);
int64_t s10 = 2097151 & (load_3(s + 26) >> 2);
int64_t s11 = 2097151 & (load_4(s + 28) >> 7);
int64_t s12 = 2097151 & (load_4(s + 31) >> 4);
int64_t s13 = 2097151 & (load_3(s + 34) >> 1);
int64_t s14 = 2097151 & (load_4(s + 36) >> 6);
int64_t s15 = 2097151 & (load_3(s + 39) >> 3);
int64_t s16 = 2097151 & load_3(s + 42);
int64_t s17 = 2097151 & (load_4(s + 44) >> 5);
int64_t s18 = 2097151 & (load_3(s + 47) >> 2);
int64_t s19 = 2097151 & (load_4(s + 49) >> 7);
int64_t s20 = 2097151 & (load_4(s + 52) >> 4);
int64_t s21 = 2097151 & (load_3(s + 55) >> 1);
int64_t s22 = 2097151 & (load_4(s + 57) >> 6);
int64_t s23 = (load_4(s + 60) >> 3);
int64_t carry0;
int64_t carry1;
int64_t carry2;
int64_t carry3;
int64_t carry4;
int64_t carry5;
int64_t carry6;
int64_t carry7;
int64_t carry8;
int64_t carry9;
int64_t carry10;
int64_t carry11;
int64_t carry12;
int64_t carry13;
int64_t carry14;
int64_t carry15;
int64_t carry16;
s11 += s23 * 666643;
s12 += s23 * 470296;
s13 += s23 * 654183;
s14 -= s23 * 997805;
s15 += s23 * 136657;
s16 -= s23 * 683901;
s23 = 0;
s10 += s22 * 666643;
s11 += s22 * 470296;
s12 += s22 * 654183;
s13 -= s22 * 997805;
s14 += s22 * 136657;
s15 -= s22 * 683901;
s22 = 0;
s9 += s21 * 666643;
s10 += s21 * 470296;
s11 += s21 * 654183;
s12 -= s21 * 997805;
s13 += s21 * 136657;
s14 -= s21 * 683901;
s21 = 0;
s8 += s20 * 666643;
s9 += s20 * 470296;
s10 += s20 * 654183;
s11 -= s20 * 997805;
s12 += s20 * 136657;
s13 -= s20 * 683901;
s20 = 0;
s7 += s19 * 666643;
s8 += s19 * 470296;
s9 += s19 * 654183;
s10 -= s19 * 997805;
s11 += s19 * 136657;
s12 -= s19 * 683901;
s19 = 0;
s6 += s18 * 666643;
s7 += s18 * 470296;
s8 += s18 * 654183;
s9 -= s18 * 997805;
s10 += s18 * 136657;
s11 -= s18 * 683901;
s18 = 0;
carry6 = (s6 + (1 << 20)) >> 21;
s7 += carry6;
s6 -= carry6 << 21;
carry8 = (s8 + (1 << 20)) >> 21;
s9 += carry8;
s8 -= carry8 << 21;
carry10 = (s10 + (1 << 20)) >> 21;
s11 += carry10;
s10 -= carry10 << 21;
carry12 = (s12 + (1 << 20)) >> 21;
s13 += carry12;
s12 -= carry12 << 21;
carry14 = (s14 + (1 << 20)) >> 21;
s15 += carry14;
s14 -= carry14 << 21;
carry16 = (s16 + (1 << 20)) >> 21;
s17 += carry16;
s16 -= carry16 << 21;
carry7 = (s7 + (1 << 20)) >> 21;
s8 += carry7;
s7 -= carry7 << 21;
carry9 = (s9 + (1 << 20)) >> 21;
s10 += carry9;
s9 -= carry9 << 21;
carry11 = (s11 + (1 << 20)) >> 21;
s12 += carry11;
s11 -= carry11 << 21;
carry13 = (s13 + (1 << 20)) >> 21;
s14 += carry13;
s13 -= carry13 << 21;
carry15 = (s15 + (1 << 20)) >> 21;
s16 += carry15;
s15 -= carry15 << 21;
s5 += s17 * 666643;
s6 += s17 * 470296;
s7 += s17 * 654183;
s8 -= s17 * 997805;
s9 += s17 * 136657;
s10 -= s17 * 683901;
s17 = 0;
s4 += s16 * 666643;
s5 += s16 * 470296;
s6 += s16 * 654183;
s7 -= s16 * 997805;
s8 += s16 * 136657;
s9 -= s16 * 683901;
s16 = 0;
s3 += s15 * 666643;
s4 += s15 * 470296;
s5 += s15 * 654183;
s6 -= s15 * 997805;
s7 += s15 * 136657;
s8 -= s15 * 683901;
s15 = 0;
s2 += s14 * 666643;
s3 += s14 * 470296;
s4 += s14 * 654183;
s5 -= s14 * 997805;
s6 += s14 * 136657;
s7 -= s14 * 683901;
s14 = 0;
s1 += s13 * 666643;
s2 += s13 * 470296;
s3 += s13 * 654183;
s4 -= s13 * 997805;
s5 += s13 * 136657;
s6 -= s13 * 683901;
s13 = 0;
s0 += s12 * 666643;
s1 += s12 * 470296;
s2 += s12 * 654183;
s3 -= s12 * 997805;
s4 += s12 * 136657;
s5 -= s12 * 683901;
s12 = 0;
carry0 = (s0 + (1 << 20)) >> 21;
s1 += carry0;
s0 -= carry0 << 21;
carry2 = (s2 + (1 << 20)) >> 21;
s3 += carry2;
s2 -= carry2 << 21;
carry4 = (s4 + (1 << 20)) >> 21;
s5 += carry4;
s4 -= carry4 << 21;
carry6 = (s6 + (1 << 20)) >> 21;
s7 += carry6;
s6 -= carry6 << 21;
carry8 = (s8 + (1 << 20)) >> 21;
s9 += carry8;
s8 -= carry8 << 21;
carry10 = (s10 + (1 << 20)) >> 21;
s11 += carry10;
s10 -= carry10 << 21;
carry1 = (s1 + (1 << 20)) >> 21;
s2 += carry1;
s1 -= carry1 << 21;
carry3 = (s3 + (1 << 20)) >> 21;
s4 += carry3;
s3 -= carry3 << 21;
carry5 = (s5 + (1 << 20)) >> 21;
s6 += carry5;
s5 -= carry5 << 21;
carry7 = (s7 + (1 << 20)) >> 21;
s8 += carry7;
s7 -= carry7 << 21;
carry9 = (s9 + (1 << 20)) >> 21;
s10 += carry9;
s9 -= carry9 << 21;
carry11 = (s11 + (1 << 20)) >> 21;
s12 += carry11;
s11 -= carry11 << 21;
s0 += s12 * 666643;
s1 += s12 * 470296;
s2 += s12 * 654183;
s3 -= s12 * 997805;
s4 += s12 * 136657;
s5 -= s12 * 683901;
s12 = 0;
carry0 = s0 >> 21;
s1 += carry0;
s0 -= carry0 << 21;
carry1 = s1 >> 21;
s2 += carry1;
s1 -= carry1 << 21;
carry2 = s2 >> 21;
s3 += carry2;
s2 -= carry2 << 21;
carry3 = s3 >> 21;
s4 += carry3;
s3 -= carry3 << 21;
carry4 = s4 >> 21;
s5 += carry4;
s4 -= carry4 << 21;
carry5 = s5 >> 21;
s6 += carry5;
s5 -= carry5 << 21;
carry6 = s6 >> 21;
s7 += carry6;
s6 -= carry6 << 21;
carry7 = s7 >> 21;
s8 += carry7;
s7 -= carry7 << 21;
carry8 = s8 >> 21;
s9 += carry8;
s8 -= carry8 << 21;
carry9 = s9 >> 21;
s10 += carry9;
s9 -= carry9 << 21;
carry10 = s10 >> 21;
s11 += carry10;
s10 -= carry10 << 21;
carry11 = s11 >> 21;
s12 += carry11;
s11 -= carry11 << 21;
s0 += s12 * 666643;
s1 += s12 * 470296;
s2 += s12 * 654183;
s3 -= s12 * 997805;
s4 += s12 * 136657;
s5 -= s12 * 683901;
s12 = 0;
carry0 = s0 >> 21;
s1 += carry0;
s0 -= carry0 << 21;
carry1 = s1 >> 21;
s2 += carry1;
s1 -= carry1 << 21;
carry2 = s2 >> 21;
s3 += carry2;
s2 -= carry2 << 21;
carry3 = s3 >> 21;
s4 += carry3;
s3 -= carry3 << 21;
carry4 = s4 >> 21;
s5 += carry4;
s4 -= carry4 << 21;
carry5 = s5 >> 21;
s6 += carry5;
s5 -= carry5 << 21;
carry6 = s6 >> 21;
s7 += carry6;
s6 -= carry6 << 21;
carry7 = s7 >> 21;
s8 += carry7;
s7 -= carry7 << 21;
carry8 = s8 >> 21;
s9 += carry8;
s8 -= carry8 << 21;
carry9 = s9 >> 21;
s10 += carry9;
s9 -= carry9 << 21;
carry10 = s10 >> 21;
s11 += carry10;
s10 -= carry10 << 21;
s[0] = (unsigned char) ((s0 >> 0) & 0xff);
s[1] = (unsigned char) ((s0 >> 8) & 0xff);
s[2] = (unsigned char) (((s0 >> 16) | (s1 << 5)) & 0xff);
s[3] = (unsigned char) ((s1 >> 3) & 0xff);
s[4] = (unsigned char) ((s1 >> 11) & 0xff);
s[5] = (unsigned char) (((s1 >> 19) | (s2 << 2)) & 0xff);
s[6] = (unsigned char) ((s2 >> 6) & 0xff);
s[7] = (unsigned char) (((s2 >> 14) | (s3 << 7)) & 0xff);
s[8] = (unsigned char) ((s3 >> 1) & 0xff);
s[9] = (unsigned char) ((s3 >> 9) & 0xff);
s[10] = (unsigned char) (((s3 >> 17) | (s4 << 4)) & 0xff);
s[11] = (unsigned char) ((s4 >> 4) & 0xff);
s[12] = (unsigned char) ((s4 >> 12) & 0xff);
s[13] = (unsigned char) (((s4 >> 20) | (s5 << 1)) & 0xff);
s[14] = (unsigned char) ((s5 >> 7) & 0xff);
s[15] = (unsigned char) (((s5 >> 15) | (s6 << 6)) & 0xff);
s[16] = (unsigned char) ((s6 >> 2) & 0xff);
s[17] = (unsigned char) ((s6 >> 10) & 0xff);
s[18] = (unsigned char) (((s6 >> 18) | (s7 << 3)) & 0xff);
s[19] = (unsigned char) ((s7 >> 5) & 0xff);
s[20] = (unsigned char) ((s7 >> 13) & 0xff);
s[21] = (unsigned char) ((s8 >> 0) & 0xff);
s[22] = (unsigned char) ((s8 >> 8) & 0xff);
s[23] = (unsigned char) (((s8 >> 16) | (s9 << 5)) & 0xff);
s[24] = (unsigned char) ((s9 >> 3) & 0xff);
s[25] = (unsigned char) ((s9 >> 11) & 0xff);
s[26] = (unsigned char) (((s9 >> 19) | (s10 << 2)) & 0xff);
s[27] = (unsigned char) ((s10 >> 6) & 0xff);
s[28] = (unsigned char) (((s10 >> 14) | (s11 << 7)) & 0xff);
s[29] = (unsigned char) ((s11 >> 1) & 0xff);
s[30] = (unsigned char) ((s11 >> 9) & 0xff);
s[31] = (unsigned char) ((s11 >> 17) & 0xff);
}
/*
Input:
a[0]+256*a[1]+...+256^31*a[31] = a
b[0]+256*b[1]+...+256^31*b[31] = b
c[0]+256*c[1]+...+256^31*c[31] = c
Output:
s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l
where l = 2^252 + 27742317777372353535851937790883648493.
*/
void sc_muladd(unsigned char *s, const unsigned char *a, const unsigned char *b, const unsigned char *c) {
int64_t a0 = 2097151 & load_3(a);
int64_t a1 = 2097151 & (load_4(a + 2) >> 5);
int64_t a2 = 2097151 & (load_3(a + 5) >> 2);
int64_t a3 = 2097151 & (load_4(a + 7) >> 7);
int64_t a4 = 2097151 & (load_4(a + 10) >> 4);
int64_t a5 = 2097151 & (load_3(a + 13) >> 1);
int64_t a6 = 2097151 & (load_4(a + 15) >> 6);
int64_t a7 = 2097151 & (load_3(a + 18) >> 3);
int64_t a8 = 2097151 & load_3(a + 21);
int64_t a9 = 2097151 & (load_4(a + 23) >> 5);
int64_t a10 = 2097151 & (load_3(a + 26) >> 2);
int64_t a11 = (load_4(a + 28) >> 7);
int64_t b0 = 2097151 & load_3(b);
int64_t b1 = 2097151 & (load_4(b + 2) >> 5);
int64_t b2 = 2097151 & (load_3(b + 5) >> 2);
int64_t b3 = 2097151 & (load_4(b + 7) >> 7);
int64_t b4 = 2097151 & (load_4(b + 10) >> 4);
int64_t b5 = 2097151 & (load_3(b + 13) >> 1);
int64_t b6 = 2097151 & (load_4(b + 15) >> 6);
int64_t b7 = 2097151 & (load_3(b + 18) >> 3);
int64_t b8 = 2097151 & load_3(b + 21);
int64_t b9 = 2097151 & (load_4(b + 23) >> 5);
int64_t b10 = 2097151 & (load_3(b + 26) >> 2);
int64_t b11 = (load_4(b + 28) >> 7);
int64_t c0 = 2097151 & load_3(c);
int64_t c1 = 2097151 & (load_4(c + 2) >> 5);
int64_t c2 = 2097151 & (load_3(c + 5) >> 2);
int64_t c3 = 2097151 & (load_4(c + 7) >> 7);
int64_t c4 = 2097151 & (load_4(c + 10) >> 4);
int64_t c5 = 2097151 & (load_3(c + 13) >> 1);
int64_t c6 = 2097151 & (load_4(c + 15) >> 6);
int64_t c7 = 2097151 & (load_3(c + 18) >> 3);
int64_t c8 = 2097151 & load_3(c + 21);
int64_t c9 = 2097151 & (load_4(c + 23) >> 5);
int64_t c10 = 2097151 & (load_3(c + 26) >> 2);
int64_t c11 = (load_4(c + 28) >> 7);
int64_t s0;
int64_t s1;
int64_t s2;
int64_t s3;
int64_t s4;
int64_t s5;
int64_t s6;
int64_t s7;
int64_t s8;
int64_t s9;
int64_t s10;
int64_t s11;
int64_t s12;
int64_t s13;
int64_t s14;
int64_t s15;
int64_t s16;
int64_t s17;
int64_t s18;
int64_t s19;
int64_t s20;
int64_t s21;
int64_t s22;
int64_t s23;
int64_t carry0;
int64_t carry1;
int64_t carry2;
int64_t carry3;
int64_t carry4;
int64_t carry5;
int64_t carry6;
int64_t carry7;
int64_t carry8;
int64_t carry9;
int64_t carry10;
int64_t carry11;
int64_t carry12;
int64_t carry13;
int64_t carry14;
int64_t carry15;
int64_t carry16;
int64_t carry17;
int64_t carry18;
int64_t carry19;
int64_t carry20;
int64_t carry21;
int64_t carry22;
s0 = c0 + a0 * b0;
s1 = c1 + a0 * b1 + a1 * b0;
s2 = c2 + a0 * b2 + a1 * b1 + a2 * b0;
s3 = c3 + a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0;
s4 = c4 + a0 * b4 + a1 * b3 + a2 * b2 + a3 * b1 + a4 * b0;
s5 = c5 + a0 * b5 + a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1 + a5 * b0;
s6 = c6 + a0 * b6 + a1 * b5 + a2 * b4 + a3 * b3 + a4 * b2 + a5 * b1 + a6 * b0;
s7 = c7 + a0 * b7 + a1 * b6 + a2 * b5 + a3 * b4 + a4 * b3 + a5 * b2 + a6 * b1 + a7 * b0;
s8 = c8 + a0 * b8 + a1 * b7 + a2 * b6 + a3 * b5 + a4 * b4 + a5 * b3 + a6 * b2 + a7 * b1 + a8 * b0;
s9 = c9 + a0 * b9 + a1 * b8 + a2 * b7 + a3 * b6 + a4 * b5 + a5 * b4 + a6 * b3 + a7 * b2 + a8 * b1 + a9 * b0;
s10 = c10 + a0 * b10 + a1 * b9 + a2 * b8 + a3 * b7 + a4 * b6 + a5 * b5 + a6 * b4 + a7 * b3 + a8 * b2 + a9 * b1 + a10 * b0;
s11 = c11 + a0 * b11 + a1 * b10 + a2 * b9 + a3 * b8 + a4 * b7 + a5 * b6 + a6 * b5 + a7 * b4 + a8 * b3 + a9 * b2 + a10 * b1 + a11 * b0;
s12 = a1 * b11 + a2 * b10 + a3 * b9 + a4 * b8 + a5 * b7 + a6 * b6 + a7 * b5 + a8 * b4 + a9 * b3 + a10 * b2 + a11 * b1;
s13 = a2 * b11 + a3 * b10 + a4 * b9 + a5 * b8 + a6 * b7 + a7 * b6 + a8 * b5 + a9 * b4 + a10 * b3 + a11 * b2;
s14 = a3 * b11 + a4 * b10 + a5 * b9 + a6 * b8 + a7 * b7 + a8 * b6 + a9 * b5 + a10 * b4 + a11 * b3;
s15 = a4 * b11 + a5 * b10 + a6 * b9 + a7 * b8 + a8 * b7 + a9 * b6 + a10 * b5 + a11 * b4;
s16 = a5 * b11 + a6 * b10 + a7 * b9 + a8 * b8 + a9 * b7 + a10 * b6 + a11 * b5;
s17 = a6 * b11 + a7 * b10 + a8 * b9 + a9 * b8 + a10 * b7 + a11 * b6;
s18 = a7 * b11 + a8 * b10 + a9 * b9 + a10 * b8 + a11 * b7;
s19 = a8 * b11 + a9 * b10 + a10 * b9 + a11 * b8;
s20 = a9 * b11 + a10 * b10 + a11 * b9;
s21 = a10 * b11 + a11 * b10;
s22 = a11 * b11;
s23 = 0;
carry0 = (s0 + (1 << 20)) >> 21;
s1 += carry0;
s0 -= carry0 << 21;
carry2 = (s2 + (1 << 20)) >> 21;
s3 += carry2;
s2 -= carry2 << 21;
carry4 = (s4 + (1 << 20)) >> 21;
s5 += carry4;
s4 -= carry4 << 21;
carry6 = (s6 + (1 << 20)) >> 21;
s7 += carry6;
s6 -= carry6 << 21;
carry8 = (s8 + (1 << 20)) >> 21;
s9 += carry8;
s8 -= carry8 << 21;
carry10 = (s10 + (1 << 20)) >> 21;
s11 += carry10;
s10 -= carry10 << 21;
carry12 = (s12 + (1 << 20)) >> 21;
s13 += carry12;
s12 -= carry12 << 21;
carry14 = (s14 + (1 << 20)) >> 21;
s15 += carry14;
s14 -= carry14 << 21;
carry16 = (s16 + (1 << 20)) >> 21;
s17 += carry16;
s16 -= carry16 << 21;
carry18 = (s18 + (1 << 20)) >> 21;
s19 += carry18;
s18 -= carry18 << 21;
carry20 = (s20 + (1 << 20)) >> 21;
s21 += carry20;
s20 -= carry20 << 21;
carry22 = (s22 + (1 << 20)) >> 21;
s23 += carry22;
s22 -= carry22 << 21;
carry1 = (s1 + (1 << 20)) >> 21;
s2 += carry1;
s1 -= carry1 << 21;
carry3 = (s3 + (1 << 20)) >> 21;
s4 += carry3;
s3 -= carry3 << 21;
carry5 = (s5 + (1 << 20)) >> 21;
s6 += carry5;
s5 -= carry5 << 21;
carry7 = (s7 + (1 << 20)) >> 21;
s8 += carry7;
s7 -= carry7 << 21;
carry9 = (s9 + (1 << 20)) >> 21;
s10 += carry9;
s9 -= carry9 << 21;
carry11 = (s11 + (1 << 20)) >> 21;
s12 += carry11;
s11 -= carry11 << 21;
carry13 = (s13 + (1 << 20)) >> 21;
s14 += carry13;
s13 -= carry13 << 21;
carry15 = (s15 + (1 << 20)) >> 21;
s16 += carry15;
s15 -= carry15 << 21;
carry17 = (s17 + (1 << 20)) >> 21;
s18 += carry17;
s17 -= carry17 << 21;
carry19 = (s19 + (1 << 20)) >> 21;
s20 += carry19;
s19 -= carry19 << 21;
carry21 = (s21 + (1 << 20)) >> 21;
s22 += carry21;
s21 -= carry21 << 21;
s11 += s23 * 666643;
s12 += s23 * 470296;
s13 += s23 * 654183;
s14 -= s23 * 997805;
s15 += s23 * 136657;
s16 -= s23 * 683901;
s23 = 0;
s10 += s22 * 666643;
s11 += s22 * 470296;
s12 += s22 * 654183;
s13 -= s22 * 997805;
s14 += s22 * 136657;
s15 -= s22 * 683901;
s22 = 0;
s9 += s21 * 666643;
s10 += s21 * 470296;
s11 += s21 * 654183;
s12 -= s21 * 997805;
s13 += s21 * 136657;
s14 -= s21 * 683901;
s21 = 0;
s8 += s20 * 666643;
s9 += s20 * 470296;
s10 += s20 * 654183;
s11 -= s20 * 997805;
s12 += s20 * 136657;
s13 -= s20 * 683901;
s20 = 0;
s7 += s19 * 666643;
s8 += s19 * 470296;
s9 += s19 * 654183;
s10 -= s19 * 997805;
s11 += s19 * 136657;
s12 -= s19 * 683901;
s19 = 0;
s6 += s18 * 666643;
s7 += s18 * 470296;
s8 += s18 * 654183;
s9 -= s18 * 997805;
s10 += s18 * 136657;
s11 -= s18 * 683901;
s18 = 0;
carry6 = (s6 + (1 << 20)) >> 21;
s7 += carry6;
s6 -= carry6 << 21;
carry8 = (s8 + (1 << 20)) >> 21;
s9 += carry8;
s8 -= carry8 << 21;
carry10 = (s10 + (1 << 20)) >> 21;
s11 += carry10;
s10 -= carry10 << 21;
carry12 = (s12 + (1 << 20)) >> 21;
s13 += carry12;
s12 -= carry12 << 21;
carry14 = (s14 + (1 << 20)) >> 21;
s15 += carry14;
s14 -= carry14 << 21;
carry16 = (s16 + (1 << 20)) >> 21;
s17 += carry16;
s16 -= carry16 << 21;
carry7 = (s7 + (1 << 20)) >> 21;
s8 += carry7;
s7 -= carry7 << 21;
carry9 = (s9 + (1 << 20)) >> 21;
s10 += carry9;
s9 -= carry9 << 21;
carry11 = (s11 + (1 << 20)) >> 21;
s12 += carry11;
s11 -= carry11 << 21;
carry13 = (s13 + (1 << 20)) >> 21;
s14 += carry13;
s13 -= carry13 << 21;
carry15 = (s15 + (1 << 20)) >> 21;
s16 += carry15;
s15 -= carry15 << 21;
s5 += s17 * 666643;
s6 += s17 * 470296;
s7 += s17 * 654183;
s8 -= s17 * 997805;
s9 += s17 * 136657;
s10 -= s17 * 683901;
s17 = 0;
s4 += s16 * 666643;
s5 += s16 * 470296;
s6 += s16 * 654183;
s7 -= s16 * 997805;
s8 += s16 * 136657;
s9 -= s16 * 683901;
s16 = 0;
s3 += s15 * 666643;
s4 += s15 * 470296;
s5 += s15 * 654183;
s6 -= s15 * 997805;
s7 += s15 * 136657;
s8 -= s15 * 683901;
s15 = 0;
s2 += s14 * 666643;
s3 += s14 * 470296;
s4 += s14 * 654183;
s5 -= s14 * 997805;
s6 += s14 * 136657;
s7 -= s14 * 683901;
s14 = 0;
s1 += s13 * 666643;
s2 += s13 * 470296;
s3 += s13 * 654183;
s4 -= s13 * 997805;
s5 += s13 * 136657;
s6 -= s13 * 683901;
s13 = 0;
s0 += s12 * 666643;
s1 += s12 * 470296;
s2 += s12 * 654183;
s3 -= s12 * 997805;
s4 += s12 * 136657;
s5 -= s12 * 683901;
s12 = 0;
carry0 = (s0 + (1 << 20)) >> 21;
s1 += carry0;
s0 -= carry0 << 21;
carry2 = (s2 + (1 << 20)) >> 21;
s3 += carry2;
s2 -= carry2 << 21;
carry4 = (s4 + (1 << 20)) >> 21;
s5 += carry4;
s4 -= carry4 << 21;
carry6 = (s6 + (1 << 20)) >> 21;
s7 += carry6;
s6 -= carry6 << 21;
carry8 = (s8 + (1 << 20)) >> 21;
s9 += carry8;
s8 -= carry8 << 21;
carry10 = (s10 + (1 << 20)) >> 21;
s11 += carry10;
s10 -= carry10 << 21;
carry1 = (s1 + (1 << 20)) >> 21;
s2 += carry1;
s1 -= carry1 << 21;
carry3 = (s3 + (1 << 20)) >> 21;
s4 += carry3;
s3 -= carry3 << 21;
carry5 = (s5 + (1 << 20)) >> 21;
s6 += carry5;
s5 -= carry5 << 21;
carry7 = (s7 + (1 << 20)) >> 21;
s8 += carry7;
s7 -= carry7 << 21;
carry9 = (s9 + (1 << 20)) >> 21;
s10 += carry9;
s9 -= carry9 << 21;
carry11 = (s11 + (1 << 20)) >> 21;
s12 += carry11;
s11 -= carry11 << 21;
s0 += s12 * 666643;
s1 += s12 * 470296;
s2 += s12 * 654183;
s3 -= s12 * 997805;
s4 += s12 * 136657;
s5 -= s12 * 683901;
s12 = 0;
carry0 = s0 >> 21;
s1 += carry0;
s0 -= carry0 << 21;
carry1 = s1 >> 21;
s2 += carry1;
s1 -= carry1 << 21;
carry2 = s2 >> 21;
s3 += carry2;
s2 -= carry2 << 21;
carry3 = s3 >> 21;
s4 += carry3;
s3 -= carry3 << 21;
carry4 = s4 >> 21;
s5 += carry4;
s4 -= carry4 << 21;
carry5 = s5 >> 21;
s6 += carry5;
s5 -= carry5 << 21;
carry6 = s6 >> 21;
s7 += carry6;
s6 -= carry6 << 21;
carry7 = s7 >> 21;
s8 += carry7;
s7 -= carry7 << 21;
carry8 = s8 >> 21;
s9 += carry8;
s8 -= carry8 << 21;
carry9 = s9 >> 21;
s10 += carry9;
s9 -= carry9 << 21;
carry10 = s10 >> 21;
s11 += carry10;
s10 -= carry10 << 21;
carry11 = s11 >> 21;
s12 += carry11;
s11 -= carry11 << 21;
s0 += s12 * 666643;
s1 += s12 * 470296;
s2 += s12 * 654183;
s3 -= s12 * 997805;
s4 += s12 * 136657;
s5 -= s12 * 683901;
s12 = 0;
carry0 = s0 >> 21;
s1 += carry0;
s0 -= carry0 << 21;
carry1 = s1 >> 21;
s2 += carry1;
s1 -= carry1 << 21;
carry2 = s2 >> 21;
s3 += carry2;
s2 -= carry2 << 21;
carry3 = s3 >> 21;
s4 += carry3;
s3 -= carry3 << 21;
carry4 = s4 >> 21;
s5 += carry4;
s4 -= carry4 << 21;
carry5 = s5 >> 21;
s6 += carry5;
s5 -= carry5 << 21;
carry6 = s6 >> 21;
s7 += carry6;
s6 -= carry6 << 21;
carry7 = s7 >> 21;
s8 += carry7;
s7 -= carry7 << 21;
carry8 = s8 >> 21;
s9 += carry8;
s8 -= carry8 << 21;
carry9 = s9 >> 21;
s10 += carry9;
s9 -= carry9 << 21;
carry10 = s10 >> 21;
s11 += carry10;
s10 -= carry10 << 21;
s[0] = (unsigned char) ((s0 >> 0) & 0xff);
s[1] = (unsigned char) ((s0 >> 8) & 0xff);
s[2] = (unsigned char) (((s0 >> 16) | (s1 << 5)) & 0xff);
s[3] = (unsigned char) ((s1 >> 3) & 0xff);
s[4] = (unsigned char) ((s1 >> 11) & 0xff);
s[5] = (unsigned char) (((s1 >> 19) | (s2 << 2)) & 0xff);
s[6] = (unsigned char) ((s2 >> 6) & 0xff);
s[7] = (unsigned char) (((s2 >> 14) | (s3 << 7)) & 0xff);
s[8] = (unsigned char) ((s3 >> 1) & 0xff);
s[9] = (unsigned char) ((s3 >> 9) & 0xff);
s[10] = (unsigned char) (((s3 >> 17) | (s4 << 4)) & 0xff);
s[11] = (unsigned char) ((s4 >> 4) & 0xff);
s[12] = (unsigned char) ((s4 >> 12) & 0xff);
s[13] = (unsigned char) (((s4 >> 20) | (s5 << 1)) & 0xff);
s[14] = (unsigned char) ((s5 >> 7) & 0xff);
s[15] = (unsigned char) (((s5 >> 15) | (s6 << 6)) & 0xff);
s[16] = (unsigned char) ((s6 >> 2) & 0xff);
s[17] = (unsigned char) ((s6 >> 10) & 0xff);
s[18] = (unsigned char) (((s6 >> 18) | (s7 << 3)) & 0xff);
s[19] = (unsigned char) ((s7 >> 5) & 0xff);
s[20] = (unsigned char) ((s7 >> 13) & 0xff);
s[21] = (unsigned char) ((s8 >> 0) & 0xff);
s[22] = (unsigned char) ((s8 >> 8) & 0xff);
s[23] = (unsigned char) (((s8 >> 16) | (s9 << 5)) & 0xff);
s[24] = (unsigned char) ((s9 >> 3) & 0xff);
s[25] = (unsigned char) ((s9 >> 11) & 0xff);
s[26] = (unsigned char) (((s9 >> 19) | (s10 << 2)) & 0xff);
s[27] = (unsigned char) ((s10 >> 6) & 0xff);
s[28] = (unsigned char) (((s10 >> 14) | (s11 << 7)) & 0xff);
s[29] = (unsigned char) ((s11 >> 1) & 0xff);
s[30] = (unsigned char) ((s11 >> 9) & 0xff);
s[31] = (unsigned char) ((s11 >> 17) & 0xff);
}

View File

@@ -0,0 +1,13 @@
#ifndef SC_H
#define SC_H
/*
The set of scalars is \Z/l
where l = 2^252 + 27742317777372353535851937790883648493.
*/
void sc_reduce(unsigned char *s);
void sc_muladd(unsigned char *s, const unsigned char *a, const unsigned char *b, const unsigned char *c);
#endif

View File

@@ -0,0 +1,41 @@
#include "libtorrent/ed25519.hpp"
#ifndef ED25519_NO_SEED
#ifdef _WIN32
#include <Windows.h>
#include <Wincrypt.h>
#else
#include <stdio.h>
#endif
int ed25519_create_seed(unsigned char *seed) {
#ifdef _WIN32
HCRYPTPROV prov;
if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
return 1;
}
if (!CryptGenRandom(prov, 32, seed)) {
CryptReleaseContext(prov, 0);
return 1;
}
CryptReleaseContext(prov, 0);
#else
FILE *f = fopen("/dev/urandom", "rb");
if (f == NULL) {
return 1;
}
fread(seed, 1, 32, f);
fclose(f);
#endif
return 0;
}
#endif

View File

@@ -0,0 +1,279 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
*/
#include "fixedint.h"
#include "sha512.h"
#ifndef UINT64_C
#define UINT64_C(x) x ## LL
#endif
/* the K array */
static const uint64_t K[80] = {
UINT64_C(0x428a2f98d728ae22), UINT64_C(0x7137449123ef65cd),
UINT64_C(0xb5c0fbcfec4d3b2f), UINT64_C(0xe9b5dba58189dbbc),
UINT64_C(0x3956c25bf348b538), UINT64_C(0x59f111f1b605d019),
UINT64_C(0x923f82a4af194f9b), UINT64_C(0xab1c5ed5da6d8118),
UINT64_C(0xd807aa98a3030242), UINT64_C(0x12835b0145706fbe),
UINT64_C(0x243185be4ee4b28c), UINT64_C(0x550c7dc3d5ffb4e2),
UINT64_C(0x72be5d74f27b896f), UINT64_C(0x80deb1fe3b1696b1),
UINT64_C(0x9bdc06a725c71235), UINT64_C(0xc19bf174cf692694),
UINT64_C(0xe49b69c19ef14ad2), UINT64_C(0xefbe4786384f25e3),
UINT64_C(0x0fc19dc68b8cd5b5), UINT64_C(0x240ca1cc77ac9c65),
UINT64_C(0x2de92c6f592b0275), UINT64_C(0x4a7484aa6ea6e483),
UINT64_C(0x5cb0a9dcbd41fbd4), UINT64_C(0x76f988da831153b5),
UINT64_C(0x983e5152ee66dfab), UINT64_C(0xa831c66d2db43210),
UINT64_C(0xb00327c898fb213f), UINT64_C(0xbf597fc7beef0ee4),
UINT64_C(0xc6e00bf33da88fc2), UINT64_C(0xd5a79147930aa725),
UINT64_C(0x06ca6351e003826f), UINT64_C(0x142929670a0e6e70),
UINT64_C(0x27b70a8546d22ffc), UINT64_C(0x2e1b21385c26c926),
UINT64_C(0x4d2c6dfc5ac42aed), UINT64_C(0x53380d139d95b3df),
UINT64_C(0x650a73548baf63de), UINT64_C(0x766a0abb3c77b2a8),
UINT64_C(0x81c2c92e47edaee6), UINT64_C(0x92722c851482353b),
UINT64_C(0xa2bfe8a14cf10364), UINT64_C(0xa81a664bbc423001),
UINT64_C(0xc24b8b70d0f89791), UINT64_C(0xc76c51a30654be30),
UINT64_C(0xd192e819d6ef5218), UINT64_C(0xd69906245565a910),
UINT64_C(0xf40e35855771202a), UINT64_C(0x106aa07032bbd1b8),
UINT64_C(0x19a4c116b8d2d0c8), UINT64_C(0x1e376c085141ab53),
UINT64_C(0x2748774cdf8eeb99), UINT64_C(0x34b0bcb5e19b48a8),
UINT64_C(0x391c0cb3c5c95a63), UINT64_C(0x4ed8aa4ae3418acb),
UINT64_C(0x5b9cca4f7763e373), UINT64_C(0x682e6ff3d6b2b8a3),
UINT64_C(0x748f82ee5defb2fc), UINT64_C(0x78a5636f43172f60),
UINT64_C(0x84c87814a1f0ab72), UINT64_C(0x8cc702081a6439ec),
UINT64_C(0x90befffa23631e28), UINT64_C(0xa4506cebde82bde9),
UINT64_C(0xbef9a3f7b2c67915), UINT64_C(0xc67178f2e372532b),
UINT64_C(0xca273eceea26619c), UINT64_C(0xd186b8c721c0c207),
UINT64_C(0xeada7dd6cde0eb1e), UINT64_C(0xf57d4f7fee6ed178),
UINT64_C(0x06f067aa72176fba), UINT64_C(0x0a637dc5a2c898a6),
UINT64_C(0x113f9804bef90dae), UINT64_C(0x1b710b35131c471b),
UINT64_C(0x28db77f523047d84), UINT64_C(0x32caab7b40c72493),
UINT64_C(0x3c9ebe0a15c9bebc), UINT64_C(0x431d67c49c100d4c),
UINT64_C(0x4cc5d4becb3e42b6), UINT64_C(0x597f299cfc657e2a),
UINT64_C(0x5fcb6fab3ad6faec), UINT64_C(0x6c44198c4a475817)
};
/* Various logical functions */
#define ROR64c(x, y) \
( ((((x)&UINT64_C(0xFFFFFFFFFFFFFFFF))>>((uint64_t)(y)&UINT64_C(63))) | \
((x)<<((uint64_t)(64-((y)&UINT64_C(63)))))) & UINT64_C(0xFFFFFFFFFFFFFFFF))
#define STORE64H(x, y) \
{ (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
(y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
(y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
(y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
#define LOAD64H(x, y) \
{ x = (((uint64_t)((y)[0] & 255))<<56)|(((uint64_t)((y)[1] & 255))<<48) | \
(((uint64_t)((y)[2] & 255))<<40)|(((uint64_t)((y)[3] & 255))<<32) | \
(((uint64_t)((y)[4] & 255))<<24)|(((uint64_t)((y)[5] & 255))<<16) | \
(((uint64_t)((y)[6] & 255))<<8)|(((uint64_t)((y)[7] & 255))); }
#define Ch(x,y,z) (z ^ (x & (y ^ z)))
#define Maj(x,y,z) (((x | y) & z) | (x & y))
#define S(x, n) ROR64c(x, n)
#define R(x, n) (((x) &UINT64_C(0xFFFFFFFFFFFFFFFF))>>((uint64_t)n))
#define Sigma0(x) (S(x, 28) ^ S(x, 34) ^ S(x, 39))
#define Sigma1(x) (S(x, 14) ^ S(x, 18) ^ S(x, 41))
#define Gamma0(x) (S(x, 1) ^ S(x, 8) ^ R(x, 7))
#define Gamma1(x) (S(x, 19) ^ S(x, 61) ^ R(x, 6))
#ifndef MIN
#define MIN(x, y) ( ((x)<(y))?(x):(y) )
#endif
/* compress 1024-bits */
static int sha512_compress(sha512_context *md, unsigned char *buf)
{
uint64_t S[8], W[80], t0, t1;
int i;
/* copy state into S */
for (i = 0; i < 8; i++) {
S[i] = md->state[i];
}
/* copy the state into 1024-bits into W[0..15] */
for (i = 0; i < 16; i++) {
LOAD64H(W[i], buf + (8*i));
}
/* fill W[16..79] */
for (i = 16; i < 80; i++) {
W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
}
/* Compress */
#define RND(a,b,c,d,e,f,g,h,i) \
t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
t1 = Sigma0(a) + Maj(a, b, c);\
d += t0; \
h = t0 + t1;
for (i = 0; i < 80; i += 8) {
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7);
}
#undef RND
/* feedback */
for (i = 0; i < 8; i++) {
md->state[i] = md->state[i] + S[i];
}
return 0;
}
/**
Initialize the hash state
@param md The hash state you wish to initialize
@return 0 if successful
*/
int sha512_init(sha512_context * md) {
if (md == NULL) return 1;
md->curlen = 0;
md->length = 0;
md->state[0] = UINT64_C(0x6a09e667f3bcc908);
md->state[1] = UINT64_C(0xbb67ae8584caa73b);
md->state[2] = UINT64_C(0x3c6ef372fe94f82b);
md->state[3] = UINT64_C(0xa54ff53a5f1d36f1);
md->state[4] = UINT64_C(0x510e527fade682d1);
md->state[5] = UINT64_C(0x9b05688c2b3e6c1f);
md->state[6] = UINT64_C(0x1f83d9abfb41bd6b);
md->state[7] = UINT64_C(0x5be0cd19137e2179);
return 0;
}
/**
Process a block of memory though the hash
@param md The hash state
@param in The data to hash
@param inlen The length of the data (octets)
@return 0 if successful
*/
int sha512_update (sha512_context * md, const unsigned char *in, size_t inlen)
{
size_t n;
size_t i;
int err;
if (md == NULL) return 1;
if (in == NULL) return 1;
if (md->curlen > sizeof(md->buf)) {
return 1;
}
while (inlen > 0) {
if (md->curlen == 0 && inlen >= 128) {
if ((err = sha512_compress (md, (unsigned char *)in)) != 0) {
return err;
}
md->length += 128 * 8;
in += 128;
inlen -= 128;
} else {
n = MIN(inlen, (128 - md->curlen));
for (i = 0; i < n; i++) {
md->buf[i + md->curlen] = in[i];
}
md->curlen += n;
in += n;
inlen -= n;
if (md->curlen == 128) {
if ((err = sha512_compress (md, md->buf)) != 0) {
return err;
}
md->length += 8*128;
md->curlen = 0;
}
}
}
return 0;
}
/**
Terminate the hash to get the digest
@param md The hash state
@param out [out] The destination of the hash (64 bytes)
@return 0 if successful
*/
int sha512_final(sha512_context * md, unsigned char *out)
{
int i;
if (md == NULL) return 1;
if (out == NULL) return 1;
if (md->curlen >= sizeof(md->buf)) {
return 1;
}
/* increase the length of the message */
md->length += md->curlen * UINT64_C(8);
/* append the '1' bit */
md->buf[md->curlen++] = (unsigned char)0x80;
/* if the length is currently above 112 bytes we append zeros
* then compress. Then we can fall back to padding zeros and length
* encoding like normal.
*/
if (md->curlen > 112) {
while (md->curlen < 128) {
md->buf[md->curlen++] = (unsigned char)0;
}
sha512_compress(md, md->buf);
md->curlen = 0;
}
/* pad upto 120 bytes of zeroes
* note: that from 112 to 120 is the 64 MSB of the length. We assume that you won't hash
* > 2^64 bits of data... :-)
*/
while (md->curlen < 120) {
md->buf[md->curlen++] = (unsigned char)0;
}
/* store length */
STORE64H(md->length, md->buf+120);
sha512_compress(md, md->buf);
/* copy output */
for (i = 0; i < 8; i++) {
STORE64H(md->state[i], out+(8*i));
}
return 0;
}
int sha512(const unsigned char *message, size_t message_len, unsigned char *out)
{
sha512_context ctx;
int ret;
if ((ret = sha512_init(&ctx))) return ret;
if ((ret = sha512_update(&ctx, message, message_len))) return ret;
if ((ret = sha512_final(&ctx, out))) return ret;
return 0;
}

View File

@@ -0,0 +1,22 @@
#ifndef SHA512_H
#define SHA512_H
#include <stddef.h>
#include "fixedint.h"
/* state */
typedef struct sha512_context_ {
uint64_t length, state[8];
size_t curlen;
unsigned char buf[128];
} sha512_context;
int sha512_init(sha512_context * md);
int sha512_final(sha512_context * md, unsigned char *out);
int sha512_update(sha512_context * md, const unsigned char *in, size_t inlen);
int sha512(const unsigned char *message, size_t message_len, unsigned char *out);
#endif

View File

@@ -0,0 +1,31 @@
#include "libtorrent/ed25519.hpp"
#include "sha512.h"
#include "ge.h"
#include "sc.h"
void ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key) {
sha512_context hash;
unsigned char hram[64];
unsigned char r[64];
ge_p3 R;
sha512_init(&hash);
sha512_update(&hash, private_key + 32, 32);
sha512_update(&hash, message, message_len);
sha512_final(&hash, r);
sc_reduce(r);
ge_scalarmult_base(&R, r);
ge_p3_tobytes(signature, &R);
sha512_init(&hash);
sha512_update(&hash, signature, 32);
sha512_update(&hash, public_key, 32);
sha512_update(&hash, message, message_len);
sha512_final(&hash, hram);
sc_reduce(hram);
sc_muladd(signature + 32, hram, private_key, r);
}

View File

@@ -0,0 +1,77 @@
#include "libtorrent/ed25519.hpp"
#include "sha512.h"
#include "ge.h"
#include "sc.h"
static int consttime_equal(const unsigned char *x, const unsigned char *y) {
unsigned char r = 0;
r = x[0] ^ y[0];
#define F(i) r |= x[i] ^ y[i]
F(1);
F(2);
F(3);
F(4);
F(5);
F(6);
F(7);
F(8);
F(9);
F(10);
F(11);
F(12);
F(13);
F(14);
F(15);
F(16);
F(17);
F(18);
F(19);
F(20);
F(21);
F(22);
F(23);
F(24);
F(25);
F(26);
F(27);
F(28);
F(29);
F(30);
F(31);
#undef F
return !r;
}
int ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key) {
unsigned char h[64];
unsigned char checker[32];
sha512_context hash;
ge_p3 A;
ge_p2 R;
if (signature[63] & 224) {
return 0;
}
if (ge_frombytes_negate_vartime(&A, public_key) != 0) {
return 0;
}
sha512_init(&hash);
sha512_update(&hash, signature, 32);
sha512_update(&hash, public_key, 32);
sha512_update(&hash, message, message_len);
sha512_final(&hash, h);
sc_reduce(h);
ge_double_scalarmult_vartime(&R, h, &A, signature + 32);
ge_tobytes(checker, &R);
if (!consttime_equal(checker, signature)) {
return 0;
}
return 1;
}

View File

@@ -0,0 +1,149 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
//#define ED25519_DLL
#include "src/ed25519.h"
#include "src/ge.h"
#include "src/sc.h"
const char message[] = "Hello, world!";
int main(int argc, char *argv[]) {
unsigned char public_key[32], private_key[64], seed[32], scalar[32];
unsigned char other_public_key[32], other_private_key[64];
unsigned char shared_secret[32], other_shared_secret[32];
unsigned char signature[64];
clock_t start;
clock_t end;
int i;
/* create a random seed, and a keypair out of that seed */
ed25519_create_seed(seed);
ed25519_create_keypair(public_key, private_key, seed);
/* create signature on the message with the keypair */
ed25519_sign(signature, message, strlen(message), public_key, private_key);
/* verify the signature */
if (ed25519_verify(signature, message, strlen(message), public_key)) {
printf("valid signature\n");
} else {
printf("invalid signature\n");
}
/* create scalar and add it to the keypair */
ed25519_create_seed(scalar);
ed25519_add_scalar(public_key, private_key, scalar);
/* create signature with the new keypair */
ed25519_sign(signature, message, strlen(message), public_key, private_key);
/* verify the signature with the new keypair */
if (ed25519_verify(signature, message, strlen(message), public_key)) {
printf("valid signature\n");
} else {
printf("invalid signature\n");
}
/* make a slight adjustment and verify again */
signature[44] ^= 0x10;
if (ed25519_verify(signature, message, strlen(message), public_key)) {
printf("did not detect signature change\n");
} else {
printf("correctly detected signature change\n");
}
/* generate two keypairs for testing key exchange */
ed25519_create_seed(seed);
ed25519_create_keypair(public_key, private_key, seed);
ed25519_create_seed(seed);
ed25519_create_keypair(other_public_key, other_private_key, seed);
/* create two shared secrets - from both perspectives - and check if they're equal */
ed25519_key_exchange(shared_secret, other_public_key, private_key);
ed25519_key_exchange(other_shared_secret, public_key, other_private_key);
for (i = 0; i < 32; ++i) {
if (shared_secret[i] != other_shared_secret[i]) {
printf("key exchange was incorrect\n");
break;
}
}
if (i == 32) {
printf("key exchange was correct\n");
}
/* test performance */
printf("testing seed generation performance: ");
start = clock();
for (i = 0; i < 10000; ++i) {
ed25519_create_seed(seed);
}
end = clock();
printf("%fus per seed\n", ((double) ((end - start) * 1000)) / CLOCKS_PER_SEC / i * 1000);
printf("testing key generation performance: ");
start = clock();
for (i = 0; i < 10000; ++i) {
ed25519_create_keypair(public_key, private_key, seed);
}
end = clock();
printf("%fus per keypair\n", ((double) ((end - start) * 1000)) / CLOCKS_PER_SEC / i * 1000);
printf("testing sign performance: ");
start = clock();
for (i = 0; i < 10000; ++i) {
ed25519_sign(signature, message, strlen(message), public_key, private_key);
}
end = clock();
printf("%fus per signature\n", ((double) ((end - start) * 1000)) / CLOCKS_PER_SEC / i * 1000);
printf("testing verify performance: ");
start = clock();
for (i = 0; i < 10000; ++i) {
ed25519_verify(signature, message, strlen(message), public_key);
}
end = clock();
printf("%fus per signature\n", ((double) ((end - start) * 1000)) / CLOCKS_PER_SEC / i * 1000);
printf("testing keypair scalar addition performance: ");
start = clock();
for (i = 0; i < 10000; ++i) {
ed25519_add_scalar(public_key, private_key, scalar);
}
end = clock();
printf("%fus per keypair\n", ((double) ((end - start) * 1000)) / CLOCKS_PER_SEC / i * 1000);
printf("testing public key scalar addition performance: ");
start = clock();
for (i = 0; i < 10000; ++i) {
ed25519_add_scalar(public_key, NULL, scalar);
}
end = clock();
printf("%fus per key\n", ((double) ((end - start) * 1000)) / CLOCKS_PER_SEC / i * 1000);
printf("testing key exchange performance: ");
start = clock();
for (i = 0; i < 10000; ++i) {
ed25519_key_exchange(shared_secret, other_public_key, private_key);
}
end = clock();
printf("%fus per shared secret\n", ((double) ((end - start) * 1000)) / CLOCKS_PER_SEC / i * 1000);
return 0;
}

View File

@@ -0,0 +1,165 @@
/*
* Copyright 2001-2004 Unicode, Inc.
*
* Disclaimer
*
* This source code is provided as is by Unicode, Inc. No claims are
* made as to fitness for any particular purpose. No warranties of any
* kind are expressed or implied. The recipient agrees to determine
* applicability of information provided. If this file has been
* purchased on magnetic or optical media from Unicode, Inc., the
* sole remedy for any claim will be exchange of defective media
* within 90 days of receipt.
*
* Limitations on Rights to Redistribute This Code
*
* Unicode, Inc. hereby grants the right to freely use the information
* supplied in this file in the creation of products supporting the
* Unicode Standard, and to make copies of this file in any form
* for internal or external distribution as long as this notice
* remains attached.
*/
/* ---------------------------------------------------------------------
Conversions between UTF32, UTF-16, and UTF-8. Header file.
Several funtions are included here, forming a complete set of
conversions between the three formats. UTF-7 is not included
here, but is handled in a separate source file.
Each of these routines takes pointers to input buffers and output
buffers. The input buffers are const.
Each routine converts the text between *sourceStart and sourceEnd,
putting the result into the buffer between *targetStart and
targetEnd. Note: the end pointers are *after* the last item: e.g.
*(sourceEnd - 1) is the last item.
The return result indicates whether the conversion was successful,
and if not, whether the problem was in the source or target buffers.
(Only the first encountered problem is indicated.)
After the conversion, *sourceStart and *targetStart are both
updated to point to the end of last text successfully converted in
the respective buffers.
Input parameters:
sourceStart - pointer to a pointer to the source buffer.
The contents of this are modified on return so that
it points at the next thing to be converted.
targetStart - similarly, pointer to pointer to the target buffer.
sourceEnd, targetEnd - respectively pointers to the ends of the
two buffers, for overflow checking only.
These conversion functions take a ConversionFlags argument. When this
flag is set to strict, both irregular sequences and isolated surrogates
will cause an error. When the flag is set to lenient, both irregular
sequences and isolated surrogates are converted.
Whether the flag is strict or lenient, all illegal sequences will cause
an error return. This includes sequences such as: <F4 90 80 80>, <C0 80>,
or <A0> in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code
must check for illegal sequences.
When the flag is set to lenient, characters over 0x10FFFF are converted
to the replacement character; otherwise (when the flag is set to strict)
they constitute an error.
Output parameters:
The value "sourceIllegal" is returned from some routines if the input
sequence is malformed. When "sourceIllegal" is returned, the source
value will point to the illegal value that caused the problem. E.g.,
in UTF-8 when a sequence is malformed, it points to the start of the
malformed sequence.
Author: Mark E. Davis, 1994.
Rev History: Rick McGowan, fixes & updates May 2001.
Fixes & updates, Sept 2001.
------------------------------------------------------------------------ */
/* ---------------------------------------------------------------------
The following 4 definitions are compiler-specific.
The C standard does not guarantee that wchar_t has at least
16 bits, so wchar_t is no less portable than unsigned short!
All should be unsigned values to avoid sign extension during
bit mask & shift operations.
------------------------------------------------------------------------ */
#ifdef __cplusplus
#include "libtorrent/config.hpp"
// these are standard C types, but they might
// not be available in c++
#include <boost/cstdint.hpp>
typedef boost::uint32_t UTF32;
typedef boost::uint16_t UTF16;
typedef boost::uint8_t UTF8;
extern "C" {
#else
#define TORRENT_EXTRA_EXPORT
#ifdef _MSC_VER
// msvc doesn't seem to have stdint.h
typedef unsigned __int32 UTF32;
typedef unsigned __int16 UTF16;
typedef unsigned __int8 UTF8;
#else
#include <stdint.h>
typedef uint32_t UTF32;
typedef uint16_t UTF16;
typedef uint8_t UTF8;
#endif
#endif
typedef unsigned char Boolean; /* 0 or 1 */
/* Some fundamental constants */
#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD
#define UNI_MAX_BMP (UTF32)0x0000FFFF
#define UNI_MAX_UTF16 (UTF32)0x0010FFFF
#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF
#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF
typedef enum {
conversionOK, /* conversion successful */
sourceExhausted, /* partial character in source, but hit end */
targetExhausted, /* insuff. room in target for conversion */
sourceIllegal /* source sequence is illegal/malformed */
} ConversionResult;
typedef enum {
strictConversion = 0,
lenientConversion
} ConversionFlags;
TORRENT_EXTRA_EXPORT ConversionResult ConvertUTF8toUTF16 (
const UTF8** sourceStart, const UTF8* sourceEnd,
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
TORRENT_EXTRA_EXPORT ConversionResult ConvertUTF16toUTF8 (
const UTF16** sourceStart, const UTF16* sourceEnd,
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
TORRENT_EXTRA_EXPORT ConversionResult ConvertUTF8toUTF32 (
const UTF8** sourceStart, const UTF8* sourceEnd,
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
TORRENT_EXTRA_EXPORT ConversionResult ConvertUTF32toUTF8 (
const UTF32** sourceStart, const UTF32* sourceEnd,
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
TORRENT_EXTRA_EXPORT ConversionResult ConvertUTF16toUTF32 (
const UTF16** sourceStart, const UTF16* sourceEnd,
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
TORRENT_EXTRA_EXPORT ConversionResult ConvertUTF32toUTF16 (
const UTF32** sourceStart, const UTF32* sourceEnd,
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
TORRENT_EXTRA_EXPORT Boolean isLegalUTF8Sequence(const UTF8 *source,
const UTF8 *sourceEnd);
#ifdef __cplusplus
}
#endif
/* --------------------------------------------------------------------- */

View File

@@ -0,0 +1,179 @@
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */
/* GeoIP.h
*
* Copyright (C) 2006 MaxMind LLC
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef GEOIP_H
#define GEOIP_H
#ifdef __cplusplus
extern "C" {
#endif
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <sys/types.h> /* for fstat */
#define SEGMENT_RECORD_LENGTH 3
#define STANDARD_RECORD_LENGTH 3
#define ORG_RECORD_LENGTH 4
#define MAX_RECORD_LENGTH 4
#define NUM_DB_TYPES 20
typedef struct GeoIPTag {
FILE *GeoIPDatabase;
char *file_path;
unsigned char *cache;
unsigned char *index_cache;
unsigned int *databaseSegments;
char databaseType;
time_t mtime;
int flags;
off_t size;
char record_length;
int charset; /* 0 iso-8859-1 1 utf8 */
int record_iter; /* used in GeoIP_next_record */
int netmask; /* netmask of last lookup - set using depth in _GeoIP_seek_record */
} GeoIP;
typedef enum {
GEOIP_CHARSET_ISO_8859_1 = 0,
GEOIP_CHARSET_UTF8 = 1
} GeoIPCharset;
typedef struct GeoIPRegionTag {
char country_code[3];
char region[3];
} GeoIPRegion;
typedef enum {
GEOIP_STANDARD = 0,
GEOIP_MEMORY_CACHE = 1,
GEOIP_CHECK_CACHE = 2,
GEOIP_INDEX_CACHE = 4,
GEOIP_MMAP_CACHE = 8
} GeoIPOptions;
typedef enum {
GEOIP_COUNTRY_EDITION = 1,
GEOIP_REGION_EDITION_REV0 = 7,
GEOIP_CITY_EDITION_REV0 = 6,
GEOIP_ORG_EDITION = 5,
GEOIP_ISP_EDITION = 4,
GEOIP_CITY_EDITION_REV1 = 2,
GEOIP_REGION_EDITION_REV1 = 3,
GEOIP_PROXY_EDITION = 8,
GEOIP_ASNUM_EDITION = 9,
GEOIP_NETSPEED_EDITION = 10,
GEOIP_DOMAIN_EDITION = 11
} GeoIPDBTypes;
typedef enum {
GEOIP_ANON_PROXY = 1,
GEOIP_HTTP_X_FORWARDED_FOR_PROXY = 2,
GEOIP_HTTP_CLIENT_IP_PROXY = 3
} GeoIPProxyTypes;
typedef enum {
GEOIP_UNKNOWN_SPEED = 0,
GEOIP_DIALUP_SPEED = 1,
GEOIP_CABLEDSL_SPEED = 2,
GEOIP_CORPORATE_SPEED = 3
} GeoIPNetspeedValues;
extern char **GeoIPDBFileName;
extern const char * GeoIPDBDescription[NUM_DB_TYPES];
extern const char *GeoIPCountryDBFileName;
extern const char *GeoIPRegionDBFileName;
extern const char *GeoIPCityDBFileName;
extern const char *GeoIPOrgDBFileName;
extern const char *GeoIPISPDBFileName;
extern const char GeoIP_country_code[253][3];
extern const char GeoIP_country_code3[253][4];
extern const char * GeoIP_country_name[253];
extern const char GeoIP_country_continent[253][3];
#ifdef DLL
#define GEOIP_API __declspec(dllexport)
#else
#define GEOIP_API
#endif /* DLL */
GEOIP_API void GeoIP_setup_custom_directory(char *dir);
GEOIP_API GeoIP* GeoIP_open_type (int type, int flags);
GEOIP_API GeoIP* GeoIP_new(int flags);
GEOIP_API GeoIP* GeoIP_open(const char * filename, int flags);
GEOIP_API int GeoIP_db_avail(int type);
GEOIP_API void GeoIP_delete(GeoIP* gi);
GEOIP_API const char *GeoIP_country_code_by_addr (GeoIP* gi, const char *addr);
GEOIP_API const char *GeoIP_country_code_by_name (GeoIP* gi, const char *host);
GEOIP_API const char *GeoIP_country_code3_by_addr (GeoIP* gi, const char *addr);
GEOIP_API const char *GeoIP_country_code3_by_name (GeoIP* gi, const char *host);
GEOIP_API const char *GeoIP_country_name_by_addr (GeoIP* gi, const char *addr);
GEOIP_API const char *GeoIP_country_name_by_name (GeoIP* gi, const char *host);
GEOIP_API const char *GeoIP_country_name_by_ipnum (GeoIP* gi, unsigned long ipnum);
GEOIP_API const char *GeoIP_country_code_by_ipnum (GeoIP* gi, unsigned long ipnum);
GEOIP_API const char *GeoIP_country_code3_by_ipnum (GeoIP* gi, unsigned long ipnum);
/* Deprecated - for backwards compatibility only */
GEOIP_API int GeoIP_country_id_by_addr (GeoIP* gi, const char *addr);
GEOIP_API int GeoIP_country_id_by_name (GeoIP* gi, const char *host);
GEOIP_API char *GeoIP_org_by_addr (GeoIP* gi, const char *addr);
GEOIP_API char *GeoIP_org_by_name (GeoIP* gi, const char *host);
/* End deprecated */
GEOIP_API int GeoIP_id_by_addr (GeoIP* gi, const char *addr);
GEOIP_API int GeoIP_id_by_name (GeoIP* gi, const char *host);
GEOIP_API int GeoIP_id_by_ipnum (GeoIP* gi, unsigned long ipnum);
GEOIP_API GeoIPRegion * GeoIP_region_by_addr (GeoIP* gi, const char *addr);
GEOIP_API GeoIPRegion * GeoIP_region_by_name (GeoIP* gi, const char *host);
GEOIP_API GeoIPRegion * GeoIP_region_by_ipnum (GeoIP *gi, unsigned long ipnum);
/* Warning - don't call this after GeoIP_assign_region_by_inetaddr calls */
GEOIP_API void GeoIPRegion_delete (GeoIPRegion *gir);
GEOIP_API void GeoIP_assign_region_by_inetaddr(GeoIP* gi, unsigned long inetaddr, GeoIPRegion *gir);
/* Used to query GeoIP Organization, ISP and AS Number databases */
GEOIP_API char *GeoIP_name_by_ipnum (GeoIP* gi, unsigned long ipnum);
GEOIP_API char *GeoIP_name_by_addr (GeoIP* gi, const char *addr);
GEOIP_API char *GeoIP_name_by_name (GeoIP* gi, const char *host);
GEOIP_API char *GeoIP_database_info (GeoIP* gi);
GEOIP_API unsigned char GeoIP_database_edition (GeoIP* gi);
GEOIP_API int GeoIP_charset (GeoIP* gi);
GEOIP_API int GeoIP_set_charset (GeoIP* gi, int charset);
GEOIP_API int GeoIP_last_netmask (GeoIP* gi);
/* Convert region code to region name */
GEOIP_API const char * GeoIP_region_name_by_code(const char *country_code, const char *region_code);
/* Get timezone from country and region code */
GEOIP_API const char * GeoIP_time_zone_by_country_and_region(const char *country_code, const char *region_code);
#ifdef __cplusplus
}
#endif
#endif /* GEOIP_H */

View File

@@ -0,0 +1,155 @@
includedir = @includedir@/libtorrent
if WITH_SHIPPED_GEOIP
GEOIP_H = GeoIP.h
endif
nobase_include_HEADERS = \
address.hpp \
add_torrent_params.hpp \
alert.hpp \
alert_manager.hpp \
alert_dispatcher.hpp \
alert_types.hpp \
alloca.hpp \
allocator.hpp \
assert.hpp \
bandwidth_limit.hpp \
bandwidth_manager.hpp \
bandwidth_socket.hpp \
bandwidth_queue_entry.hpp \
bencode.hpp \
bitfield.hpp \
bloom_filter.hpp \
broadcast_socket.hpp \
bt_peer_connection.hpp \
buffer.hpp \
build_config.hpp \
chained_buffer.hpp \
config.hpp \
connection_queue.hpp \
ConvertUTF.h \
copy_ptr.hpp \
create_torrent.hpp \
deadline_timer.hpp \
debug.hpp \
disk_buffer_holder.hpp \
disk_buffer_pool.hpp \
disk_io_thread.hpp \
ed25519.hpp \
entry.hpp \
enum_net.hpp \
error.hpp \
error_code.hpp \
escape_string.hpp \
export.hpp \
extensions.hpp \
file.hpp \
file_pool.hpp \
file_storage.hpp \
fingerprint.hpp \
gzip.hpp \
hasher.hpp \
http_connection.hpp \
http_parser.hpp \
http_seed_connection.hpp \
http_stream.hpp \
http_tracker_connection.hpp \
i2p_stream.hpp \
identify_client.hpp \
instantiate_connection.hpp \
intrusive_ptr_base.hpp \
invariant_check.hpp \
io.hpp \
io_service.hpp \
io_service_fwd.hpp \
ip_filter.hpp \
ip_voter.hpp \
lazy_entry.hpp \
lsd.hpp \
magnet_uri.hpp \
max.hpp \
natpmp.hpp \
packet_buffer.hpp \
parse_url.hpp \
pe_crypto.hpp \
peer_connection.hpp \
peer.hpp \
peer_id.hpp \
peer_info.hpp \
peer_request.hpp \
piece_block_progress.hpp \
piece_picker.hpp \
policy.hpp \
proxy_base.hpp \
ptime.hpp \
puff.hpp \
random.hpp \
rss.hpp \
session.hpp \
session_settings.hpp \
session_status.hpp \
settings.hpp \
sha1_hash.hpp \
size_type.hpp \
sliding_average.hpp \
socket.hpp \
socket_io.hpp \
socket_type.hpp \
socket_type_fwd.hpp \
socks5_stream.hpp \
ssl_stream.hpp \
stat.hpp \
storage.hpp \
storage_defs.hpp \
string_util.hpp \
thread.hpp \
time.hpp \
timestamp_history.hpp \
torrent_handle.hpp \
torrent.hpp \
torrent_info.hpp \
tracker_manager.hpp \
udp_socket.hpp \
udp_tracker_connection.hpp \
union_endpoint.hpp \
upnp.hpp \
utp_socket_manager.hpp \
utp_stream.hpp \
utf8.hpp \
version.hpp \
web_connection_base.hpp \
web_peer_connection.hpp \
xml_parse.hpp \
\
$(GEOIP_H) \
tommath.h \
tommath_class.h \
tommath_superclass.h \
\
aux_/session_impl.hpp \
\
extensions/logger.hpp \
extensions/lt_trackers.hpp \
extensions/metadata_transfer.hpp \
extensions/smart_ban.hpp \
extensions/ut_metadata.hpp \
extensions/ut_pex.hpp \
\
kademlia/dht_tracker.hpp \
kademlia/dht_observer.hpp \
kademlia/find_data.hpp \
kademlia/logging.hpp \
kademlia/msg.hpp \
kademlia/node.hpp \
kademlia/node_entry.hpp \
kademlia/node_id.hpp \
kademlia/observer.hpp \
kademlia/refresh.hpp \
kademlia/routing_table.hpp \
kademlia/rpc_manager.hpp \
kademlia/traversal_algorithm.hpp \
kademlia/item.hpp \
kademlia/get_item.hpp \
kademlia/get_peers.hpp

View File

@@ -0,0 +1,805 @@
# Makefile.in generated by automake 1.15 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2014 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
VPATH = @srcdir@
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
subdir = include/libtorrent
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_boost_base.m4 \
$(top_srcdir)/m4/ax_boost_python.m4 \
$(top_srcdir)/m4/ax_boost_system.m4 \
$(top_srcdir)/m4/ax_check_geoip.m4 \
$(top_srcdir)/m4/ax_check_openssl.m4 \
$(top_srcdir)/m4/ax_pthread.m4 \
$(top_srcdir)/m4/ax_python_devel.m4 \
$(top_srcdir)/m4/gettext-lib.m4 $(top_srcdir)/m4/iconv.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkgconfig.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__nobase_include_HEADERS_DIST) \
$(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
am__v_GEN_1 =
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 =
SOURCES =
DIST_SOURCES =
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
am__nobase_include_HEADERS_DIST = address.hpp add_torrent_params.hpp \
alert.hpp alert_manager.hpp alert_dispatcher.hpp \
alert_types.hpp alloca.hpp allocator.hpp assert.hpp \
bandwidth_limit.hpp bandwidth_manager.hpp bandwidth_socket.hpp \
bandwidth_queue_entry.hpp bencode.hpp bitfield.hpp \
bloom_filter.hpp broadcast_socket.hpp bt_peer_connection.hpp \
buffer.hpp build_config.hpp chained_buffer.hpp config.hpp \
connection_queue.hpp ConvertUTF.h copy_ptr.hpp \
create_torrent.hpp deadline_timer.hpp debug.hpp \
disk_buffer_holder.hpp disk_buffer_pool.hpp disk_io_thread.hpp \
ed25519.hpp entry.hpp enum_net.hpp error.hpp error_code.hpp \
escape_string.hpp export.hpp extensions.hpp file.hpp \
file_pool.hpp file_storage.hpp fingerprint.hpp gzip.hpp \
hasher.hpp http_connection.hpp http_parser.hpp \
http_seed_connection.hpp http_stream.hpp \
http_tracker_connection.hpp i2p_stream.hpp identify_client.hpp \
instantiate_connection.hpp intrusive_ptr_base.hpp \
invariant_check.hpp io.hpp io_service.hpp io_service_fwd.hpp \
ip_filter.hpp ip_voter.hpp lazy_entry.hpp lsd.hpp \
magnet_uri.hpp max.hpp natpmp.hpp packet_buffer.hpp \
parse_url.hpp pe_crypto.hpp peer_connection.hpp peer.hpp \
peer_id.hpp peer_info.hpp peer_request.hpp \
piece_block_progress.hpp piece_picker.hpp policy.hpp \
proxy_base.hpp ptime.hpp puff.hpp random.hpp rss.hpp \
session.hpp session_settings.hpp session_status.hpp \
settings.hpp sha1_hash.hpp size_type.hpp sliding_average.hpp \
socket.hpp socket_io.hpp socket_type.hpp socket_type_fwd.hpp \
socks5_stream.hpp ssl_stream.hpp stat.hpp storage.hpp \
storage_defs.hpp string_util.hpp thread.hpp time.hpp \
timestamp_history.hpp torrent_handle.hpp torrent.hpp \
torrent_info.hpp tracker_manager.hpp udp_socket.hpp \
udp_tracker_connection.hpp union_endpoint.hpp upnp.hpp \
utp_socket_manager.hpp utp_stream.hpp utf8.hpp version.hpp \
web_connection_base.hpp web_peer_connection.hpp xml_parse.hpp \
GeoIP.h tommath.h tommath_class.h tommath_superclass.h \
aux_/session_impl.hpp extensions/logger.hpp \
extensions/lt_trackers.hpp extensions/metadata_transfer.hpp \
extensions/smart_ban.hpp extensions/ut_metadata.hpp \
extensions/ut_pex.hpp kademlia/dht_tracker.hpp \
kademlia/dht_observer.hpp kademlia/find_data.hpp \
kademlia/logging.hpp kademlia/msg.hpp kademlia/node.hpp \
kademlia/node_entry.hpp kademlia/node_id.hpp \
kademlia/observer.hpp kademlia/refresh.hpp \
kademlia/routing_table.hpp kademlia/rpc_manager.hpp \
kademlia/traversal_algorithm.hpp kademlia/item.hpp \
kademlia/get_item.hpp kademlia/get_peers.hpp
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
am__install_max = 40
am__nobase_strip_setup = \
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
am__nobase_strip = \
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
am__nobase_list = $(am__nobase_strip_setup); \
for p in $$list; do echo "$$p $$p"; done | \
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
if (++n[$$2] == $(am__install_max)) \
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
END { for (dir in files) print dir, files[dir] }'
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__uninstall_files_from_dir = { \
test -z "$$files" \
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
$(am__cd) "$$dir" && rm -f $$files; }; \
}
am__installdirs = "$(DESTDIR)$(includedir)"
HEADERS = $(nobase_include_HEADERS)
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
BEGIN { nonempty = 0; } \
{ items[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique. This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
list='$(am__tagged_files)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
am__DIST_COMMON = $(srcdir)/Makefile.in
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BOOST_CPPFLAGS = @BOOST_CPPFLAGS@
BOOST_LDFLAGS = @BOOST_LDFLAGS@
BOOST_PYTHON_LIB = @BOOST_PYTHON_LIB@
BOOST_SYSTEM_LIB = @BOOST_SYSTEM_LIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
COMPILETIME_OPTIONS = @COMPILETIME_OPTIONS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEBUGFLAGS = @DEBUGFLAGS@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GEOIP_CFLAGS = @GEOIP_CFLAGS@
GEOIP_LIBS = @GEOIP_LIBS@
GREP = @GREP@
ICONV_LIBS = @ICONV_LIBS@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
INTERFACE_VERSION_INFO = @INTERFACE_VERSION_INFO@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBICONV = @LIBICONV@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBICONV = @LTLIBICONV@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OPENSSL_INCLUDES = @OPENSSL_INCLUDES@
OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
OPENSSL_LIBS = @OPENSSL_LIBS@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PKG_CONFIG = @PKG_CONFIG@
PTHREAD_CC = @PTHREAD_CC@
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
PTHREAD_LIBS = @PTHREAD_LIBS@
PYTHON = @PYTHON@
PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@
PYTHON_INSTALL_PARAMS = @PYTHON_INSTALL_PARAMS@
PYTHON_LDFLAGS = @PYTHON_LDFLAGS@
PYTHON_PLATFORM = @PYTHON_PLATFORM@
PYTHON_PREFIX = @PYTHON_PREFIX@
PYTHON_SITE_PKG = @PYTHON_SITE_PKG@
PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
ax_pthread_config = @ax_pthread_config@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@/libtorrent
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
pkgpyexecdir = @pkgpyexecdir@
pkgpythondir = @pkgpythondir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
pyexecdir = @pyexecdir@
pythondir = @pythondir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target = @target@
target_alias = @target_alias@
target_cpu = @target_cpu@
target_os = @target_os@
target_vendor = @target_vendor@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
@WITH_SHIPPED_GEOIP_TRUE@GEOIP_H = GeoIP.h
nobase_include_HEADERS = \
address.hpp \
add_torrent_params.hpp \
alert.hpp \
alert_manager.hpp \
alert_dispatcher.hpp \
alert_types.hpp \
alloca.hpp \
allocator.hpp \
assert.hpp \
bandwidth_limit.hpp \
bandwidth_manager.hpp \
bandwidth_socket.hpp \
bandwidth_queue_entry.hpp \
bencode.hpp \
bitfield.hpp \
bloom_filter.hpp \
broadcast_socket.hpp \
bt_peer_connection.hpp \
buffer.hpp \
build_config.hpp \
chained_buffer.hpp \
config.hpp \
connection_queue.hpp \
ConvertUTF.h \
copy_ptr.hpp \
create_torrent.hpp \
deadline_timer.hpp \
debug.hpp \
disk_buffer_holder.hpp \
disk_buffer_pool.hpp \
disk_io_thread.hpp \
ed25519.hpp \
entry.hpp \
enum_net.hpp \
error.hpp \
error_code.hpp \
escape_string.hpp \
export.hpp \
extensions.hpp \
file.hpp \
file_pool.hpp \
file_storage.hpp \
fingerprint.hpp \
gzip.hpp \
hasher.hpp \
http_connection.hpp \
http_parser.hpp \
http_seed_connection.hpp \
http_stream.hpp \
http_tracker_connection.hpp \
i2p_stream.hpp \
identify_client.hpp \
instantiate_connection.hpp \
intrusive_ptr_base.hpp \
invariant_check.hpp \
io.hpp \
io_service.hpp \
io_service_fwd.hpp \
ip_filter.hpp \
ip_voter.hpp \
lazy_entry.hpp \
lsd.hpp \
magnet_uri.hpp \
max.hpp \
natpmp.hpp \
packet_buffer.hpp \
parse_url.hpp \
pe_crypto.hpp \
peer_connection.hpp \
peer.hpp \
peer_id.hpp \
peer_info.hpp \
peer_request.hpp \
piece_block_progress.hpp \
piece_picker.hpp \
policy.hpp \
proxy_base.hpp \
ptime.hpp \
puff.hpp \
random.hpp \
rss.hpp \
session.hpp \
session_settings.hpp \
session_status.hpp \
settings.hpp \
sha1_hash.hpp \
size_type.hpp \
sliding_average.hpp \
socket.hpp \
socket_io.hpp \
socket_type.hpp \
socket_type_fwd.hpp \
socks5_stream.hpp \
ssl_stream.hpp \
stat.hpp \
storage.hpp \
storage_defs.hpp \
string_util.hpp \
thread.hpp \
time.hpp \
timestamp_history.hpp \
torrent_handle.hpp \
torrent.hpp \
torrent_info.hpp \
tracker_manager.hpp \
udp_socket.hpp \
udp_tracker_connection.hpp \
union_endpoint.hpp \
upnp.hpp \
utp_socket_manager.hpp \
utp_stream.hpp \
utf8.hpp \
version.hpp \
web_connection_base.hpp \
web_peer_connection.hpp \
xml_parse.hpp \
\
$(GEOIP_H) \
tommath.h \
tommath_class.h \
tommath_superclass.h \
\
aux_/session_impl.hpp \
\
extensions/logger.hpp \
extensions/lt_trackers.hpp \
extensions/metadata_transfer.hpp \
extensions/smart_ban.hpp \
extensions/ut_metadata.hpp \
extensions/ut_pex.hpp \
\
kademlia/dht_tracker.hpp \
kademlia/dht_observer.hpp \
kademlia/find_data.hpp \
kademlia/logging.hpp \
kademlia/msg.hpp \
kademlia/node.hpp \
kademlia/node_entry.hpp \
kademlia/node_id.hpp \
kademlia/observer.hpp \
kademlia/refresh.hpp \
kademlia/routing_table.hpp \
kademlia/rpc_manager.hpp \
kademlia/traversal_algorithm.hpp \
kademlia/item.hpp \
kademlia/get_item.hpp \
kademlia/get_peers.hpp
all: all-am
.SUFFIXES:
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign include/libtorrent/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --foreign include/libtorrent/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
install-nobase_includeHEADERS: $(nobase_include_HEADERS)
@$(NORMAL_INSTALL)
@list='$(nobase_include_HEADERS)'; test -n "$(includedir)" || list=; \
if test -n "$$list"; then \
echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \
$(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \
fi; \
$(am__nobase_list) | while read dir files; do \
xfiles=; for file in $$files; do \
if test -f "$$file"; then xfiles="$$xfiles $$file"; \
else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \
test -z "$$xfiles" || { \
test "x$$dir" = x. || { \
echo " $(MKDIR_P) '$(DESTDIR)$(includedir)/$$dir'"; \
$(MKDIR_P) "$(DESTDIR)$(includedir)/$$dir"; }; \
echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(includedir)/$$dir'"; \
$(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(includedir)/$$dir" || exit $$?; }; \
done
uninstall-nobase_includeHEADERS:
@$(NORMAL_UNINSTALL)
@list='$(nobase_include_HEADERS)'; test -n "$(includedir)" || list=; \
$(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \
dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir)
ID: $(am__tagged_files)
$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-am
TAGS: tags
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
$(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: ctags-am
CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
$(am__define_uniq_tagged_files); \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
cscopelist: cscopelist-am
cscopelist-am: $(am__tagged_files)
list='$(am__tagged_files)'; \
case "$(srcdir)" in \
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
*) sdir=$(subdir)/$(srcdir) ;; \
esac; \
for i in $$list; do \
if test -f "$$i"; then \
echo "$(subdir)/$$i"; \
else \
echo "$$sdir/$$i"; \
fi; \
done >> $(top_builddir)/cscope.files
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(HEADERS)
installdirs:
for dir in "$(DESTDIR)$(includedir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic clean-libtool mostlyclean-am
distclean: distclean-am
-rm -f Makefile
distclean-am: clean-am distclean-generic distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am: install-nobase_includeHEADERS
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am:
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man:
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-nobase_includeHEADERS
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
clean-libtool cscopelist-am ctags ctags-am distclean \
distclean-generic distclean-libtool distclean-tags distdir dvi \
dvi-am html html-am info info-am install install-am \
install-data install-data-am install-dvi install-dvi-am \
install-exec install-exec-am install-html install-html-am \
install-info install-info-am install-man \
install-nobase_includeHEADERS install-pdf install-pdf-am \
install-ps install-ps-am install-strip installcheck \
installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-generic \
mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
uninstall-am uninstall-nobase_includeHEADERS
.PRECIOUS: Makefile
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View File

@@ -0,0 +1,402 @@
/*
Copyright (c) 2009-2014, 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_ADD_TORRENT_PARAMS_HPP_INCLUDED
#define TORRENT_ADD_TORRENT_PARAMS_HPP_INCLUDED
#include <string>
#include <vector>
#include <boost/intrusive_ptr.hpp>
#include "libtorrent/storage_defs.hpp"
#include "libtorrent/peer_id.hpp" // sha1_hash
#include "libtorrent/version.hpp"
#ifndef TORRENT_DISABLE_EXTENSIONS
#include "libtorrent/extensions.hpp"
#endif
namespace libtorrent
{
class torrent_info;
class torrent;
struct torrent_plugin;
// The add_torrent_params is a parameter pack for adding torrents to a
// session. The key fields when adding a torrent are:
//
// * ti - when you have a .torrent file
// * url - when you have a magnet link or http URL to the .torrent file
// * info_hash - when all you have is an info-hash (this is similar to a
// magnet link)
//
// one of those fields need to be set. Another mandatory field is
// ``save_path``. The add_torrent_params object is passed into one of the
// ``session::add_torrent()`` overloads or ``session::async_add_torrent()``.
//
// If you only specify the info-hash, the torrent file will be downloaded
// from peers, which requires them to support the metadata extension. For
// the metadata extension to work, libtorrent must be built with extensions
// enabled (``TORRENT_DISABLE_EXTENSIONS`` must not be defined). It also
// takes an optional ``name`` argument. This may be left empty in case no
// name should be assigned to the torrent. In case it's not, the name is
// used for the torrent as long as it doesn't have metadata. See
// ``torrent_handle::name``.
//
struct TORRENT_EXPORT add_torrent_params
{
// The constructor can be used to initialize the storage constructor,
// which determines the storage mechanism for the downloaded or seeding
// data for the torrent. For more information, see the ``storage`` field.
add_torrent_params(storage_constructor_type sc = default_storage_constructor)
: version(LIBTORRENT_VERSION_NUM)
#ifndef TORRENT_NO_DEPRECATE
, tracker_url(0)
#endif
, storage_mode(storage_mode_sparse)
, storage(sc)
, userdata(0)
#ifndef TORRENT_NO_DEPRECATE
, flags(flag_ignore_flags | default_flags)
#else
, flags(default_flags)
#endif
, max_uploads(-1)
, max_connections(-1)
, upload_limit(-1)
, download_limit(-1)
#ifndef TORRENT_NO_DEPRECATE
, seed_mode(false)
, override_resume_data(false)
, upload_mode(false)
, share_mode(false)
, apply_ip_filter(true)
, paused(true)
, auto_managed(true)
, duplicate_is_error(false)
, merge_resume_trackers(false)
#endif
{
}
#ifndef TORRENT_NO_DEPRECATE
void update_flags() const
{
if (flags != (flag_ignore_flags | default_flags)) return;
boost::uint64_t& f = const_cast<boost::uint64_t&>(flags);
f = flag_update_subscribe;
if (seed_mode) f |= flag_seed_mode;
if (override_resume_data) f |= flag_override_resume_data;
if (upload_mode) f |= flag_upload_mode;
if (share_mode) f |= flag_share_mode;
if (apply_ip_filter) f |= flag_apply_ip_filter;
if (paused) f |= flag_paused;
if (auto_managed) f |= flag_auto_managed;
if (duplicate_is_error) f |= flag_duplicate_is_error;
if (merge_resume_trackers) f |= flag_merge_resume_trackers;
}
#endif
// values for the ``flags`` field
enum flags_t
{
// If ``flag_seed_mode`` is set, libtorrent will assume that all files
// are present for this torrent and that they all match the hashes in
// the torrent file. Each time a peer requests to download a block,
// the piece is verified against the hash, unless it has been verified
// already. If a hash fails, the torrent will automatically leave the
// seed mode and recheck all the files. The use case for this mode is
// if a torrent is created and seeded, or if the user already know
// that the files are complete, this is a way to avoid the initial
// file checks, and significantly reduce the startup time.
//
// Setting ``flag_seed_mode`` on a torrent without metadata (a
// .torrent file) is a no-op and will be ignored.
//
// If resume data is passed in with this torrent, the seed mode saved
// in there will override the seed mode you set here.
flag_seed_mode = 0x001,
// If ``flag_override_resume_data`` is set, flags set for this torrent
// in this ``add_torrent_params`` object will take precedence over
// whatever states are saved in the resume data. For instance, the
// ``paused``, ``auto_managed``, ``sequential_download``, ``seed_mode``,
// ``super_seeding``, ``max_uploads``, ``max_connections``,
// ``upload_limit`` and ``download_limit`` are all affected by this
// flag. The intention of this flag is to have any field in
// add_torrent_params configuring the torrent override the corresponding
// configuration from the resume file, with the one exception of save
// resume data, which has its own flag (for historic reasons).
flag_override_resume_data = 0x002,
// If ``flag_upload_mode`` is set, the torrent will be initialized in
// upload-mode, which means it will not make any piece requests. This
// state is typically entered on disk I/O errors, and if the torrent
// is also auto managed, it will be taken out of this state
// periodically. This mode can be used to avoid race conditions when
// adjusting priorities of pieces before allowing the torrent to start
// downloading.
//
// If the torrent is auto-managed (``flag_auto_managed``), the torrent
// will eventually be taken out of upload-mode, regardless of how it
// got there. If it's important to manually control when the torrent
// leaves upload mode, don't make it auto managed.
flag_upload_mode = 0x004,
// determines if the torrent should be added in *share mode* or not.
// Share mode indicates that we are not interested in downloading the
// torrent, but merley want to improve our share ratio (i.e. increase
// it). A torrent started in share mode will do its best to never
// download more than it uploads to the swarm. If the swarm does not
// have enough demand for upload capacity, the torrent will not
// download anything. This mode is intended to be safe to add any
// number of torrents to, without manual screening, without the risk
// of downloading more than is uploaded.
//
// A torrent in share mode sets the priority to all pieces to 0,
// except for the pieces that are downloaded, when pieces are decided
// to be downloaded. This affects the progress bar, which might be set
// to "100% finished" most of the time. Do not change file or piece
// priorities for torrents in share mode, it will make it not work.
//
// The share mode has one setting, the share ratio target, see
// ``session_settings::share_mode_target`` for more info.
flag_share_mode = 0x008,
// determines if the IP filter should apply to this torrent or not. By
// default all torrents are subject to filtering by the IP filter
// (i.e. this flag is set by default). This is useful if certain
// torrents needs to be excempt for some reason, being an auto-update
// torrent for instance.
flag_apply_ip_filter = 0x010,
// specifies whether or not the torrent is to be started in a paused
// state. I.e. it won't connect to the tracker or any of the peers
// until it's resumed. This is typically a good way of avoiding race
// conditions when setting configuration options on torrents before
// starting them.
flag_paused = 0x020,
// If the torrent is auto-managed (``flag_auto_managed``), the torrent
// may be resumed at any point, regardless of how it paused. If it's
// important to manually control when the torrent is paused and
// resumed, don't make it auto managed.
//
// If ``flag_auto_managed`` is set, the torrent will be queued,
// started and seeded automatically by libtorrent. When this is set,
// the torrent should also be started as paused. The default queue
// order is the order the torrents were added. They are all downloaded
// in that order. For more details, see queuing_.
//
// If you pass in resume data, the auto_managed state of the torrent
// when the resume data was saved will override the auto_managed state
// you pass in here. You can override this by setting
// ``override_resume_data``.
flag_auto_managed = 0x040,
flag_duplicate_is_error = 0x080,
// defaults to off and specifies whether tracker URLs loaded from
// resume data should be added to the trackers in the torrent or
// replace the trackers.
flag_merge_resume_trackers = 0x100,
// on by default and means that this torrent will be part of state
// updates when calling post_torrent_updates().
flag_update_subscribe = 0x200,
// sets the torrent into super seeding mode. If the torrent is not a
// seed, this flag has no effect. It has the same effect as calling
// ``torrent_handle::super_seeding(true)`` on the torrent handle
// immediately after adding it.
flag_super_seeding = 0x400,
// sets the sequential download state for the torrent. It has the same
// effect as calling ``torrent_handle::sequential_download(true)`` on
// the torrent handle immediately after adding it.
flag_sequential_download = 0x800,
// if this flag is set, the save path from the resume data file, if
// present, is honored. This defaults to not being set, in which
// case the save_path specified in add_torrent_params is always used.
flag_use_resume_save_path = 0x1000,
// internal
default_flags = 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.
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;
#ifndef TORRENT_NO_DEPRECATE
char const* tracker_url;
#endif
// If the torrent doesn't have a tracker, but relies on the DHT to find
// peers, the ``trackers`` can specify tracker URLs for the torrent.
std::vector<std::string> trackers;
// url seeds to be added to the torrent (`BEP 17`_).
std::vector<std::string> url_seeds;
// a list of hostname and port pairs, representing DHT nodes to be added
// to the session (if DHT is enabled). The hostname may be an IP address.
std::vector<std::pair<std::string, int> > dht_nodes;
std::string name;
// the path where the torrent is or will be stored. Note that this may
// alos be stored in resume data. If you want the save path saved in
// the resume data to be used, you need to set the
// flag_use_resume_save_path flag.
//
// .. note::
// On windows this path (and other paths) are interpreted as UNC
// paths. This means they must use backslashes as directory separators
// and may not contain the special directories "." or "..".
std::string save_path;
// The optional parameter, ``resume_data`` can be given if up to date
// fast-resume data is available. The fast-resume data can be acquired
// from a running torrent by calling save_resume_data() on
// torrent_handle. See fast-resume_. The ``vector`` that is passed in
// will be swapped into the running torrent instance with
// ``std::vector::swap()``.
std::vector<char> resume_data;
// One of the values from storage_mode_t. For more information, see
// storage-allocation_.
storage_mode_t storage_mode;
// can be used to customize how the data is stored. The default storage
// will simply write the data to the files it belongs to, but it could be
// overridden to save everything to a single file at a specific location
// or encrypt the content on disk for instance. For more information
// about the storage_interface that needs to be implemented for a custom
// storage, see storage_interface.
storage_constructor_type storage;
// The ``userdata`` parameter is optional and will be passed on to the
// extension constructor functions, if any (see `add_extension()`_).
void* userdata;
// can be set to control the initial file priorities when adding a
// torrent. The semantics are the same as for
// ``torrent_handle::prioritize_files()``.
std::vector<boost::uint8_t> file_priorities;
// torrent extension construction functions can be added to this vector
// to have them be added immediately when the torrent is constructed.
// This may be desired over the torrent_handle::add_extension() in order
// to avoid race conditions. For instance it may be important to have the
// plugin catch events that happen very early on after the torrent is
// created.
std::vector<boost::function<boost::shared_ptr<torrent_plugin>(torrent*, void*)> >
extensions;
// the default tracker id to be used when announcing to trackers. By
// default this is empty, and no tracker ID is used, since this is an
// optional argument. If a tracker returns a tracker ID, that ID is used
// instead of this.
std::string trackerid;
// If you specify a ``url``, the torrent will be set in
// ``downloading_metadata`` state until the .torrent file has been
// downloaded. If there's any error while downloading, the torrent will
// be stopped and the torrent error state (``torrent_status::error``)
// will indicate what went wrong. The ``url`` may refer to a magnet link
// or a regular http URL.
//
// If it refers to an HTTP URL, the info-hash for the added torrent will
// not be the true info-hash of the .torrent. Instead a placeholder,
// unique, info-hash is used which is later updated once the .torrent
// file has been downloaded.
//
// Once the info-hash change happens, a torrent_update_alert is posted.
std::string url;
// if ``uuid`` is specified, it is used to find duplicates. If another
// torrent is already running with the same UUID as the one being added,
// it will be considered a duplicate. This is mainly useful for RSS feed
// 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.
std::string source_feed_url;
// flags controlling aspects of this torrent and how it's added. See
// flags_t for details.
boost::uint64_t flags;
// set this to the info hash of the torrent to add in case the info-hash
// is the only known property of the torrent. i.e. you don't have a
// .torrent file nor a magnet link.
sha1_hash info_hash;
// ``max_uploads``, ``max_connections``, ``upload_limit``,
// ``download_limit`` correspond to the ``set_max_uploads()``,
// ``set_max_connections()``, ``set_upload_limit()`` and
// ``set_download_limit()`` functions on torrent_handle. These values let
// you initialize these settings when the torrent is added, instead of
// calling these functions immediately following adding it.
//
// -1 means unlimited on these settings just like their counterpart
// functions on torrent_handle
int max_uploads;
int max_connections;
int upload_limit;
int download_limit;
#ifndef TORRENT_NO_DEPRECATE
bool seed_mode;
bool override_resume_data;
bool upload_mode;
bool share_mode;
bool apply_ip_filter;
bool paused;
bool auto_managed;
bool duplicate_is_error;
bool merge_resume_trackers;
#endif
};
}
#endif

View File

@@ -0,0 +1,77 @@
/*
Copyright (c) 2009-2014, 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_ADDRESS_HPP_INCLUDED
#define TORRENT_ADDRESS_HPP_INCLUDED
#include <boost/version.hpp>
#include "libtorrent/config.hpp"
#ifdef __OBJC__
#define Protocol Protocol_
#endif
#if defined TORRENT_WINDOWS || defined TORRENT_CYGWIN
// asio assumes that the windows error codes are defined already
#include <winsock2.h>
#endif
#if BOOST_VERSION < 103500
#include <asio/ip/address.hpp>
#else
#include <boost/asio/ip/address.hpp>
#endif
#ifdef __OBJC__
#undef Protocol
#endif
namespace libtorrent
{
#if BOOST_VERSION < 103500
typedef ::asio::ip::address address;
typedef ::asio::ip::address_v4 address_v4;
#if TORRENT_USE_IPV6
typedef ::asio::ip::address_v6 address_v6;
#endif
#else
typedef boost::asio::ip::address address;
typedef boost::asio::ip::address_v4 address_v4;
#if TORRENT_USE_IPV6
typedef boost::asio::ip::address_v6 address_v6;
#endif
#endif
}
#endif

View File

@@ -0,0 +1,319 @@
/*
Copyright (c) 2003-2014, Arvid Norberg, Daniel Wallin
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_HPP_INCLUDED
#define TORRENT_ALERT_HPP_INCLUDED
#include <memory>
#include <deque>
#include <string>
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_shifted_params.hpp>
#include <boost/preprocessor/repetition/enum_shifted_binary_params.hpp>
// OVERVIEW
//
// The pop_alerts() function on session is the main interface for retrieving
// alerts (warnings, messages and errors from libtorrent). If no alerts have
// been posted by libtorrent pop_alert() will return an empty list.
//
// By default, only errors are reported. set_alert_mask() can be used to
// specify which kinds of events should be reported. The alert mask is
// comprised by bits from the category_t enum.
//
// Every alert belongs to one or more category. There is a small cost involved
// in posting alerts. Only alerts that belong to an enabled category are
// posted. Setting the alert bitmask to 0 will disable all alerts (except those
// that are non-discardable).
//
// There are other alert base classes that some alerts derive from, all the
// alerts that are generated for a specific torrent are derived from
// torrent_alert, and tracker events derive from tracker_alert.
//
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/ptime.hpp"
#include "libtorrent/config.hpp"
#ifndef TORRENT_NO_DEPRECATE
#ifndef BOOST_NO_TYPEID
#include <typeinfo>
#endif
#endif // TORRENT_NO_DEPRECATE
#ifndef TORRENT_MAX_ALERT_TYPES
#define TORRENT_MAX_ALERT_TYPES 15
#endif
namespace libtorrent {
// The ``alert`` class is the base class that specific messages are derived from.
class TORRENT_EXPORT alert
{
public:
#ifndef TORRENT_NO_DEPRECATE
// only here for backwards compatibility
enum severity_t { debug, info, warning, critical, fatal, none };
#endif
// these are bits for the alert_mask used by the session. See set_alert_mask().
enum category_t
{
// Enables alerts that report an error. This includes:
//
// * tracker errors
// * tracker warnings
// * file errors
// * resume data failures
// * web seed errors
// * .torrent files errors
// * listen socket errors
// * port mapping errors
error_notification = 0x1,
// Enables alerts when peers send invalid requests, get banned or
// snubbed.
peer_notification = 0x2,
// Enables alerts for port mapping events. For NAT-PMP and UPnP.
port_mapping_notification = 0x4,
// Enables alerts for events related to the storage. File errors and
// synchronization events for moving the storage, renaming files etc.
storage_notification = 0x8,
// Enables all tracker events. Includes announcing to trackers,
// receiving responses, warnings and errors.
tracker_notification = 0x10,
// Low level alerts for when peers are connected and disconnected.
debug_notification = 0x20,
// Enables alerts for when a torrent or the session changes state.
status_notification = 0x40,
// Alerts for when blocks are requested and completed. Also when
// pieces are completed.
progress_notification = 0x80,
// Alerts when a peer is blocked by the ip blocker or port blocker.
ip_block_notification = 0x100,
// Alerts when some limit is reached that might limit the download
// or upload rate.
performance_warning = 0x200,
// Alerts on events in the DHT node. For incoming searches or
// bootstrapping being done etc.
dht_notification = 0x400,
// If you enable these alerts, you will receive a stats_alert
// approximately once every second, for every active torrent.
// These alerts contain all statistics counters for the interval since
// the lasts stats alert.
stats_notification = 0x800,
// Alerts on RSS related events, like feeds being updated, feed error
// conditions and successful RSS feed updates. Enabling this categoty
// will make you receive rss_alert alerts.
rss_notification = 0x1000,
// The full bitmask, representing all available categories.
//
// since the enum is signed, make sure this isn't
// interpreted as -1. For instance, boost.python
// does that and fails when assigning it to an
// unsigned parameter.
all_categories = 0x7fffffff
};
// hidden
alert();
// hidden
virtual ~alert();
// a timestamp is automatically created in the constructor
ptime timestamp() const;
// returns an integer that is unique to this alert type. It can be
// compared against a specific alert by querying a static constant called ``alert_type``
// in the alert. It can be used to determine the run-time type of an alert* in
// order to cast to that alert type and access specific members.
//
// e.g:
//
// .. code:: c++
//
// std::auto_ptr<alert> a = ses.pop_alert();
// switch (a->type())
// {
// case read_piece_alert::alert_type:
// {
// read_piece_alert* p = (read_piece_alert*)a.get();
// if (p->ec) {
// // read_piece failed
// break;
// }
// // use p
// break;
// }
// case file_renamed_alert::alert_type:
// {
// // etc...
// }
// }
virtual int type() const = 0;
// returns a string literal describing the type of the alert. It does
// not include any information that might be bundled with the alert.
virtual char const* what() const = 0;
// generate a string describing the alert and the information bundled
// with it. This is mainly intended for debug and development use. It is not suitable
// to use this for applications that may be localized. Instead, handle each alert
// type individually and extract and render the information from the alert depending
// on the locale.
virtual std::string message() const = 0;
// returns a bitmask specifying which categories this alert belong to.
virtual int category() const = 0;
// determines whether or not an alert is allowed to be discarded
// when the alert queue is full. There are a few alerts which may not be discared,
// since they would break the user contract, such as save_resume_data_alert.
virtual bool discardable() const { return true; }
#ifndef TORRENT_NO_DEPRECATE
TORRENT_DEPRECATED_PREFIX
severity_t severity() const TORRENT_DEPRECATED { return warning; }
#endif
// returns a pointer to a copy of the alert.
virtual std::auto_ptr<alert> clone() const = 0;
private:
ptime m_timestamp;
};
#ifndef BOOST_NO_EXCEPTIONS
#ifndef TORRENT_NO_DEPRECATE
struct TORRENT_EXPORT unhandled_alert : std::exception
{
unhandled_alert() {}
};
#ifndef BOOST_NO_TYPEID
namespace detail {
struct void_;
template<class Handler
, BOOST_PP_ENUM_PARAMS(TORRENT_MAX_ALERT_TYPES, class T)>
void handle_alert_dispatch(
const std::auto_ptr<alert>& alert_, const Handler& handler
, const std::type_info& typeid_
, T0*, BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS(TORRENT_MAX_ALERT_TYPES, T, *p))
{
if (typeid_ == typeid(T0))
handler(*static_cast<T0*>(alert_.get()));
else
handle_alert_dispatch(alert_, handler, typeid_
, BOOST_PP_ENUM_SHIFTED_PARAMS(
TORRENT_MAX_ALERT_TYPES, p), (void_*)0);
}
template<class Handler>
void handle_alert_dispatch(
const std::auto_ptr<alert>&
, const Handler&
, const std::type_info&
, BOOST_PP_ENUM_PARAMS(TORRENT_MAX_ALERT_TYPES, void_* BOOST_PP_INTERCEPT))
{
throw unhandled_alert();
}
} // namespace detail
template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(
TORRENT_MAX_ALERT_TYPES, class T, detail::void_)>
struct TORRENT_EXPORT handle_alert
{
template<class Handler>
handle_alert(const std::auto_ptr<alert>& alert_
, const Handler& handler)
{
#define ALERT_POINTER_TYPE(z, n, text) (BOOST_PP_CAT(T, n)*)0
detail::handle_alert_dispatch(alert_, handler, typeid(*alert_)
, BOOST_PP_ENUM(TORRENT_MAX_ALERT_TYPES, ALERT_POINTER_TYPE, _));
#undef ALERT_POINTER_TYPE
}
};
#endif // BOOST_NO_TYPEID
#endif // TORRENT_NO_DEPRECATE
#endif // BOOST_NO_EXCEPTIONS
// When you get an alert, you can use ``alert_cast<>`` to attempt to cast the pointer to a
// more specific alert type, in order to query it for more information.
template <class T>
T* alert_cast(alert* a)
{
if (a == 0) return 0;
if (a->type() == T::alert_type) return static_cast<T*>(a);
return 0;
}
template <class T>
T const* alert_cast(alert const* a)
{
if (a == 0) return 0;
if (a->type() == T::alert_type) return static_cast<T const*>(a);
return 0;
}
} // namespace libtorrent
#endif // TORRENT_ALERT_HPP_INCLUDED

View File

@@ -0,0 +1,50 @@
/*
Copyright (c) 2012-2014, 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_DISPATCHER_HPP_INCLUDED
#define TORRENT_ALERT_DISPATCHER_HPP_INCLUDED
namespace libtorrent
{
class alert;
struct alert_dispatcher
{
// return true if the alert was swallowed (i.e.
// ownership was taken over). In this case, the
// alert will not be passed on to any one else
virtual bool post_alert(alert* a) = 0;
};
}
#endif

View File

@@ -0,0 +1,114 @@
/*
Copyright (c) 2003-2014, Arvid Norberg, Daniel Wallin
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_MANAGER_HPP_INCLUDED
#define TORRENT_ALERT_MANAGER_HPP_INCLUDED
#include "libtorrent/config.hpp"
#include "libtorrent/alert.hpp"
#include "libtorrent/thread.hpp"
#include <boost/function/function1.hpp>
#include <boost/shared_ptr.hpp>
#include <list>
namespace libtorrent {
#ifndef TORRENT_DISABLE_EXTENSIONS
struct plugin;
#endif
class TORRENT_EXTRA_EXPORT alert_manager
{
public:
alert_manager(int queue_limit
, boost::uint32_t alert_mask = alert::error_notification);
~alert_manager();
void post_alert(const alert& alert_);
void post_alert_ptr(alert* alert_);
bool pending() const;
std::auto_ptr<alert> get();
void get_all(std::deque<alert*>* alerts);
template <class T>
bool should_post() const
{
mutex::scoped_lock lock(m_mutex);
if (m_alerts.size() >= m_queue_size_limit) return false;
return (m_alert_mask & T::static_category) != 0;
}
bool should_post(alert const* a) const
{
return (m_alert_mask & a->category()) != 0;
}
alert const* wait_for_alert(time_duration max_wait);
void set_alert_mask(boost::uint32_t m)
{
mutex::scoped_lock lock(m_mutex);
m_alert_mask = m;
}
int alert_mask() const { return m_alert_mask; }
size_t alert_queue_size_limit() const { return m_queue_size_limit; }
size_t set_alert_queue_size_limit(size_t queue_size_limit_);
void set_dispatch_function(boost::function<void(std::auto_ptr<alert>)> const&);
#ifndef TORRENT_DISABLE_EXTENSIONS
void add_extension(boost::shared_ptr<plugin> ext);
#endif
private:
void post_impl(std::auto_ptr<alert>& alert_, mutex::scoped_lock& l);
std::deque<alert*> m_alerts;
mutable mutex m_mutex;
condition_variable m_condition;
boost::uint32_t m_alert_mask;
size_t m_queue_size_limit;
boost::function<void(std::auto_ptr<alert>)> m_dispatch;
#ifndef TORRENT_DISABLE_EXTENSIONS
typedef std::list<boost::shared_ptr<plugin> > ses_extension_list_t;
ses_extension_list_t m_ses_extensions;
#endif
};
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,54 @@
/*
Copyright (c) 2008-2014, 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_ALLOCA
#include "libtorrent/config.hpp"
#if defined TORRENT_WINDOWS || defined TORRENT_MINGW
#include <malloc.h>
#define TORRENT_ALLOCA(t, n) static_cast<t*>(_alloca(sizeof(t) * (n)))
#elif defined TORRENT_BSD
#include <stdlib.h>
#define TORRENT_ALLOCA(t, n) static_cast<t*>(alloca(sizeof(t) * (n)))
#else
#include <alloca.h>
#define TORRENT_ALLOCA(t, n) static_cast<t*>(alloca(sizeof(t) * (n)))
#endif
#endif

View File

@@ -0,0 +1,79 @@
/*
Copyright (c) 2009-2014, 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_ALLOCATOR_HPP_INCLUDED
#define TORRENT_ALLOCATOR_HPP_INCLUDED
#include <cstddef>
#include "libtorrent/config.hpp"
namespace libtorrent
{
TORRENT_EXTRA_EXPORT int page_size();
struct TORRENT_EXTRA_EXPORT page_aligned_allocator
{
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
static char* malloc(const size_type bytes);
static void free(char* block);
};
struct TORRENT_EXTRA_EXPORT aligned_holder
{
aligned_holder(): m_buf(0) {}
aligned_holder(int size): m_buf(page_aligned_allocator::malloc(size)) {}
~aligned_holder() { if (m_buf) page_aligned_allocator::free(m_buf); }
char* get() const { return m_buf; }
void reset(char* buf = 0)
{
if (m_buf) page_aligned_allocator::free(m_buf);
m_buf = buf;
}
void swap(aligned_holder& h)
{
char* tmp = m_buf;
m_buf = h.m_buf;
h.m_buf = tmp;
}
private:
aligned_holder(aligned_holder const&);
aligned_holder& operator=(aligned_holder const&);
char* m_buf;
};
}
#endif

View File

@@ -0,0 +1,89 @@
/*
Copyright (c) 2007-2014, 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_ASSERT
#include "libtorrent/config.hpp"
#if defined TORRENT_DEBUG || defined TORRENT_ASIO_DEBUGGING \
|| TORRENT_RELEASE_ASSERTS || defined TORRENT_DEBUG_BUFFERS
#include <string>
std::string demangle(char const* name);
TORRENT_EXPORT void print_backtrace(char* out, int len, int max_depth = 0);
#endif
#if TORRENT_USE_ASSERTS
#if TORRENT_PRODUCTION_ASSERTS
extern char const* libtorrent_assert_log;
#endif
#if (defined __linux__ || defined __MACH__) && defined __GNUC__ && !TORRENT_USE_SYSTEM_ASSERT
#if TORRENT_USE_IOSTREAM
#include <sstream>
#endif
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)
#define TORRENT_ASSERT(x) \
do { if (x) {} else assert_fail(#x, __LINE__, __FILE__, __PRETTY_FUNCTION__, "", 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)
#else
#define TORRENT_ASSERT_VAL(x, y) TORRENT_ASSERT(x)
#endif
#else
#include <cassert>
#define TORRENT_ASSERT_PRECOND(x) assert(x)
#define TORRENT_ASSERT(x) assert(x)
#define TORRENT_ASSERT_VAL(x, y) assert(x)
#endif
#else // TORRENT_USE_ASSERTS
#define TORRENT_ASSERT_PRECOND(a) do {} while(false)
#define TORRENT_ASSERT(a) do {} while(false)
#define TORRENT_ASSERT_VAL(a, b) do {} while(false)
#endif // TORRENT_USE_ASSERTS
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,101 @@
/*
Copyright (c) 2007-2014, 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_BANDWIDTH_CHANNEL_HPP_INCLUDED
#define TORRENT_BANDWIDTH_CHANNEL_HPP_INCLUDED
#include <boost/integer_traits.hpp>
#include <boost/cstdint.hpp>
#include "libtorrent/assert.hpp"
namespace libtorrent {
// member of peer_connection
struct TORRENT_EXTRA_EXPORT bandwidth_channel
{
static const int inf = boost::integer_traits<int>::const_max;
bandwidth_channel();
// 0 means infinite
void throttle(int limit);
int throttle() const
{
TORRENT_ASSERT_VAL(m_limit < INT_MAX, m_limit);
return int(m_limit);
}
int quota_left() const;
void update_quota(int dt_milliseconds);
// this is used when connections disconnect with
// some quota left. It's returned to its bandwidth
// channels.
void return_quota(int amount);
void use_quota(int amount);
// this is an optimization. If there is more than one second
// of quota built up in this channel, just apply it right away
// instead of introducing a delay to split it up evenly. This
// should especially help in situations where a single peer
// has a capacity under the rate limit, but would otherwise be
// held back by the latency of getting bandwidth from the limiter
bool need_queueing(int amount)
{
if (m_quota_left - amount < m_limit) return true;
m_quota_left -= amount;
return false;
}
// used as temporary storage while distributing
// bandwidth
int tmp;
// this is the number of bytes to distribute this round
int distribute_quota;
private:
// this is the amount of bandwidth we have
// been assigned without using yet.
boost::int64_t m_quota_left;
// the limit is the number of bytes
// per second we are allowed to use.
boost::int64_t m_limit;
};
}
#endif

View File

@@ -0,0 +1,116 @@
/*
Copyright (c) 2007-2014, 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_BANDWIDTH_MANAGER_HPP_INCLUDED
#define TORRENT_BANDWIDTH_MANAGER_HPP_INCLUDED
#include <boost/intrusive_ptr.hpp>
#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT
#include <fstream>
#endif
#include "libtorrent/socket.hpp"
#include "libtorrent/error_code.hpp"
#include "libtorrent/invariant_check.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/bandwidth_limit.hpp"
#include "libtorrent/bandwidth_queue_entry.hpp"
#include "libtorrent/thread.hpp"
#include "libtorrent/bandwidth_socket.hpp"
#include "libtorrent/ptime.hpp"
using boost::intrusive_ptr;
namespace libtorrent {
struct TORRENT_EXTRA_EXPORT bandwidth_manager
{
bandwidth_manager(int channel
#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT
, bool log = false
#endif
);
void close();
#if TORRENT_USE_ASSERTS
bool is_queued(bandwidth_socket const* peer) const;
#endif
int queue_size() const;
boost::int64_t queued_bytes() const;
// non prioritized means that, if there's a line for bandwidth,
// others will cut in front of the non-prioritized peers.
// 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);
#if TORRENT_USE_INVARIANT_CHECKS
void check_invariant() const;
#endif
void update_quotas(time_duration const& dt);
private:
// these are the consumers that want bandwidth
typedef std::vector<bw_request> queue_t;
queue_t m_queue;
// the number of bytes all the requests in queue are for
boost::int64_t m_queued_bytes;
// this is the channel within the consumers
// that bandwidth is assigned to (upload or download)
int m_channel;
bool m_abort;
#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT
std::ofstream m_log;
ptime m_start;
#endif
};
}
#endif

View File

@@ -0,0 +1,73 @@
/*
Copyright (c) 2007-2014, 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_BANDWIDTH_QUEUE_ENTRY_HPP_INCLUDED
#define TORRENT_BANDWIDTH_QUEUE_ENTRY_HPP_INCLUDED
#include <boost/intrusive_ptr.hpp>
#include "libtorrent/bandwidth_limit.hpp"
#include "libtorrent/bandwidth_socket.hpp"
namespace libtorrent {
struct TORRENT_EXTRA_EXPORT bw_request
{
bw_request(boost::intrusive_ptr<bandwidth_socket> const& pe
, int blk, int prio);
boost::intrusive_ptr<bandwidth_socket> peer;
// 1 is normal prio
int priority;
// the number of bytes assigned to this request so far
int assigned;
// once assigned reaches this, we dispatch the request function
int request_size;
// the max number of rounds for this request to survive
// this ensures that requests gets responses at very low
// rate limits, when the requested size would take a long
// time to satisfy
int ttl;
// loops over the bandwidth channels and assigns bandwidth
// from the most limiting one
int assign_bandwidth();
enum { max_bandwidth_channels = 5 };
// we don't actually support more than 5 channels per peer
bandwidth_channel* channel[max_bandwidth_channels];
};
}
#endif

View File

@@ -0,0 +1,51 @@
/*
Copyright (c) 2009-2014, 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_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;
virtual ~bandwidth_socket() {}
};
}
#endif // TORRENT_BANDWIDTH_SOCKET_HPP_INCLUDED

View File

@@ -0,0 +1,465 @@
/*
Copyright (c) 2003-2014, 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_BENCODE_HPP_INCLUDED
#define TORRENT_BENCODE_HPP_INCLUDED
// OVERVIEW
//
// 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.
//
// 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 `BEP 3`_.
//
// There are two mechanims to *decode* bencoded buffers in libtorrent.
//
// The most flexible one is bdecode(), which returns a structure
// represented by entry. When a buffer is decoded with this function,
// it can be discarded. The entry does not contain any references back
// to it. This means that bdecode() 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.
//
// Another consideration is that bdecode() 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.
//
// The second mechanism is lazy_bdecode(), which returns a
// bencoded structure represented by lazy_entry. This function
// builds a tree that points back into the original buffer.
// The returned lazy_entry will not be valid once the buffer
// it was parsed out of is discarded.
//
// 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.
#include <stdlib.h>
#include <string>
#include <exception>
#include <iterator> // for distance
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/static_assert.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/entry.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/escape_string.hpp"
#include "libtorrent/io.hpp" // for write_string
namespace libtorrent
{
#ifndef TORRENT_NO_DEPRECATE
// thrown by bdecode() if the provided bencoded buffer does not contain
// valid encoding.
struct TORRENT_EXPORT invalid_encoding: std::exception
{
// hidden
virtual const char* what() const throw() { return "invalid bencoding"; }
};
#endif
namespace detail
{
// this is used in the template, so it must be available to the client
TORRENT_EXPORT char const* integer_to_str(char* buf, int size
, entry::integer_type val);
template <class OutIt>
int write_integer(OutIt& out, entry::integer_type val)
{
// the stack allocated buffer for keeping the
// decimal representation of the number can
// not hold number bigger than this:
BOOST_STATIC_ASSERT(sizeof(entry::integer_type) <= 8);
char buf[21];
int ret = 0;
for (char const* str = integer_to_str(buf, 21, val);
*str != 0; ++str)
{
*out = *str;
++out;
++ret;
}
return ret;
}
template <class OutIt>
void write_char(OutIt& out, char c)
{
*out = c;
++out;
}
template <class InIt>
std::string read_until(InIt& in, InIt end, char end_token, bool& err)
{
std::string ret;
if (in == end)
{
err = true;
return ret;
}
while (*in != end_token)
{
ret += *in;
++in;
if (in == end)
{
err = true;
return ret;
}
}
return ret;
}
template<class InIt>
void read_string(InIt& in, InIt end, int len, std::string& str, bool& err)
{
TORRENT_ASSERT(len >= 0);
for (int i = 0; i < len; ++i)
{
if (in == end)
{
err = true;
return;
}
str += *in;
++in;
}
}
template<class OutIt>
int bencode_recursive(OutIt& out, const entry& e)
{
int ret = 0;
switch(e.type())
{
case entry::int_t:
write_char(out, 'i');
ret += write_integer(out, e.integer());
write_char(out, 'e');
ret += 2;
break;
case entry::string_t:
ret += write_integer(out, e.string().length());
write_char(out, ':');
ret += write_string(e.string(), out);
ret += 1;
break;
case entry::list_t:
write_char(out, 'l');
for (entry::list_type::const_iterator i = e.list().begin(); i != e.list().end(); ++i)
ret += bencode_recursive(out, *i);
write_char(out, 'e');
ret += 2;
break;
case entry::dictionary_t:
write_char(out, 'd');
for (entry::dictionary_type::const_iterator i = e.dict().begin();
i != e.dict().end(); ++i)
{
// write key
ret += write_integer(out, i->first.length());
write_char(out, ':');
ret += write_string(i->first, out);
// write value
ret += bencode_recursive(out, i->second);
ret += 1;
}
write_char(out, 'e');
ret += 2;
break;
default:
// trying to encode a structure with uninitialized values!
TORRENT_ASSERT_VAL(false, e.type());
// do nothing
break;
}
return ret;
}
template<class InIt>
void bdecode_recursive(InIt& in, InIt end, entry& ret, bool& err, int depth)
{
if (depth >= 100)
{
err = true;
return;
}
if (in == end)
{
err = true;
#ifdef TORRENT_DEBUG
ret.m_type_queried = false;
#endif
return;
}
switch (*in)
{
// ----------------------------------------------
// integer
case 'i':
{
++in; // 'i'
std::string val = read_until(in, end, 'e', err);
if (err) return;
TORRENT_ASSERT(*in == 'e');
++in; // 'e'
ret = entry(entry::int_t);
char* end_pointer;
ret.integer() = strtoll(val.c_str(), &end_pointer, 10);
#ifdef TORRENT_DEBUG
ret.m_type_queried = false;
#endif
if (end_pointer == val.c_str())
{
err = true;
return;
}
} break;
// ----------------------------------------------
// list
case 'l':
{
ret = entry(entry::list_t);
++in; // 'l'
while (*in != 'e')
{
ret.list().push_back(entry());
entry& e = ret.list().back();
bdecode_recursive(in, end, e, err, depth + 1);
if (err)
{
#ifdef TORRENT_DEBUG
ret.m_type_queried = false;
#endif
return;
}
if (in == end)
{
err = true;
#ifdef TORRENT_DEBUG
ret.m_type_queried = false;
#endif
return;
}
}
#ifdef TORRENT_DEBUG
ret.m_type_queried = false;
#endif
TORRENT_ASSERT(*in == 'e');
++in; // 'e'
} break;
// ----------------------------------------------
// dictionary
case 'd':
{
ret = entry(entry::dictionary_t);
++in; // 'd'
while (*in != 'e')
{
entry key;
bdecode_recursive(in, end, key, err, depth + 1);
if (err || key.type() != entry::string_t)
{
#ifdef TORRENT_DEBUG
ret.m_type_queried = false;
#endif
return;
}
entry& e = ret[key.string()];
bdecode_recursive(in, end, e, err, depth + 1);
if (err)
{
#ifdef TORRENT_DEBUG
ret.m_type_queried = false;
#endif
return;
}
if (in == end)
{
err = true;
#ifdef TORRENT_DEBUG
ret.m_type_queried = false;
#endif
return;
}
}
#ifdef TORRENT_DEBUG
ret.m_type_queried = false;
#endif
TORRENT_ASSERT(*in == 'e');
++in; // 'e'
} break;
// ----------------------------------------------
// string
default:
if (is_digit((unsigned char)*in))
{
std::string len_s = read_until(in, end, ':', err);
if (err)
{
#ifdef TORRENT_DEBUG
ret.m_type_queried = false;
#endif
return;
}
TORRENT_ASSERT(*in == ':');
++in; // ':'
int len = atoi(len_s.c_str());
ret = entry(entry::string_t);
read_string(in, end, len, ret.string(), err);
if (err)
{
#ifdef TORRENT_DEBUG
ret.m_type_queried = false;
#endif
return;
}
}
else
{
err = true;
#ifdef TORRENT_DEBUG
ret.m_type_queried = false;
#endif
return;
}
#ifdef TORRENT_DEBUG
ret.m_type_queried = false;
#endif
}
}
}
// These functions will encode data to bencoded_ or decode bencoded_ data.
//
// If possible, lazy_bdecode() should be preferred over ``bdecode()``.
//
// The entry_ class is the internal representation of the bencoded data
// and it can be used to retrieve information, an entry_ can also be build by
// the program and given to ``bencode()`` to encode it into the ``OutIt``
// iterator.
//
// The ``OutIt`` and ``InIt`` are iterators
// (InputIterator_ and OutputIterator_ respectively). They
// are templates and are usually instantiated as ostream_iterator_,
// back_insert_iterator_ or istream_iterator_. These
// functions will assume that the iterator refers to a character
// (``char``). So, if you want to encode entry ``e`` into a buffer
// in memory, you can do it like this::
//
// std::vector<char> buffer;
// bencode(std::back_inserter(buf), e);
//
// .. _InputIterator: http://www.sgi.com/tech/stl/InputIterator.html
// .. _OutputIterator: http://www.sgi.com/tech/stl/OutputIterator.html
// .. _ostream_iterator: http://www.sgi.com/tech/stl/ostream_iterator.html
// .. _back_insert_iterator: http://www.sgi.com/tech/stl/back_insert_iterator.html
// .. _istream_iterator: http://www.sgi.com/tech/stl/istream_iterator.html
//
// If you want to decode a torrent file from a buffer in memory, you can do it like this::
//
// std::vector<char> buffer;
// // ...
// entry e = bdecode(buf.begin(), buf.end());
//
// Or, if you have a raw char buffer::
//
// const char* buf;
// // ...
// entry e = bdecode(buf, buf + data_size);
//
// Now we just need to know how to retrieve information from the entry.
//
// If ``bdecode()`` encounters invalid encoded data in the range given to it
// it will return a default constructed ``entry`` object.
template<class OutIt> int bencode(OutIt out, const entry& e)
{
return detail::bencode_recursive(out, e);
}
template<class InIt> entry bdecode(InIt start, InIt end)
{
entry e;
bool err = false;
detail::bdecode_recursive(start, end, e, err, 0);
#ifdef TORRENT_DEBUG
TORRENT_ASSERT(e.m_type_queried == false);
#endif
if (err) return entry();
return e;
}
template<class InIt> entry bdecode(InIt start, InIt end, int& len)
{
entry e;
bool err = false;
InIt s = start;
detail::bdecode_recursive(start, end, e, err, 0);
len = std::distance(s, start);
TORRENT_ASSERT(len >= 0);
if (err) return entry();
return e;
}
}
#endif // TORRENT_BENCODE_HPP_INCLUDED

View File

@@ -0,0 +1,360 @@
/*
Copyright (c) 2008-2014, 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_BITFIELD_HPP_INCLUDED
#define TORRENT_BITFIELD_HPP_INCLUDED
#include "libtorrent/assert.hpp"
#include "libtorrent/config.hpp"
#include <cstring> // for memset and memcpy
#include <cstdlib> // for malloc, free and realloc
#include <boost/cstdint.hpp> // uint32_t
#include <algorithm> // for min()
namespace libtorrent
{
// The bitfiled type stores any number of bits as a bitfield
// in a heap allocated or borrowed array.
struct TORRENT_EXPORT bitfield
{
// constructs a new bitfield. The default constructor creates an empty
// bitfield. ``bits`` is the size of the bitfield (specified in bits).
// ``val`` is the value to initialize the bits to. If not specified
// all bits are initialized to 0.
//
// 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)
{ resize(bits); }
bitfield(int bits, bool val): m_bytes(0), m_size(0), m_own(false)
{ resize(bits, val); }
bitfield(char const* b, int bits): m_bytes(0), m_size(0), m_own(false)
{ assign(b, bits); }
bitfield(bitfield const& rhs): m_bytes(0), m_size(0), m_own(false)
{ 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; }
#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(); }
// 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;
}
// 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));
}
void set_bit(int index)
{
TORRENT_ASSERT(index >= 0);
TORRENT_ASSERT(index < m_size);
m_bytes[index / 8] |= (0x80 >> (index & 7));
}
// returns true if all bits in the bitfield are set
bool all_set() const
{
boost::uint8_t* bytes = m_bytes;
int num_bytes = m_size / 8;
int num_words = 0;
// head
if (num_bytes >= 4)
{
switch (uintptr_t(bytes) & 0x3)
{
case 0: break;
case 1:
if (bytes[0] != 0xff) return false;
if (bytes[1] != 0xff) return false;
if (bytes[2] != 0xff) return false;
bytes += 3;
num_bytes -= 3;
break;
case 2:
if (bytes[0] != 0xff) return false;
if (bytes[1] != 0xff) return false;
bytes += 2;
num_bytes -= 2;
break;
case 3:
if (bytes[0] != 0xff) return false;
++bytes;
--num_bytes;
break;
}
num_words = num_bytes / 4;
TORRENT_ASSERT((uintptr_t(bytes) & 0x3) == 0);
boost::uint32_t* words = (boost::uint32_t*)bytes;
for (int i = 0; i < num_words; ++i)
{
if (words[i] != 0xffffffff) return false;
}
}
// tail
for (int i = num_words * 4; i < num_bytes; ++i)
{
if (bytes[i] != 0xff) return false;
}
int rest = m_size & 0x7;
if (rest > 0)
{
boost::uint8_t mask = (0xff << (8-rest)) & 0xff;
if ((bytes[num_bytes] & mask) != mask) return false;
}
return true;
}
// returns the size of the bitfield in bits.
int size() const { return m_size; }
// returns true if the bitfield has zero size.
bool empty() const { return m_size == 0; }
// returns a pointer to the internal buffer of the bitfield.
char const* bytes() const { return (char*)m_bytes; }
// copy operator
bitfield& operator=(bitfield const& rhs)
{
assign(rhs.bytes(), rhs.size());
return *this;
}
// 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)
{
ret += num_bits[m_bytes[i] & 0xf] + num_bits[m_bytes[i] >> 4];
}
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 >= 0);
return ret;
}
struct const_iterator
{
friend struct bitfield;
typedef bool value_type;
typedef ptrdiff_t difference_type;
typedef bool const* pointer;
typedef bool& reference;
typedef std::forward_iterator_tag iterator_category;
bool operator*() { return (*byte & bit) != 0; }
const_iterator& operator++() { inc(); return *this; }
const_iterator operator++(int)
{ const_iterator ret(*this); inc(); return ret; }
const_iterator& operator--() { dec(); return *this; }
const_iterator operator--(int)
{ const_iterator ret(*this); dec(); return ret; }
const_iterator(): byte(0), bit(0x80) {}
bool operator==(const_iterator const& rhs) const
{ return byte == rhs.byte && bit == rhs.bit; }
bool operator!=(const_iterator const& rhs) const
{ return byte != rhs.byte || bit != rhs.bit; }
private:
void inc()
{
TORRENT_ASSERT(byte);
if (bit == 0x01)
{
bit = 0x80;
++byte;
}
else
{
bit >>= 1;
}
}
void dec()
{
TORRENT_ASSERT(byte);
if (bit == 0x80)
{
bit = 0x01;
--byte;
}
else
{
bit <<= 1;
}
}
const_iterator(unsigned char const* ptr, int offset)
: byte(ptr), bit(0x80 >> offset) {}
unsigned char const* byte;
int 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); }
// 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;
resize(bits);
if (s >= m_size) return;
int old_size_bytes = (s + 7) / 8;
int new_size_bytes = (m_size + 7) / 8;
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);
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);
}
}
void resize(int bits)
{
TORRENT_ASSERT(bits >= 0);
const int b = (bits + 7) / 8;
if (m_bytes)
{
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;
}
}
else if (bits > 0)
{
m_bytes = (unsigned char*)std::malloc(b);
m_own = true;
}
m_size = bits;
clear_trailing_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);
clear_trailing_bits();
}
void clear_all()
{
std::memset(m_bytes, 0x00, (m_size + 7) / 8);
}
// make the bitfield empty, of zero size.
void clear() { dealloc(); m_size = 0; }
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));
}
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;
};
}
#endif // TORRENT_BITFIELD_HPP_INCLUDED

View File

@@ -0,0 +1,81 @@
/*
Copyright (c) 2010-2014, 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_BLOOM_FILTER_HPP_INCLUDED
#define TORRENT_BLOOM_FILTER_HPP_INCLUDED
#include <boost/cstdint.hpp>
#include "libtorrent/peer_id.hpp" // for sha1_hash
#include "libtorrent/config.hpp" // for sha1_hash
#include <math.h> // for log()
namespace libtorrent
{
TORRENT_EXTRA_EXPORT void set_bits(boost::uint8_t const* b, boost::uint8_t* bits, int len);
TORRENT_EXTRA_EXPORT bool has_bits(boost::uint8_t const* b, boost::uint8_t const* bits, int len);
TORRENT_EXTRA_EXPORT int count_zero_bits(boost::uint8_t const* bits, int len);
template <int N>
struct bloom_filter
{
bool find(sha1_hash const& k) const
{ return has_bits(&k[0], bits, N); }
void set(sha1_hash const& k)
{ set_bits(&k[0], bits, N); }
std::string to_string() const
{ return std::string((char const*)&bits[0], N); }
void from_string(char const* str)
{ memcpy(bits, str, N); }
void clear() { memset(bits, 0, N); }
float size() const
{
const int c = (std::min)(count_zero_bits(bits, N), (N * 8) - 1);
const int m = N * 8;
return ::log(c / float(m)) / (2.f * ::log(1.f - 1.f/m));
}
bloom_filter() { clear(); }
private:
boost::uint8_t bits[N];
};
}
#endif

View File

@@ -0,0 +1,156 @@
/*
Copyright (c) 2007-2014, 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_BROADCAST_SOCKET_HPP_INCLUDED
#define TORRENT_BROADCAST_SOCKET_HPP_INCLUDED
#include "libtorrent/config.hpp"
#include "libtorrent/io_service_fwd.hpp"
#include "libtorrent/socket.hpp"
#include "libtorrent/address.hpp"
#include "libtorrent/error_code.hpp"
#include <boost/shared_ptr.hpp>
#include <boost/function/function3.hpp>
#include <list>
namespace libtorrent
{
TORRENT_EXTRA_EXPORT bool is_local(address const& a);
TORRENT_EXTRA_EXPORT bool is_loopback(address const& addr);
TORRENT_EXTRA_EXPORT bool is_multicast(address const& addr);
TORRENT_EXTRA_EXPORT bool is_any(address const& addr);
TORRENT_EXTRA_EXPORT bool is_teredo(address const& addr);
TORRENT_EXTRA_EXPORT int cidr_distance(address const& a1, address const& a2);
// determines if the operating system supports IPv6
TORRENT_EXTRA_EXPORT bool supports_ipv6();
TORRENT_EXTRA_EXPORT int common_bits(unsigned char const* b1
, unsigned char const* b2, int n);
TORRENT_EXTRA_EXPORT address guess_local_address(io_service&);
typedef boost::function<void(udp::endpoint const& from
, char* buffer, int size)> receive_handler_t;
class TORRENT_EXTRA_EXPORT broadcast_socket
{
public:
broadcast_socket(udp::endpoint const& multicast_endpoint
, receive_handler_t const& handler);
~broadcast_socket() { close(); }
void open(io_service& ios, error_code& ec, bool loopback = true);
enum flags_t { broadcast = 1 };
void send(char const* buffer, int size, error_code& ec, int flags = 0);
void close();
int num_send_sockets() const { return m_unicast_sockets.size(); }
void enable_ip_broadcast(bool e);
private:
struct socket_entry
{
socket_entry(boost::shared_ptr<datagram_socket> const& s)
: socket(s), broadcast(false) {}
socket_entry(boost::shared_ptr<datagram_socket> const& s
, address_v4 const& mask): socket(s), netmask(mask), broadcast(false) {}
boost::shared_ptr<datagram_socket> socket;
char buffer[1500];
udp::endpoint remote;
address_v4 netmask;
bool broadcast;
void close()
{
if (!socket) return;
error_code ec;
socket->close(ec);
}
bool can_broadcast() const
{
error_code ec;
return broadcast
&& netmask != address_v4()
&& socket->local_endpoint(ec).address().is_v4();
}
address_v4 broadcast_address() const
{
error_code ec;
#if BOOST_VERSION < 104700
return address_v4(socket->local_endpoint(ec).address().to_v4().to_ulong() | ((~netmask.to_ulong()) & 0xffffffff));
#else
return address_v4::broadcast(socket->local_endpoint(ec).address().to_v4(), netmask);
#endif
}
};
void on_receive(socket_entry* s, error_code const& ec
, std::size_t bytes_transferred);
void open_unicast_socket(io_service& ios, address const& addr
, address_v4 const& mask);
void open_multicast_socket(io_service& ios, address const& addr
, bool loopback, error_code& ec);
// if we're aborting, destruct the handler and return true
bool maybe_abort();
// these sockets are used to
// join the multicast group (on each interface)
// and receive multicast messages
std::list<socket_entry> m_sockets;
// these sockets are not bound to any
// specific port and are used to
// send messages to the multicast group
// and receive unicast responses
std::list<socket_entry> m_unicast_sockets;
udp::endpoint m_multicast_endpoint;
receive_handler_t m_on_receive;
// the number of outstanding async operations
// we have on these sockets. The m_on_receive
// handler may not be destructed until this reaches
// 0, since it may be holding references to
// the broadcast_socket itself.
int m_outstanding_operations;
// when set to true, we're trying to shut down
// don't initiate new operations and once the
// outstanding counter reaches 0, destruct
// the handler object
bool m_abort;
};
}
#endif

View File

@@ -0,0 +1,461 @@
/*
Copyright (c) 2003-2014, Arvid Norberg
Copyright (c) 2007-2014, Arvid Norberg, Un Shyam
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_BT_PEER_CONNECTION_HPP_INCLUDED
#define TORRENT_BT_PEER_CONNECTION_HPP_INCLUDED
#include <ctime>
#include <algorithm>
#include <vector>
#include <string>
#include "libtorrent/debug.hpp"
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/smart_ptr.hpp>
#include <boost/noncopyable.hpp>
#include <boost/array.hpp>
#include <boost/optional.hpp>
#include <boost/cstdint.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/buffer.hpp"
#include "libtorrent/peer_connection.hpp"
#include "libtorrent/socket.hpp"
#include "libtorrent/peer_id.hpp"
#include "libtorrent/stat.hpp"
#include "libtorrent/alert.hpp"
#include "libtorrent/torrent.hpp"
#include "libtorrent/peer_request.hpp"
#include "libtorrent/piece_block_progress.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/pe_crypto.hpp"
namespace libtorrent
{
class torrent;
namespace detail
{
struct session_impl;
}
class TORRENT_EXTRA_EXPORT bt_peer_connection
: public peer_connection
{
friend class invariant_access;
public:
// this is the constructor where the we are the active part.
// The peer_conenction should handshake and verify that the
// other end has the correct id
bt_peer_connection(
aux::session_impl& ses
, boost::shared_ptr<socket_type> s
, tcp::endpoint const& remote
, policy::peer* peerinfo
, peer_id const& pid
, boost::weak_ptr<torrent> t = boost::weak_ptr<torrent>()
, bool outgoing = false);
void start();
enum
{
// pex_msg = 1,
// metadata_msg = 2,
upload_only_msg = 3,
holepunch_msg = 4,
// recommend_msg = 5,
// comment_msg = 6,
dont_have_msg = 7,
share_mode_msg = 8
};
~bt_peer_connection();
#ifndef TORRENT_DISABLE_ENCRYPTION
bool supports_encryption() const
{ return m_encrypted; }
bool rc4_encrypted() const
{ return m_rc4_encrypted; }
#endif
virtual int type() const { return peer_connection::bittorrent_connection; }
enum message_type
{
// standard messages
msg_choke = 0,
msg_unchoke,
msg_interested,
msg_not_interested,
msg_have,
msg_bitfield,
msg_request,
msg_piece,
msg_cancel,
// DHT extension
msg_dht_port,
// FAST extension
msg_suggest_piece = 0xd,
msg_have_all,
msg_have_none,
msg_reject_request,
msg_allowed_fast,
// extension protocol message
msg_extended = 20,
num_supported_messages
};
enum hp_message_t
{
// msg_types
hp_rendezvous = 0,
hp_connect = 1,
hp_failed = 2,
// error codes
hp_no_such_peer = 1,
hp_not_connected = 2,
hp_no_support = 3,
hp_no_self = 4
};
// called from the main loop when this connection has any
// work to do.
void on_sent(error_code const& error
, std::size_t bytes_transferred);
void on_receive(error_code const& error
, std::size_t bytes_transferred);
virtual void get_specific_peer_info(peer_info& p) const;
virtual bool in_handshake() const;
#ifndef TORRENT_DISABLE_EXTENSIONS
bool supports_holepunch() const { return m_holepunch_id != 0; }
#endif
bool support_extensions() const { return m_supports_extensions; }
// the message handlers are called
// each time a recv() returns some new
// data, the last time it will be called
// is when the entire packet has been
// received, then it will no longer
// be called. i.e. most handlers need
// to check how much of the packet they
// have received before any processing
void on_keepalive();
void on_choke(int received);
void on_unchoke(int received);
void on_interested(int received);
void on_not_interested(int received);
void on_have(int received);
void on_bitfield(int received);
void on_request(int received);
void on_piece(int received);
void on_cancel(int received);
// DHT extension
void on_dht_port(int received);
// FAST extension
void on_suggest_piece(int received);
void on_have_all(int received);
void on_have_none(int received);
void on_reject_request(int received);
void on_allowed_fast(int received);
#ifndef TORRENT_DISABLE_EXTENSIONS
void on_holepunch();
void on_extended(int received);
void on_extended_handshake();
#endif
typedef void (bt_peer_connection::*message_handler)(int received);
// the following functions appends messages
// to the send buffer
void write_choke();
void write_unchoke();
void write_interested();
void write_not_interested();
void write_request(peer_request const& r);
void write_cancel(peer_request const& r);
void write_bitfield();
void write_have(int index);
void write_piece(peer_request const& r, disk_buffer_holder& buffer);
void write_handshake();
#ifndef TORRENT_DISABLE_EXTENSIONS
void write_extensions();
void write_upload_only();
void write_share_mode();
void write_holepunch_msg(int type, tcp::endpoint const& ep, int error);
#endif
void write_metadata(std::pair<int, int> req);
void write_metadata_request(std::pair<int, int> req);
void write_keepalive();
// DHT extension
void write_dht_port(int listen_port);
// FAST extension
void write_have_all();
void write_have_none();
void write_reject_request(peer_request const&);
void write_allow_fast(int piece);
void write_suggest(int piece);
void on_connected();
void on_metadata();
#if TORRENT_USE_INVARIANT_CHECKS
void check_invariant() const;
ptime m_last_choke;
#endif
private:
bool dispatch_message(int received);
// returns the block currently being
// downloaded. And the progress of that
// block. If the peer isn't downloading
// a piece for the moment, the boost::optional
// will be invalid.
boost::optional<piece_block_progress> downloading_piece_progress() const;
#ifndef TORRENT_DISABLE_ENCRYPTION
// if (is_local()), we are 'a' otherwise 'b'
//
// 1. a -> b dhkey, pad
// 2. b -> a dhkey, pad
// 3. a -> b sync, payload
// 4. b -> a sync, payload
// 5. a -> b payload
void write_pe1_2_dhkey();
void write_pe3_sync();
void write_pe4_sync(int crypto_select);
void write_pe_vc_cryptofield(char* write_buf, int len
, int crypto_field, int pad_size);
// stream key (info hash of attached torrent)
// secret is the DH shared secret
// initializes m_enc_handler
void init_pe_rc4_handler(char const* secret, sha1_hash const& stream_key);
// Returns offset at which bytestream (src, src + src_size)
// matches bytestream(target, target + target_size).
// If no sync found, return -1
int get_syncoffset(char const* src, int src_size
, char const* target, int target_size) const;
#endif
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 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);
}
private:
enum state
{
#ifndef TORRENT_DISABLE_ENCRYPTION
read_pe_dhkey = 0,
read_pe_syncvc,
read_pe_synchash,
read_pe_skey_vc,
read_pe_cryptofield,
read_pe_pad,
read_pe_ia,
init_bt_handshake,
read_protocol_identifier,
#else
read_protocol_identifier = 0,
#endif
read_info_hash,
read_peer_id,
// handshake complete
read_packet_size,
read_packet
};
#ifndef TORRENT_DISABLE_ENCRYPTION
enum
{
handshake_len = 68,
dh_key_len = 96
};
#endif
// state of on_receive
boost::uint8_t m_state;
// this is set to true if the handshake from
// the peer indicated that it supports the
// extension protocol
bool m_supports_extensions:1;
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
bool m_sent_bitfield:1;
bool m_in_constructor:1;
bool m_sent_handshake:1;
#endif
#ifndef TORRENT_DISABLE_ENCRYPTION
// this is set to true after the encryption method has been
// succesfully negotiated (either plaintext or rc4), to signal
// automatic encryption/decryption.
bool m_encrypted:1;
// true if rc4, false if plaintext
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;
// this is a queue of ranges that describes
// where in the send buffer actual payload
// data is located. This is currently
// only used to be able to gather statistics
// seperately on payload and protocol data.
struct range
{
range(int s, int l)
: start(s)
, length(l)
{
TORRENT_ASSERT(s >= 0);
TORRENT_ASSERT(l > 0);
}
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;
#ifndef TORRENT_DISABLE_ENCRYPTION
// initialized during write_pe1_2_dhkey, and destroyed on
// creation of m_enc_handler. Cannot reinitialize once
// initialized.
boost::scoped_ptr<dh_key_exchange> m_dh_key_exchange;
// if encryption is negotiated, this is used for
// encryption/decryption during the entire session. Destroyed
// if plaintext is selected
boost::scoped_ptr<encryption_handler> m_enc_handler;
// (outgoing only) synchronize verification constant with
// remote peer, this will hold rc4_decrypt(vc). Destroyed
// after the sync step.
boost::scoped_array<char> m_sync_vc;
// (incoming only) synchronize hash with remote peer, holds
// the sync hash (hash("req1",secret)). Destroyed after the
// sync step.
boost::scoped_ptr<sha1_hash> m_sync_hash;
// 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
#ifndef TORRENT_DISABLE_EXTENSIONS
// the message ID for don't-have message
boost::uint8_t m_dont_have_id;
// the message ID for share mode message
// 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
};
}
#endif // TORRENT_BT_PEER_CONNECTION_HPP_INCLUDED

View File

@@ -0,0 +1,224 @@
/*
Copyright (c) 2007-2014, 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 Rasterbar Software 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 LIBTORRENT_BUFFER_HPP
#define LIBTORRENT_BUFFER_HPP
#include <cstring>
#include "libtorrent/invariant_check.hpp"
#include "libtorrent/assert.hpp"
#include <cstdlib> // malloc/free/realloc
namespace libtorrent {
class buffer
{
public:
struct interval
{
interval()
: begin(0)
, end(0)
{}
interval(char* b, char* e)
: begin(b)
, end(e)
{}
char operator[](int index) const
{
TORRENT_ASSERT(begin + index < end);
return begin[index];
}
int left() const
{
TORRENT_ASSERT(end >= begin);
TORRENT_ASSERT(end - begin < INT_MAX);
return int(end - begin);
}
char* begin;
char* end;
};
struct const_interval
{
const_interval(interval const& i)
: begin(i.begin)
, end(i.end)
{}
const_interval(char const* b, char const* e)
: begin(b)
, end(e)
{}
char operator[](int index) const
{
TORRENT_ASSERT(begin + index < end);
return begin[index];
}
bool operator==(const const_interval& p_interval)
{
return begin == p_interval.begin
&& end == p_interval.end;
}
int left() const
{
TORRENT_ASSERT(end >= begin);
TORRENT_ASSERT(end - begin < INT_MAX);
return int(end - begin);
}
char const* begin;
char const* end;
};
buffer(std::size_t n = 0)
: m_begin(0)
, m_end(0)
, m_last(0)
{
if (n) resize(n);
}
buffer(buffer const& b)
: m_begin(0)
, m_end(0)
, m_last(0)
{
if (b.size() == 0) return;
resize(b.size());
std::memcpy(m_begin, b.begin(), b.size());
}
#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; }
#endif
buffer& operator=(buffer const& b)
{
if (&b == this) return *this;
resize(b.size());
if (b.size() == 0) return *this;
std::memcpy(m_begin, b.begin(), b.size());
return *this;
}
~buffer()
{
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); }
void resize(std::size_t n)
{
reserve(n);
m_end = m_begin + n;
}
void insert(char* point, char const* first, char const* last)
{
std::size_t p = point - m_begin;
if (point == m_end)
{
resize(size() + last - first);
std::memcpy(m_begin + p, first, last - first);
return;
}
resize(size() + last - first);
std::memmove(m_begin + p + (last - first), m_begin + p, last - first);
std::memcpy(m_begin + p, first, last - first);
}
void erase(char* b, char* e)
{
TORRENT_ASSERT(e <= m_end);
TORRENT_ASSERT(b >= m_begin);
TORRENT_ASSERT(b <= e);
if (e == m_end)
{
resize(b - m_begin);
return;
}
std::memmove(b, e, m_end - e);
m_end = b + (m_end - e);
}
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 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;
}
bool empty() const { return m_begin == m_end; }
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; }
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);
}
private:
char* m_begin; // first
char* m_end; // one passed end of size
char* m_last; // one passed end of allocation
};
}
#endif // LIBTORRENT_BUFFER_HPP

View File

@@ -0,0 +1,73 @@
/*
Copyright (c) 2010-2014, 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_BUILD_CONFIG_HPP_INCLUDED
#define TORRENT_BUILD_CONFIG_HPP_INCLUDED
#include "libtorrent/config.hpp"
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/stringize.hpp>
#if TORRENT_USE_BOOST_DATE_TIME
#define TORRENT_CFG_TIME boosttime_
#elif TORRENT_USE_ABSOLUTE_TIME
#define TORRENT_CFG_TIME absolutetime_
#elif TORRENT_USE_QUERY_PERFORMANCE_TIMER
#define TORRENT_CFG_TIME performancetimer_
#elif TORRENT_USE_CLOCK_GETTIME
#define TORRENT_CFG_TIME clocktime_
#elif TORRENT_USE_SYSTEM_TIME
#define TORRENT_CFG_TIME systime_
#else
#error what timer is used?
#endif
#if TORRENT_USE_IPV6
#define TORRENT_CFG_IPV6 ipv6_
#else
#define TORRENT_CFG_IPV6 noipv_-
#endif
#ifdef TORRENT_NO_DEPRECATE
#define TORRENT_CFG_DEPR nodeprecate_
#else
#define TORRENT_CFG_DEPR deprecated_
#endif
#define TORRENT_CFG \
BOOST_PP_CAT(TORRENT_CFG_TIME, \
TORRENT_CFG_DEPR)
#define TORRENT_CFG_STRING BOOST_PP_STRINGIZE(TORRENT_CFG)
#endif

View File

@@ -0,0 +1,124 @@
/*
Copyright (c) 2007-2014, 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_CHAINED_BUFFER_HPP_INCLUDED
#define TORRENT_CHAINED_BUFFER_HPP_INCLUDED
#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 <string.h> // for memcpy
namespace libtorrent
{
#if BOOST_VERSION >= 103500
namespace asio = boost::asio;
#endif
struct TORRENT_EXTRA_EXPORT chained_buffer
{
chained_buffer(): m_bytes(0), m_capacity(0)
{
#if TORRENT_USE_ASSERTS
m_destructed = false;
#endif
}
struct buffer_t
{
boost::function<void(char*)> free; // destructs the buffer
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
};
bool empty() const { return m_bytes == 0; }
int size() const { return m_bytes; }
int capacity() const { return m_capacity; }
void pop_front(int bytes_to_pop);
void append_buffer(char* buffer, int s, int used_size
, boost::function<void(char*)> const& destructor);
// returns the number of bytes available at the
// end of the last chained buffer.
int space_in_last_buffer();
// tries to copy the given buffer to the end of the
// last chained buffer. If there's not enough room
// it returns false
char* append(char const* buf, int s);
// tries to allocate memory from the end
// of the last buffer. If there isn't
// enough room, returns 0
char* allocate_appendix(int s);
std::list<asio::const_buffer> const& build_iovec(int to_send);
~chained_buffer();
private:
// 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;
// this is the number of bytes in the send buf.
// this will always be equal to the sum of the
// size of all buffers in vec
int m_bytes;
// the total size of all buffers in the chain
// including unused space
int m_capacity;
#if TORRENT_USE_ASSERTS
bool m_destructed;
#endif
};
}
#endif

View File

@@ -0,0 +1,572 @@
/*
Copyright (c) 2005-2014, 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_CONFIG_HPP_INCLUDED
#define TORRENT_CONFIG_HPP_INCLUDED
#if !defined _MSC_VER || _MSC_VER >= 1600
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS 1
#endif
#ifndef __STDC_CONSTANT_MACROS
#define __STDC_CONSTANT_MACROS 1
#endif
#endif
#include <boost/config.hpp>
#include <boost/version.hpp>
#include <boost/detail/endian.hpp>
#include <stdio.h> // for snprintf
#include <limits.h> // for IOV_MAX
#include "libtorrent/export.hpp"
#if defined TORRENT_DEBUG_BUFFERS && !defined TORRENT_DISABLE_POOL_ALLOCATOR
#error TORRENT_DEBUG_BUFFERS only works if you also disable pool allocators with TORRENT_DISABLE_POOL_ALLOCATOR
#endif
#if !defined BOOST_ASIO_SEPARATE_COMPILATION && !defined BOOST_ASIO_DYN_LINK
#define BOOST_ASIO_SEPARATE_COMPILATION
#endif
#ifndef _MSC_VER
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS 1
#endif
#include <inttypes.h> // for PRId64 et.al.
#endif
#ifndef PRId64
// MinGW uses microsofts runtime
#if defined _MSC_VER || defined __MINGW32__
#define PRId64 "I64d"
#define PRIu64 "I64u"
#define PRIx64 "I64x"
#define PRIu32 "u"
#else
#define PRId64 "lld"
#define PRIu64 "llu"
#define PRIx64 "llx"
#define PRIu32 "u"
#endif
#endif
// ======= GCC =========
#if defined __GNUC__
# if __GNUC__ >= 3
# define TORRENT_DEPRECATED __attribute__ ((deprecated))
# endif
// ======= SUNPRO =========
#elif defined __SUNPRO_CC
// SunPRO seems to have an overly-strict
// definition of POD types and doesn't
// seem to allow boost::array in unions
#define TORRENT_BROKEN_UNIONS 1
// ======= MSVC =========
#elif defined BOOST_MSVC
#pragma warning(disable: 4258)
#pragma warning(disable: 4251)
// class X needs to have dll-interface to be used by clients of class Y
#pragma warning(disable:4251)
// '_vsnprintf': This function or variable may be unsafe
#pragma warning(disable:4996)
#define TORRENT_DEPRECATED_PREFIX __declspec(deprecated)
#endif
// ======= PLATFORMS =========
// set up defines for target environments
// ==== AMIGA ===
#if defined __AMIGA__ || defined __amigaos__ || defined __AROS__
#define TORRENT_AMIGA
#define TORRENT_USE_MLOCK 0
#define TORRENT_USE_WRITEV 0
#define TORRENT_USE_READV 0
#define TORRENT_USE_IPV6 0
#define TORRENT_USE_BOOST_THREAD 0
#define TORRENT_USE_IOSTREAM 0
// set this to 1 to disable all floating point operations
// (disables some float-dependent APIs)
#define TORRENT_NO_FPU 1
#define TORRENT_USE_I2P 0
#ifndef TORRENT_USE_ICONV
#define TORRENT_USE_ICONV 0
#endif
// ==== Darwin/BSD ===
#elif (defined __APPLE__ && defined __MACH__) || defined __FreeBSD__ || defined __NetBSD__ \
|| defined __OpenBSD__ || defined __bsdi__ || defined __DragonFly__ \
|| defined __FreeBSD_kernel__
#define TORRENT_BSD
// we don't need iconv on mac, because
// the locale is always utf-8
#if defined __APPLE__
#ifndef TORRENT_USE_ICONV
#define TORRENT_USE_ICONV 0
#define TORRENT_USE_LOCALE 0
#define TORRENT_CLOSE_MAY_BLOCK 1
#include <AvailabilityMacros.h>
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
#ifdef TORRENT_USE_OPENSSL
#define TORRENT_USE_COMMONCRYPTO 1
#endif // TORRENT_USE_OPENSSL
#endif // MAC_OS_X_VERSION_MIN_REQUIRED
// execinfo.h is available in the MacOS X 10.5 SDK.
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
#define TORRENT_USE_EXECINFO 1
#endif
#endif // __APPLE__
#else
// FreeBSD has a reasonable iconv signature
// unless we're on glibc
#ifndef __GLIBC__
# define TORRENT_ICONV_ARG (const char**)
#endif
#endif
#define TORRENT_HAS_FALLOCATE 0
#define TORRENT_USE_IFADDRS 1
#define TORRENT_USE_SYSCTL 1
#define TORRENT_USE_IFCONF 1
// ==== LINUX ===
#elif defined __linux__
#define TORRENT_LINUX
#define TORRENT_USE_NETLINK 1
#define TORRENT_USE_IFCONF 1
#define TORRENT_HAS_SALEN 0
// ===== ANDROID ===== (almost linux, sort of)
#if defined __ANDROID__
#define TORRENT_ANDROID
#define TORRENT_HAS_FALLOCATE 0
#define TORRENT_USE_ICONV 0
#define TORRENT_USE_IFADDRS 0
#define TORRENT_USE_MEMALIGN 1
#else
#define TORRENT_USE_IFADDRS 1
#define TORRENT_USE_POSIX_MEMALIGN 1
#endif
#if __amd64__ || __i386__
#define TORRENT_USE_EXECINFO 1
#endif
// ==== MINGW ===
#elif defined __MINGW32__
#define TORRENT_MINGW
#define TORRENT_WINDOWS
#ifndef TORRENT_USE_ICONV
# define TORRENT_USE_ICONV 0
# define TORRENT_USE_LOCALE 1
#endif
#define TORRENT_USE_RLIMIT 0
#define TORRENT_USE_NETLINK 0
#define TORRENT_USE_GETADAPTERSADDRESSES 1
#define TORRENT_HAS_SALEN 0
#define TORRENT_USE_GETIPFORWARDTABLE 1
#ifndef TORRENT_USE_UNC_PATHS
# define TORRENT_USE_UNC_PATHS 1
#endif
// ==== WINDOWS ===
#elif defined WIN32
#define TORRENT_WINDOWS
#ifndef TORRENT_USE_GETIPFORWARDTABLE
#define TORRENT_USE_GETIPFORWARDTABLE 1
#endif
#define TORRENT_USE_GETADAPTERSADDRESSES 1
#define TORRENT_HAS_SALEN 0
// windows has its own functions to convert
#ifndef TORRENT_USE_ICONV
#define TORRENT_USE_ICONV 0
#define TORRENT_USE_LOCALE 1
#endif
#define TORRENT_USE_RLIMIT 0
#define TORRENT_HAS_FALLOCATE 0
#ifndef TORRENT_USE_UNC_PATHS
#define TORRENT_USE_UNC_PATHS 1
#endif
// ==== SOLARIS ===
#elif defined sun || defined __sun
#define TORRENT_SOLARIS
#define TORRENT_COMPLETE_TYPES_REQUIRED 1
#define TORRENT_USE_IFCONF 1
#define TORRENT_HAS_SALEN 0
// ==== BEOS ===
#elif defined __BEOS__ || defined __HAIKU__
#define TORRENT_BEOS
#include <storage/StorageDefs.h> // B_PATH_NAME_LENGTH
#define TORRENT_HAS_FALLOCATE 0
#define TORRENT_USE_MLOCK 0
#ifndef TORRENT_USE_ICONV
#define TORRENT_USE_ICONV 0
#endif
// ==== GNU/Hurd ===
#elif defined __GNU__
#define TORRENT_HURD
#define TORRENT_USE_IFADDRS 1
#define TORRENT_USE_IFCONF 1
// ==== eCS(OS/2) ===
#elif defined __OS2__
#define TORRENT_OS2
#define TORRENT_HAS_FALLOCATE 0
#define TORRENT_USE_IFCONF 1
#define TORRENT_USE_SYSCTL 1
#define TORRENT_USE_MLOCK 0
#define TORRENT_USE_IPV6 0
#define TORRENT_ICONV_ARG (const char**)
#define TORRENT_USE_WRITEV 0
#define TORRENT_USE_READV 0
#else
#ifdef _MSC_VER
#pragma message ( "unknown OS, assuming BSD" )
#else
#warning "unknown OS, assuming BSD"
#endif
#define TORRENT_BSD
#endif
// on windows, NAME_MAX refers to Unicode characters
// on linux it refers to bytes (utf-8 encoded)
// TODO: Make this count Unicode characters instead of bytes on windows
// windows
#if defined FILENAME_MAX
#define TORRENT_MAX_PATH FILENAME_MAX
// beos
#elif defined B_PATH_NAME_LENGTH
#define TORRENT_MAX_PATH B_PATH_NAME_LENGTH
// solaris
#elif defined MAXPATH
#define TORRENT_MAX_PATH MAXPATH
// posix
#elif defined NAME_MAX
#define TORRENT_MAX_PATH NAME_MAX
// none of the above
#else
// this is the maximum number of characters in a
// path element / filename on windows
#define TORRENT_MAX_PATH 255
#ifdef _MSC_VER
#pragma message ( "unknown platform, assuming the longest path is 255" )
#else
#warning "unknown platform, assuming the longest path is 255"
#endif
#endif
#if defined TORRENT_WINDOWS && !defined TORRENT_MINGW
#include <stdarg.h>
// internal
#ifdef __cplusplus
inline
#else
static
#endif
int snprintf(char* buf, int len, char const* fmt, ...)
{
va_list lp;
int ret;
va_start(lp, fmt);
ret = _vsnprintf(buf, len, fmt, lp);
va_end(lp);
if (ret < 0) { buf[len-1] = 0; ret = len-1; }
return ret;
}
#define strtoll _strtoi64
#else
#include <limits.h>
#endif
#if (defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)) \
&& !defined (TORRENT_UPNP_LOGGING) && TORRENT_USE_IOSTREAM
#define TORRENT_UPNP_LOGGING
#endif
#ifndef TORRENT_ICONV_ARG
#define TORRENT_ICONV_ARG (char**)
#endif
// libiconv presence, not implemented yet
#ifndef TORRENT_USE_ICONV
#define TORRENT_USE_ICONV 1
#endif
#ifndef TORRENT_HAS_SALEN
#define TORRENT_HAS_SALEN 1
#endif
#ifndef TORRENT_USE_GETADAPTERSADDRESSES
#define TORRENT_USE_GETADAPTERSADDRESSES 0
#endif
#ifndef TORRENT_USE_NETLINK
#define TORRENT_USE_NETLINK 0
#endif
#ifndef TORRENT_USE_EXECINFO
#define TORRENT_USE_EXECINFO 0
#endif
#ifndef TORRENT_USE_SYSCTL
#define TORRENT_USE_SYSCTL 0
#endif
#ifndef TORRENT_USE_GETIPFORWARDTABLE
#define TORRENT_USE_GETIPFORWARDTABLE 0
#endif
#ifndef TORRENT_USE_LOCALE
#define TORRENT_USE_LOCALE 0
#endif
// set this to true if close() may block on your system
// Mac OS X does this if the file being closed is not fully
// allocated on disk yet for instance. When defined, the disk
// I/O subsytem will use a separate thread for closing files
#ifndef TORRENT_CLOSE_MAY_BLOCK
#define TORRENT_CLOSE_MAY_BLOCK 0
#endif
#ifndef TORRENT_BROKEN_UNIONS
#define TORRENT_BROKEN_UNIONS 0
#endif
#ifndef TORRENT_USE_WSTRING
#if !defined BOOST_NO_STD_WSTRING
#define TORRENT_USE_WSTRING 1
#else
#define TORRENT_USE_WSTRING 0
#endif // BOOST_NO_STD_WSTRING
#endif // TORRENT_USE_WSTRING
#ifndef TORRENT_HAS_FALLOCATE
#define TORRENT_HAS_FALLOCATE 1
#endif
#ifndef TORRENT_DEPRECATED_PREFIX
#define TORRENT_DEPRECATED_PREFIX
#endif
#ifndef TORRENT_USE_COMMONCRYPTO
#define TORRENT_USE_COMMONCRYPTO 0
#endif
#ifndef TORRENT_DEPRECATED
#define TORRENT_DEPRECATED
#endif
#ifndef TORRENT_COMPLETE_TYPES_REQUIRED
#define TORRENT_COMPLETE_TYPES_REQUIRED 0
#endif
#ifndef TORRENT_USE_UNC_PATHS
#define TORRENT_USE_UNC_PATHS 0
#endif
#ifndef TORRENT_USE_RLIMIT
#define TORRENT_USE_RLIMIT 1
#endif
#ifndef TORRENT_USE_IFADDRS
#define TORRENT_USE_IFADDRS 0
#endif
#ifndef TORRENT_USE_IPV6
#define TORRENT_USE_IPV6 1
#endif
#ifndef TORRENT_USE_MLOCK
#define TORRENT_USE_MLOCK 1
#endif
#ifndef TORRENT_USE_WRITEV
#define TORRENT_USE_WRITEV 1
#endif
#ifndef TORRENT_USE_READV
#define TORRENT_USE_READV 1
#endif
#ifndef TORRENT_NO_FPU
#define TORRENT_NO_FPU 0
#endif
#ifndef TORRENT_USE_IOSTREAM
#ifndef BOOST_NO_IOSTREAM
#define TORRENT_USE_IOSTREAM 1
#else
#define TORRENT_USE_IOSTREAM 0
#endif
#endif
// if set to true, piece picker will use less RAM
// but only support up to ~260000 pieces in a torrent
#ifndef TORRENT_COMPACT_PICKER
#define TORRENT_COMPACT_PICKER 0
#endif
#ifndef TORRENT_USE_I2P
#define TORRENT_USE_I2P 1
#endif
#if !defined TORRENT_IOV_MAX
#ifdef IOV_MAX
#define TORRENT_IOV_MAX IOV_MAX
#else
#define TORRENT_IOV_MAX INT_MAX
#endif
#endif
#if !defined(TORRENT_READ_HANDLER_MAX_SIZE)
# ifdef _GLIBCXX_DEBUG
# define TORRENT_READ_HANDLER_MAX_SIZE 400
# else
// if this is not divisible by 8, we're wasting space
# define TORRENT_READ_HANDLER_MAX_SIZE 336
# endif
#endif
#if !defined(TORRENT_WRITE_HANDLER_MAX_SIZE)
# ifdef _GLIBCXX_DEBUG
# define TORRENT_WRITE_HANDLER_MAX_SIZE 400
# else
// if this is not divisible by 8, we're wasting space
# define TORRENT_WRITE_HANDLER_MAX_SIZE 336
# endif
#endif
#if defined _MSC_VER && _MSC_VER <= 1200
#define for if (false) {} else for
#endif
#if TORRENT_BROKEN_UNIONS
#define TORRENT_UNION struct
#else
#define TORRENT_UNION union
#endif
// determine what timer implementation we can use
// if one is already defined, don't pick one
// autmatically. This lets the user control this
// from the Jamfile
#if !defined TORRENT_USE_ABSOLUTE_TIME \
&& !defined TORRENT_USE_QUERY_PERFORMANCE_TIMER \
&& !defined TORRENT_USE_CLOCK_GETTIME \
&& !defined TORRENT_USE_BOOST_DATE_TIME \
&& !defined TORRENT_USE_ECLOCK \
&& !defined TORRENT_USE_SYSTEM_TIME
#if defined __APPLE__ && defined __MACH__
#define TORRENT_USE_ABSOLUTE_TIME 1
#elif defined(_WIN32) || defined TORRENT_MINGW
#define TORRENT_USE_QUERY_PERFORMANCE_TIMER 1
#elif defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0
#define TORRENT_USE_CLOCK_GETTIME 1
#elif defined(TORRENT_AMIGA)
#define TORRENT_USE_ECLOCK 1
#elif defined(TORRENT_BEOS)
#define TORRENT_USE_SYSTEM_TIME 1
#else
#define TORRENT_USE_BOOST_DATE_TIME 1
#endif
#endif
// debug builds have asserts enabled by default, release
// builds have asserts if they are explicitly enabled by
// the release_asserts macro.
#ifndef TORRENT_USE_ASSERTS
#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
#define TORRENT_USE_ASSERTS 1
#else
#define TORRENT_USE_ASSERTS 0
#endif
#endif // TORRENT_USE_ASSERTS
#if defined TORRENT_DEBUG && TORRENT_USE_ASSERTS \
&& !defined TORRENT_DISABLE_INVARIANT_CHECKS
#define TORRENT_USE_INVARIANT_CHECKS 1
#else
#define TORRENT_USE_INVARIANT_CHECKS 0
#endif
// for non-exception builds
#ifdef BOOST_NO_EXCEPTIONS
#define TORRENT_TRY if (true)
#define TORRENT_CATCH(x) else if (false)
#define TORRENT_CATCH_ALL else if (false)
#define TORRENT_DECLARE_DUMMY(x, y) x y
#else
#define TORRENT_TRY try
#define TORRENT_CATCH(x) catch(x)
#define TORRENT_CATCH_ALL catch(...)
#define TORRENT_DECLARE_DUMMY(x, y)
#endif // BOOST_NO_EXCEPTIONS
#endif // TORRENT_CONFIG_HPP_INCLUDED

View File

@@ -0,0 +1,150 @@
/*
Copyright (c) 2007-2014, 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_CONNECTION_QUEUE
#define TORRENT_CONNECTION_QUEUE
#include <list>
#include <boost/function/function1.hpp>
#include <boost/function/function0.hpp>
#include <boost/noncopyable.hpp>
#include "libtorrent/io_service.hpp"
#include "libtorrent/error_code.hpp"
#include "libtorrent/deadline_timer.hpp"
#ifdef TORRENT_CONNECTION_LOGGING
#include <fstream>
#endif
#include "libtorrent/thread.hpp"
namespace libtorrent
{
class TORRENT_EXTRA_EXPORT connection_queue : public boost::noncopyable
{
public:
connection_queue(io_service& ios);
// if there are no free slots, returns the negative
// number of queued up connections
int free_slots() const;
void enqueue(boost::function<void(int)> const& on_connect
, boost::function<void()> const& on_timeout
, time_duration timeout, int priority = 0);
bool done(int ticket);
void limit(int limit);
int limit() const;
void close();
int size() const { return m_queue.size(); }
int num_connecting() const { return m_num_connecting; }
#if defined TORRENT_ASIO_DEBUGGING
float next_timeout() const { return total_milliseconds(m_timer.expires_at() - time_now_hires()) / 1000.f; }
float max_timeout() const
{
ptime max_timeout = min_time();
for (std::list<entry>::const_iterator i = m_queue.begin()
, end(m_queue.end()); i != end; ++i)
{
if (!i->connecting) continue;
if (i->expires > max_timeout) max_timeout = i->expires;
}
if (max_timeout == min_time()) return 0.f;
return total_milliseconds(max_timeout - time_now_hires()) / 1000.f;
}
#endif
#if TORRENT_USE_INVARIANT_CHECKS
void check_invariant() const;
#endif
private:
typedef mutex mutex_t;
void try_connect(mutex_t::scoped_lock& l);
void on_timeout(error_code const& e);
void on_try_connect();
struct entry
{
entry()
: expires(max_time())
, ticket(0)
, connecting(false)
, priority(0)
{}
// called when the connection is initiated
// this is when the timeout countdown starts
boost::function<void(int)> on_connect;
// called if done hasn't been called within the timeout
// or if the connection queue aborts. This means there
// are 3 different interleaves of these function calls:
// 1. on_connect
// 2. on_connect, on_timeout
// 3. on_timeout
boost::function<void()> on_timeout;
ptime expires;
time_duration timeout;
boost::int32_t ticket;
bool connecting;
boost::uint8_t priority;
};
std::list<entry> m_queue;
// the next ticket id a connection will be given
int m_next_ticket;
int m_num_connecting;
int m_half_open_limit;
bool m_abort;
// the number of outstanding timers
int m_num_timers;
deadline_timer m_timer;
mutable mutex_t m_mutex;
#ifdef TORRENT_DEBUG
bool m_in_timeout_function;
#endif
#ifdef TORRENT_CONNECTION_LOGGING
std::ofstream m_log;
#endif
};
}
#endif

View File

@@ -0,0 +1,69 @@
/*
Copyright (c) 2010-2014, 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_COPY_PTR
#define TORRENT_COPY_PTR
namespace libtorrent
{
template <class T>
struct copy_ptr
{
copy_ptr(): m_ptr(0) {}
copy_ptr(T* t): m_ptr(t) {}
copy_ptr(copy_ptr const& p): m_ptr(p.m_ptr ? new T(*p.m_ptr) : 0) {}
void reset(T* t = 0) { delete m_ptr; m_ptr = t; }
copy_ptr& operator=(copy_ptr const& p)
{
delete m_ptr;
m_ptr = p.m_ptr ? new T(*p.m_ptr) : 0;
return *this;
}
T* operator->() { return m_ptr; }
T const* operator->() const { return m_ptr; }
T& operator*() { return *m_ptr; }
T const& operator*() const { return *m_ptr; }
void swap(copy_ptr<T>& p)
{
T* tmp = m_ptr;
m_ptr = p.m_ptr;
p.m_ptr = tmp;
}
operator bool() const { return m_ptr != 0; }
~copy_ptr() { delete m_ptr; }
private:
T* m_ptr;
};
}
#endif // TORRENT_COPY_PTR

View File

@@ -0,0 +1,505 @@
/*
Copyright (c) 2008-2014, 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_CREATE_TORRENT_HPP_INCLUDED
#define TORRENT_CREATE_TORRENT_HPP_INCLUDED
#include "libtorrent/bencode.hpp"
#include "libtorrent/peer_id.hpp"
#include "libtorrent/file_storage.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/storage.hpp"
#include "libtorrent/hasher.hpp"
#include "libtorrent/utf8.hpp"
#include "libtorrent/allocator.hpp"
#include "libtorrent/file.hpp" // for combine_path etc.
#include <vector>
#include <string>
#include <utility>
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/scoped_ptr.hpp>
#include <boost/config.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
// OVERVIEW
//
// 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:
//
// 1. first the files that will be part of the torrent are determined.
// 2. the torrent properties are set, such as tracker url, web seeds,
// DHT nodes etc.
// 3. Read through all the files in the torrent, SHA-1 all the data
// and set the piece hashes.
// 4. The torrent is bencoded into a file or buffer.
//
// If there are a lot of files and or deep directoy hierarchies to
// traverse, step one can be time consuming.
//
// 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.
//
// All of these classes and functions are declared by including
// ``libtorrent/create_torrent.hpp``.
//
// example:
//
// .. code:: c++
//
// 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());
//
namespace libtorrent
{
class torrent_info;
// This class holds state for creating a torrent. After having added
// all information to it, call create_torrent::generate() to generate
// the torrent. The entry that's returned can then be bencoded into a
// .torrent file using bencode().
struct TORRENT_EXPORT create_torrent
{
// flags for create_torrent::create_torrent().
enum flags_t
{
// This will insert pad files to align the files to piece boundaries, for
// optimized disk-I/O.
optimize = 1
// 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
// create_torrent::merkle_tree() function.
, merkle = 2
// 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.
, modification_time = 4
// 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.
, symlinks = 8
// If this is set, the set_piece_hashes() 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 set_piece_hashes() function,
// this flag will have no effect.
, calculate_file_hashes = 16
};
// The ``piece_size`` 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.
//
// If a ``pad_size_limit`` 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
// ``optimize`` flag is passed. Typically it doesn't make sense to set this
// any lower than 4kiB.
//
// The overload that takes a ``torrent_info`` 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 create_torrent::generate(). This means
// that none of the member functions of create_torrent that affects
// the content of the info dictionary (such as ``set_hash()``), will
// have any affect.
//
// The ``flags`` arguments specifies options for the torrent creation. It can
// be any combination of the flags defined by create_torrent::flags_t.
//
// ``alignment`` 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.
create_torrent(file_storage& fs, int piece_size = 0
, int pad_file_limit = -1, int flags = optimize, int alignment = -1);
create_torrent(torrent_info const& ti);
// internal
~create_torrent();
// This function will generate the .torrent file as a bencode tree. In order to
// generate the flat file, use the bencode() function.
//
// It may be useful to add custom entries to the torrent file before bencoding it
// and saving it to disk.
//
// If anything goes wrong during torrent generation, this function will return
// an empty ``entry`` structure. You can test for this condition by querying the
// type of the entry:
//
// .. code:: c++
//
// 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
// }
//
// For instance, you cannot generate a torrent with 0 files in it. If you don't add
// any files to the ``file_storage``, torrent generation will fail.
entry generate() const;
// returns an immutable reference to the file_storage used to create
// the torrent from.
file_storage const& files() const { return m_files; }
// Sets the comment for the torrent. The string ``str`` should be utf-8 encoded.
// The comment in a torrent file is optional.
void set_comment(char const* str);
// Sets the creator of the torrent. The string ``str`` should be utf-8 encoded.
// This is optional.
void set_creator(char const* str);
// This sets the SHA-1 hash for the specified piece (``index``). 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 set_piece_hashes().
void set_hash(int index, sha1_hash const& h);
// This sets the sha1 hash for this file. This hash will end up under the key ``sha1``
// associated with this file (for multi-file torrents) or in the root info dictionary
// for single-file torrents.
void set_file_hash(int index, sha1_hash const& h);
// 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.
//
// The second function, ``add_http_seed()`` adds an HTTP seed instead.
void add_url_seed(std::string const& url);
void add_http_seed(std::string const& url);
// 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.
void add_node(std::pair<std::string, int> const& node);
// 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 http:// 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.
void add_tracker(std::string const& url, int tier = 0);
// This function sets an X.509 certificate in PEM format to the torrent. This makes the
// torrent an *SSL torrent*. 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 ssl-torrents_.
//
// The string is not the path to the cert, it's the actual content of the certificate,
// loaded into a std::string.
void set_root_cert(std::string const& pem);
// 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.
void set_priv(bool p) { m_private = p; }
bool priv() const { return m_private; }
// returns the number of pieces in the associated file_storage object.
int num_pieces() const { return m_files.num_pieces(); }
// ``piece_length()`` returns the piece size of all pieces but the
// last one. ``piece_size()`` returns the size of the specified piece.
// these functions are just forwarding to the associated file_storage.
int piece_length() const { return m_files.piece_length(); }
int piece_size(int i) const { return m_files.piece_size(i); }
// internal
bool should_add_file_hashes() const { return m_calculate_file_hashes; }
// This function returns the merkle hash tree, if the torrent was created as a merkle
// torrent. The tree is created by ``generate()`` 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 ``torrent_info::set_merkle_tree()`` function. From that point onwards, the
// tree will be saved in the resume data.
std::vector<sha1_hash> const& merkle_tree() const { return m_merkle_tree; }
private:
file_storage& m_files;
// if m_info_dict is initialized, it is
// used instead of m_files to generate
// the info dictionary
entry m_info_dict;
// the urls to the trackers
typedef std::pair<std::string, int> announce_entry;
std::vector<announce_entry> m_urls;
std::vector<std::string> m_url_seeds;
std::vector<std::string> m_http_seeds;
std::vector<sha1_hash> m_piece_hash;
std::vector<sha1_hash> m_filehashes;
// if we're generating a merkle torrent, this is the
// merkle tree we got. This should be saved in fast-resume
// in order to start seeding the torrent
mutable std::vector<sha1_hash> m_merkle_tree;
// dht nodes to add to the routing table/bootstrap from
typedef std::vector<std::pair<std::string, int> > nodes_t;
nodes_t m_nodes;
// the hash that identifies this torrent
// is mutable because it's calculated
// lazily
mutable sha1_hash m_info_hash;
// if a creation date is found in the torrent file
// this will be set to that, otherwise it'll be
// 1970, Jan 1
time_t m_creation_date;
// if a comment is found in the torrent file
// this will be set to that comment
std::string m_comment;
// an optional string naming the software used
// to create the torrent file
std::string m_created_by;
// this is the root cert for SSL torrents
std::string m_root_cert;
// this is used when creating a torrent. If there's
// only one file there are cases where it's impossible
// to know if it should be written as a multifile torrent
// or not. e.g. test/test there's one file and one directory
// and they have the same name.
bool m_multifile:1;
// this is true if the torrent is private. i.e., is should not
// be announced on the dht
bool m_private:1;
// if set to one, a merkle torrent will be generated
bool m_merkle_torrent:1;
// if set, include the 'mtime' modification time in the
// torrent file
bool m_include_mtime:1;
// if set, symbolic links are declared as such in
// the torrent file. The full data of the pointed-to
// file is still included
bool m_include_symlinks:1;
// this is only used by set_piece_hashes(). It will
// calculate sha1 hashes for each file and add it
// to the file list
bool m_calculate_file_hashes:1;
};
namespace detail
{
inline bool default_pred(std::string const&) { return true; }
inline bool ignore_subdir(std::string const& leaf)
{ return leaf == ".." || leaf == "."; }
inline void nop(int) {}
int get_file_attributes(std::string const& p);
std::string get_symlink_path(std::string const& p);
// internal
TORRENT_EXPORT void add_files_impl(file_storage& fs, std::string const& p
, std::string const& l, boost::function<bool(std::string)> pred
, boost::uint32_t flags);
}
// Adds the file specified by ``path`` to the file_storage object. In case ``path``
// refers to a diretory, files will be added recursively from the directory.
//
// If specified, the predicate ``p`` is called once for every file and directory that
// is encountered. files for which ``p`` returns true are added, and directories for
// which ``p`` returns true are traversed. ``p`` must have the following signature::
//
// bool Pred(std::string const& 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.
//
// The ".." directory is never traversed.
//
// The ``flags`` argument should be the same as the flags passed to the `create_torrent`_
// constructor.
template <class Pred> void add_files(file_storage& fs, std::string const& file, Pred p, boost::uint32_t flags = 0)
{
detail::add_files_impl(fs, parent_path(complete(file)), filename(file), p, flags);
}
inline void add_files(file_storage& fs, std::string const& file, boost::uint32_t flags = 0)
{
detail::add_files_impl(fs, parent_path(complete(file)), filename(file)
, detail::default_pred, flags);
}
// This function will assume that the files added to the torrent file exists at path
// ``p``, read those files and hash the content and set the hashes in the ``create_torrent``
// object. The optional function ``f`` is called in between every hash that is set. ``f``
// must have the following signature::
//
// void Fun(int);
//
// The overloads that don't take an ``error_code&`` may throw an exception in case of a
// file error, the other overloads sets the error code to reflect the error, if any.
TORRENT_EXPORT void set_piece_hashes(create_torrent& t, std::string const& p
, boost::function<void(int)> f, error_code& ec);
inline void set_piece_hashes(create_torrent& t, std::string const& p, error_code& ec)
{
set_piece_hashes(t, p, detail::nop, ec);
}
#ifndef BOOST_NO_EXCEPTIONS
inline void set_piece_hashes(create_torrent& t, std::string const& p)
{
error_code ec;
set_piece_hashes(t, p, detail::nop, ec);
if (ec) throw libtorrent_exception(ec);
}
template <class Fun>
void set_piece_hashes(create_torrent& t, std::string const& p, Fun f)
{
error_code ec;
set_piece_hashes(t, p, f, ec);
if (ec) throw libtorrent_exception(ec);
}
#endif
#if TORRENT_USE_WSTRING
// wstring versions
// all wstring APIs are deprecated since 0.16.11
// instead, use the wchar -> utf8 conversion functions
// and pass in utf8 strings
#ifndef TORRENT_NO_DEPRECATE
template <class Pred>
TORRENT_DEPRECATED_PREFIX
void TORRENT_DEPRECATED add_files(file_storage& fs, std::wstring const& wfile, Pred p, boost::uint32_t flags = 0)
{
std::string utf8;
wchar_utf8(wfile, utf8);
detail::add_files_impl(fs, parent_path(complete(utf8))
, filename(utf8), p, flags);
}
TORRENT_DEPRECATED_PREFIX
inline void TORRENT_DEPRECATED add_files(file_storage& fs, std::wstring const& wfile, boost::uint32_t flags = 0)
{
std::string utf8;
wchar_utf8(wfile, utf8);
detail::add_files_impl(fs, parent_path(complete(utf8))
, filename(utf8), detail::default_pred, flags);
}
void TORRENT_EXPORT set_piece_hashes(create_torrent& t, std::wstring const& p
, boost::function<void(int)> const& f, error_code& ec);
#ifndef BOOST_NO_EXCEPTIONS
template <class Fun>
TORRENT_DEPRECATED_PREFIX
void TORRENT_DEPRECATED set_piece_hashes(create_torrent& t, std::wstring const& p, Fun f)
{
error_code ec;
set_piece_hashes(t, p, f, ec);
if (ec) throw libtorrent_exception(ec);
}
TORRENT_DEPRECATED_PREFIX
inline void TORRENT_DEPRECATED set_piece_hashes(create_torrent& t, std::wstring const& p)
{
error_code ec;
set_piece_hashes(t, p, detail::nop, ec);
if (ec) throw libtorrent_exception(ec);
}
#endif
TORRENT_DEPRECATED_PREFIX
inline void TORRENT_DEPRECATED set_piece_hashes(create_torrent& t, std::wstring const& p, error_code& ec)
{
set_piece_hashes(t, p, detail::nop, ec);
}
#endif // TORRENT_NO_DEPRECATE
#endif // TORRENT_USE_WSTRING
}
#endif

View File

@@ -0,0 +1,103 @@
/*
Copyright (c) 2009-2014, 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_DEADLINE_TIMER_HPP_INCLUDED
#define TORRENT_DEADLINE_TIMER_HPP_INCLUDED
#ifdef __OBJC__
#define Protocol Protocol_
#endif
#if __GNUC__ < 3
// in GCC 2.95 templates seems to have all symbols
// resolved as they are parsed, so the time_traits
// template actually needs the definitions it uses,
// even though it's never instantiated
#include <boost/date_time/posix_time/posix_time_types.hpp>
#else
#include <boost/date_time/posix_time/posix_time_duration.hpp>
#endif
#if BOOST_VERSION < 103500
#include <asio/basic_deadline_timer.hpp>
#else
#include <boost/asio/basic_deadline_timer.hpp>
#endif
#ifdef __OBJC__
#undef Protocol
#endif
#include "libtorrent/time.hpp"
// asio time_traits
#if !TORRENT_USE_BOOST_DATE_TIME
#if BOOST_VERSION >= 103500
namespace boost {
#endif
namespace asio
{
template<>
struct time_traits<libtorrent::ptime>
{
typedef libtorrent::ptime time_type;
typedef libtorrent::time_duration duration_type;
static time_type now()
{ return time_type(libtorrent::time_now_hires()); }
static time_type add(time_type t, duration_type d)
{ return time_type(t.time + d.diff);}
static duration_type subtract(time_type t1, time_type t2)
{ return duration_type(t1 - t2); }
static bool less_than(time_type t1, time_type t2)
{ return t1 < t2; }
static boost::posix_time::time_duration to_posix_duration(
duration_type d)
{ return boost::posix_time::microseconds(libtorrent::total_microseconds(d)); }
};
}
#if BOOST_VERSION >= 103500
}
#endif
#endif
namespace libtorrent
{
#if BOOST_VERSION < 103500
typedef ::asio::basic_deadline_timer<libtorrent::ptime> deadline_timer;
#else
typedef boost::asio::basic_deadline_timer<libtorrent::ptime> deadline_timer;
#endif
}
#endif // TORRENT_DEADLINE_TIMER_HPP_INCLUDED

View File

@@ -0,0 +1,219 @@
/*
Copyright (c) 2003-2014, 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_DEBUG_HPP_INCLUDED
#define TORRENT_DEBUG_HPP_INCLUDED
#if defined TORRENT_ASIO_DEBUGGING
#include "libtorrent/assert.hpp"
#include "libtorrent/thread.hpp"
#include <map>
#include <cstring>
std::string demangle(char const* name);
namespace libtorrent
{
struct async_t
{
async_t() : refs(0) {}
std::string stack;
int refs;
};
extern std::map<std::string, async_t> _async_ops;
extern int _async_ops_nthreads;
extern mutex _async_ops_mutex;
inline void add_outstanding_async(char const* name)
{
mutex::scoped_lock l(_async_ops_mutex);
async_t& a = _async_ops[name];
if (a.stack.empty())
{
char stack_text[10000];
print_backtrace(stack_text, sizeof(stack_text), 9);
a.stack = stack_text;
}
++a.refs;
}
inline void complete_async(char const* name)
{
mutex::scoped_lock l(_async_ops_mutex);
async_t& a = _async_ops[name];
TORRENT_ASSERT(a.refs > 0);
--a.refs;
}
inline void async_inc_threads()
{
mutex::scoped_lock l(_async_ops_mutex);
++_async_ops_nthreads;
}
inline void async_dec_threads()
{
mutex::scoped_lock l(_async_ops_mutex);
--_async_ops_nthreads;
}
inline int log_async()
{
mutex::scoped_lock l(_async_ops_mutex);
int ret = 0;
for (std::map<std::string, async_t>::iterator i = _async_ops.begin()
, end(_async_ops.end()); i != end; ++i)
{
if (i->second.refs <= _async_ops_nthreads - 1) continue;
ret += i->second.refs;
printf("%s: (%d)\n%s\n", i->first.c_str(), i->second.refs, i->second.stack.c_str());
}
return ret;
}
}
#endif
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
#include <cstring>
#include "libtorrent/config.hpp"
#include "libtorrent/file.hpp"
#include "libtorrent/thread.hpp"
#if TORRENT_USE_IOSTREAM
#include <string>
#include <fstream>
#include <iostream>
#endif
namespace libtorrent
{
// DEBUG API
struct logger
{
#if TORRENT_USE_IOSTREAM
// all log streams share a single file descriptor
// and re-opens the file for each log line
// these members are defined in session_impl.cpp
static std::ofstream log_file;
static std::string open_filename;
static mutex file_mutex;
#endif
~logger()
{
mutex::scoped_lock l(file_mutex);
log_file.close();
open_filename.clear();
}
logger(std::string const& logpath, std::string const& filename
, int instance, bool append)
{
char log_name[512];
snprintf(log_name, sizeof(log_name), "libtorrent_logs%d", instance);
std::string dir(complete(combine_path(combine_path(logpath, log_name), filename)) + ".log");
error_code ec;
if (!exists(parent_path(dir)))
create_directories(parent_path(dir), ec);
m_filename = dir;
mutex::scoped_lock l(file_mutex);
open(!append);
log_file << "\n\n\n*** starting log ***\n";
}
void move_log_file(std::string const& logpath, std::string const& new_name, int instance)
{
mutex::scoped_lock l(file_mutex);
if (open_filename == m_filename)
{
log_file.close();
open_filename.clear();
}
char log_name[512];
snprintf(log_name, sizeof(log_name), "libtorrent_logs%d", instance);
std::string dir(combine_path(combine_path(complete(logpath), log_name), new_name) + ".log");
error_code ec;
create_directories(parent_path(dir), ec);
if (ec)
fprintf(stderr, "Failed to create logfile directory %s: %s\n"
, parent_path(dir).c_str(), ec.message().c_str());
ec.clear();
rename(m_filename, dir, ec);
if (ec)
fprintf(stderr, "Failed to move logfile %s: %s\n"
, parent_path(dir).c_str(), ec.message().c_str());
m_filename = dir;
}
#if TORRENT_USE_IOSTREAM
void open(bool truncate)
{
if (open_filename == m_filename) return;
log_file.close();
log_file.clear();
log_file.open(m_filename.c_str(), truncate ? std::ios_base::trunc : std::ios_base::app);
open_filename = m_filename;
if (!log_file.good())
fprintf(stderr, "Failed to open logfile %s: %s\n", m_filename.c_str(), strerror(errno));
}
#endif
template <class T>
logger& operator<<(T const& v)
{
#if TORRENT_USE_IOSTREAM
mutex::scoped_lock l(file_mutex);
open(false);
log_file << v;
#endif
return *this;
}
std::string m_filename;
};
}
#endif // TORRENT_VERBOSE_LOGGING || TORRENT_LOGGING || TORRENT_ERROR_LOGGING
#endif // TORRENT_DEBUG_HPP_INCLUDED

View File

@@ -0,0 +1,101 @@
/*
Copyright (c) 2008-2014, 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_DISK_BUFFER_HOLDER_HPP_INCLUDED
#define TORRENT_DISK_BUFFER_HOLDER_HPP_INCLUDED
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
#include <algorithm>
namespace libtorrent
{
namespace aux { struct session_impl; }
struct disk_buffer_pool;
// The disk buffer holder acts like a ``scoped_ptr`` that frees a disk buffer
// when it's destructed, unless it's released. ``release`` returns the disk
// buffer and transferres ownership and responsibility to free it to the caller.
//
// A disk buffer is freed by passing it to ``session_impl::free_disk_buffer()``.
//
// ``buffer()`` returns the pointer without transferring responsibility. If
// this buffer has been released, ``buffer()`` will return 0.
struct TORRENT_EXPORT disk_buffer_holder
{
// internal
disk_buffer_holder(aux::session_impl& ses, char* buf);
// construct a buffer holder that will free the held buffer
// using a disk buffer pool directly (there's only one
// disk_buffer_pool per session)
disk_buffer_holder(disk_buffer_pool& disk_pool, char* buf);
// frees any unreleased disk buffer held by this object
~disk_buffer_holder();
// return the held disk buffer and clear it from the
// holder. The responsibility to free it is passed on
// to the caller
char* release();
// return a pointer to the held buffer
char* get() const { return m_buf; }
// set the holder object to hold the specified buffer
// (or NULL by default). If it's already holding a
// disk buffer, it will first be freed.
void reset(char* buf = 0);
// swap pointers of two disk buffer holders.
void swap(disk_buffer_holder& h)
{
TORRENT_ASSERT(&h.m_disk_pool == &m_disk_pool);
std::swap(h.m_buf, m_buf);
}
typedef char* (disk_buffer_holder::*unspecified_bool_type)();
// internal
operator unspecified_bool_type() const
{ return m_buf == 0? 0: &disk_buffer_holder::release; }
private:
disk_buffer_pool& m_disk_pool;
char* m_buf;
};
}
#endif

View File

@@ -0,0 +1,145 @@
/*
Copyright (c) 2007-2014, 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_DISK_BUFFER_POOL
#define TORRENT_DISK_BUFFER_POOL
#include <boost/utility.hpp>
#include "libtorrent/config.hpp"
#include "libtorrent/thread.hpp"
#include "libtorrent/session_settings.hpp"
#include "libtorrent/allocator.hpp"
#ifndef TORRENT_DISABLE_POOL_ALLOCATOR
#include <boost/pool/pool.hpp>
#endif
#ifdef TORRENT_DISK_STATS
#include <fstream>
#endif
#if TORRENT_USE_ASSERTS || TORRENT_DISK_STATS
#include <boost/unordered_map.hpp>
#endif
namespace libtorrent
{
struct TORRENT_EXTRA_EXPORT disk_buffer_pool : boost::noncopyable
{
disk_buffer_pool(int block_size);
#if TORRENT_USE_ASSERTS
~disk_buffer_pool();
#endif
#if TORRENT_USE_ASSERTS || TORRENT_DISK_STATS
bool is_disk_buffer(char* buffer
, mutex::scoped_lock& l) const;
bool is_disk_buffer(char* buffer) const;
#endif
char* allocate_buffer(char const* category);
void free_buffer(char* buf);
void free_multiple_buffers(char** bufvec, int numbufs);
int block_size() const { return m_block_size; }
#ifdef TORRENT_STATS
int disk_allocations() const
{ return m_allocations; }
#endif
#ifdef TORRENT_DISK_STATS
std::ofstream m_disk_access_log;
#endif
void release_memory();
int in_use() const { return m_in_use; }
protected:
void free_buffer_impl(char* buf, mutex::scoped_lock& l);
// number of bytes per block. The BitTorrent
// protocol defines the block size to 16 KiB.
const int m_block_size;
// number of disk buffers currently allocated
int m_in_use;
session_settings m_settings;
private:
mutable mutex m_pool_mutex;
#ifndef TORRENT_DISABLE_POOL_ALLOCATOR
// if this is true, all buffers are allocated
// from m_pool. If this is false, all buffers
// are allocated using page_aligned_allocator.
// if the settings change to prefer the other
// allocator, this bool will not switch over
// to match the settings until all buffers have
// been freed. That way, we never have a mixture
// of buffers allocated from different sources.
// in essence, this make the setting only take
// effect after a restart (which seems fine).
// or once the client goes idle for a while.
bool m_using_pool_allocator;
// memory pool for read and write operations
// and disk cache
boost::pool<page_aligned_allocator> m_pool;
#endif
#if defined TORRENT_DISK_STATS || defined TORRENT_STATS
int m_allocations;
#endif
#ifdef TORRENT_DISK_STATS
public:
void rename_buffer(char* buf, char const* category);
protected:
boost::unordered_map<std::string, int> m_categories;
boost::unordered_map<char*, std::string> m_buf_to_category;
std::ofstream m_log;
private:
#endif
#if TORRENT_USE_ASSERTS
int m_magic;
#endif
};
}
#endif // TORRENT_DISK_BUFFER_POOL

View File

@@ -0,0 +1,534 @@
/*
Copyright (c) 2007-2014, 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_DISK_IO_THREAD
#define TORRENT_DISK_IO_THREAD
#include "libtorrent/storage.hpp"
#include "libtorrent/allocator.hpp"
#include "libtorrent/io_service.hpp"
#include "libtorrent/sliding_average.hpp"
#include <boost/function/function0.hpp>
#include <boost/function/function2.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_array.hpp>
#include <deque>
#include "libtorrent/config.hpp"
#include "libtorrent/thread.hpp"
#include "libtorrent/disk_buffer_pool.hpp"
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/mem_fun.hpp>
namespace libtorrent
{
using boost::multi_index::multi_index_container;
using boost::multi_index::ordered_non_unique;
using boost::multi_index::ordered_unique;
using boost::multi_index::indexed_by;
using boost::multi_index::member;
using boost::multi_index::const_mem_fun;
struct cached_piece_info
{
// the piece index for this cache entry.
int piece;
// holds one entry for each block in this piece. ``true`` represents
// the data for that block being in the disk cache and ``false`` means it's not.
std::vector<bool> blocks;
// the time when a block was last written to this piece. The older
// a piece is, the more likely it is to be flushed to disk.
ptime last_use;
// The index of the next block that needs to be hashed.
// Blocks are hashed as they are downloaded in order to not
// have to re-read them from disk once the piece is complete, to
// compare its hash against the hashes in the .torrent file.
int next_to_hash;
enum kind_t { read_cache = 0, write_cache = 1 };
// specifies if this piece is part of the read cache or the write cache.
kind_t kind;
};
struct disk_io_job
{
disk_io_job()
: buffer(0)
, buffer_size(0)
, piece(0)
, offset(0)
, max_cache_line(0)
, cache_min_time(0)
, action(read)
{}
enum action_t
{
read
, write
, hash
, move_storage
, release_files
, delete_files
, check_fastresume
, check_files
, save_resume_data
, rename_file
, abort_thread
, clear_read_cache
, abort_torrent
, update_settings
, read_and_hash
, cache_piece
, file_priority
#ifndef TORRENT_NO_DEPRECATE
, finalize_file
#endif
};
char* buffer;
// this is called when operation completes
boost::function<void(int, disk_io_job const&)> callback;
boost::intrusive_ptr<piece_manager> storage;
boost::shared_ptr<entry> resume_data;
// the error code from the file operation
error_code error;
// the time when this job was issued. This is used to
// keep track of disk I/O congestion
ptime start_time;
// used for move_storage and rename_file. On errors, this is set
// to the error message
std::string str;
// on error, this is set to the path of the
// file the disk operation failed on
std::string error_file;
int buffer_size;
// arguments used for read and write
// piece is used as flags for move_storage
int piece, offset;
// if this is > 0, it specifies the max number of blocks to read
// ahead in the read cache for this access. This is only valid
// for 'read' actions
int max_cache_line;
// if this is > 0, it may increase the minimum time the cache
// line caused by this operation stays in the cache
int cache_min_time;
boost::uint8_t action;
};
// returns true if the fundamental operation
// of the given disk job is a read operation
bool is_read_operation(disk_io_job const& j);
// this is true if the buffer field in the disk_io_job
// points to a disk buffer
bool operation_has_buffer(disk_io_job const& j);
// this struct holds a number of statistics counters
// relevant for the disk io thread and disk cache.
struct TORRENT_EXPORT cache_status
{
// initializes all counters to 0
cache_status()
: blocks_written(0)
, writes(0)
, blocks_read(0)
, blocks_read_hit(0)
, reads(0)
, queued_bytes(0)
, cache_size(0)
, read_cache_size(0)
, total_used_buffers(0)
, average_queue_time(0)
, average_read_time(0)
, average_write_time(0)
, average_hash_time(0)
, average_job_time(0)
, average_sort_time(0)
, job_queue_length(0)
, cumulative_job_time(0)
, cumulative_read_time(0)
, cumulative_write_time(0)
, cumulative_hash_time(0)
, cumulative_sort_time(0)
, total_read_back(0)
, read_queue_size(0)
{}
// the total number of 16 KiB blocks written to disk
// since this session was started.
size_type blocks_written;
// the total number of write operations performed since this
// session was started.
//
// The ratio (``blocks_written`` - ``writes``) / ``blocks_written`` represents
// the number of saved write operations per total write operations. i.e. a kind
// of cache hit ratio for the write cahe.
size_type writes;
// the number of blocks that were requested from the
// bittorrent engine (from peers), that were served from disk or cache.
size_type blocks_read;
// the number of blocks that was just copied from the read cache
//
// The ratio ``blocks_read_hit`` / ``blocks_read`` is the cache hit ratio
// for the read cache.
size_type blocks_read_hit;
// the number of read operations used
size_type reads;
// the number of bytes waiting, in the disk job queue, to be written
// or inserted into the disk cache
mutable size_type queued_bytes;
// the number of 16 KiB blocks currently in the disk cache (both read and write).
// This includes both read and write cache.
int cache_size;
// the number of 16KiB blocks in the read cache.
int read_cache_size;
// the total number of buffers currently in use.
// This includes the read/write disk cache as well as send and receive buffers
// used in peer connections.
mutable int total_used_buffers;
// the number of microseconds an average disk I/O job
// has to wait in the job queue before it get processed.
int average_queue_time;
// the time read jobs takes on average to complete
// (not including the time in the queue), in microseconds. This only measures
// read cache misses.
int average_read_time;
// the time write jobs takes to complete, on average,
// in microseconds. This does not include the time the job sits in the disk job
// queue or in the write cache, only blocks that are flushed to disk.
int average_write_time;
// the time hash jobs takes to complete on average, in
// microseconds. Hash jobs include running SHA-1 on the data (which for the most
// part is done incrementally) and sometimes reading back parts of the piece. It
// also includes checking files without valid resume data.
int average_hash_time;
int average_job_time;
int average_sort_time;
// the number of jobs in the job queue.
int job_queue_length;
// the number of milliseconds spent in all disk jobs, and specific ones
// since the start of the session. Times are specified in milliseconds
boost::uint32_t cumulative_job_time;
boost::uint32_t cumulative_read_time;
boost::uint32_t cumulative_write_time;
boost::uint32_t cumulative_hash_time;
boost::uint32_t cumulative_sort_time;
// the number of blocks that had to be read back from disk because
// they were flushed before the SHA-1 hash got to hash them. If this
// is large, a larger cache could significantly improve performance
int total_read_back;
// number of read jobs in the disk job queue
int read_queue_size;
};
// this is a singleton consisting of the thread and a queue
// of disk io jobs
struct TORRENT_EXTRA_EXPORT disk_io_thread : disk_buffer_pool
{
disk_io_thread(io_service& ios
, boost::function<void()> const& queue_callback
, file_pool& fp
, int block_size = 16 * 1024);
~disk_io_thread();
void abort();
void join();
// aborts read operations
void stop(boost::intrusive_ptr<piece_manager> s);
// returns the disk write queue size
int add_job(disk_io_job const& j
, boost::function<void(int, disk_io_job const&)> const& f
= boost::function<void(int, disk_io_job const&)>());
// keep track of the number of bytes in the job queue
// at any given time. i.e. the sum of all buffer_size.
// this is used to slow down the download global download
// speed when the queue buffer size is too big.
size_type queue_buffer_size() const;
bool can_write() const;
void get_cache_info(sha1_hash const& ih
, std::vector<cached_piece_info>& ret) const;
cache_status status() const;
void thread_fun();
#if TORRENT_USE_INVARIANT_CHECKS
void check_invariant() const;
#endif
struct cached_block_entry
{
cached_block_entry(): buf(0) {}
// the buffer pointer (this is a disk_pool buffer)
// or 0
char* buf;
// callback for when this block is flushed to disk
boost::function<void(int, disk_io_job const&)> callback;
};
struct cached_piece_entry
{
int piece;
// storage this piece belongs to
boost::intrusive_ptr<piece_manager> storage;
// the pointers to the block data
boost::shared_array<cached_block_entry> blocks;
// the last time a block was writting to this piece
// plus the minimum amount of time the block is guaranteed
// to stay in the cache
ptime expire;
// the number of blocks in the cache for this piece
int num_blocks;
// used to determine if this piece should be flushed
int num_contiguous_blocks;
// this is the first block that has not yet been hashed
// by the partial hasher. When minimizing read-back, this
// is used to determine if flushing a range would force us
// to read it back later when hashing
int next_block_to_hash;
std::pair<void*, int> storage_piece_pair() const
{ return std::pair<void*, int>(storage.get(), piece); }
};
typedef multi_index_container<
cached_piece_entry, indexed_by<
ordered_unique<const_mem_fun<cached_piece_entry, std::pair<void*, int>
, &cached_piece_entry::storage_piece_pair> >
, ordered_non_unique<member<cached_piece_entry, ptime
, &cached_piece_entry::expire> >
>
> cache_t;
typedef cache_t::nth_index<0>::type cache_piece_index_t;
typedef cache_t::nth_index<1>::type cache_lru_index_t;
private:
int add_job(disk_io_job const& j
, mutex::scoped_lock& l
, boost::function<void(int, disk_io_job const&)> const& f
= boost::function<void(int, disk_io_job const&)>());
bool test_error(disk_io_job& j);
void post_callback(disk_io_job const& j, int ret);
// cache operations
cache_piece_index_t::iterator find_cached_piece(
cache_t& cache, disk_io_job const& j
, mutex::scoped_lock& l);
bool is_cache_hit(cached_piece_entry& p
, disk_io_job const& j, mutex::scoped_lock& l);
int copy_from_piece(cached_piece_entry& p, bool& hit
, disk_io_job const& j, mutex::scoped_lock& l);
struct ignore_t
{
ignore_t(): piece(-1), storage(0) {}
ignore_t(int idx, piece_manager* st): piece(idx), storage(st) {}
int piece;
piece_manager* storage;
};
// write cache operations
enum options_t { dont_flush_write_blocks = 1, ignore_cache_size = 2 };
int flush_cache_blocks(mutex::scoped_lock& l
, int blocks, ignore_t ignore = ignore_t(), int options = 0);
void flush_expired_pieces();
int flush_contiguous_blocks(cached_piece_entry& p
, mutex::scoped_lock& l, int lower_limit = 0, bool avoid_readback = false);
int flush_range(cached_piece_entry& p, int start, int end, mutex::scoped_lock& l);
int cache_block(disk_io_job& j
, boost::function<void(int,disk_io_job const&)>& handler
, int cache_expire
, mutex::scoped_lock& l);
// read cache operations
int clear_oldest_read_piece(int num_blocks, ignore_t ignore
, mutex::scoped_lock& l);
int read_into_piece(cached_piece_entry& p, int start_block
, int options, int num_blocks, mutex::scoped_lock& l);
int cache_read_block(disk_io_job const& j, mutex::scoped_lock& l);
int free_piece(cached_piece_entry& p, mutex::scoped_lock& l);
int drain_piece_bufs(cached_piece_entry& p, std::vector<char*>& buf
, mutex::scoped_lock& l);
enum cache_flags_t {
cache_only = 1
};
int try_read_from_cache(disk_io_job const& j, bool& hit, int flags = 0);
int read_piece_from_cache_and_hash(disk_io_job const& j, sha1_hash& h);
int cache_piece(disk_io_job const& j, cache_piece_index_t::iterator& p
, bool& hit, int options, mutex::scoped_lock& l);
// this mutex only protects m_jobs, m_queue_buffer_size,
// m_exceeded_write_queue and m_abort
mutable mutex m_queue_mutex;
event m_signal;
bool m_abort;
bool m_waiting_to_shutdown;
std::deque<disk_io_job> m_jobs;
size_type m_queue_buffer_size;
ptime m_last_file_check;
// this protects the piece cache and related members
mutable mutex m_piece_mutex;
// write cache
cache_t m_pieces;
// read cache
cache_t m_read_pieces;
void flip_stats(ptime now);
// total number of blocks in use by both the read
// and the write cache. This is not supposed to
// exceed m_cache_size
cache_status m_cache_stats;
// keeps average queue time for disk jobs (in microseconds)
average_accumulator m_queue_time;
// average read time for cache misses (in microseconds)
average_accumulator m_read_time;
// average write time (in microseconds)
average_accumulator m_write_time;
// average hash time (in microseconds)
average_accumulator m_hash_time;
// average time to serve a job (any job) in microseconds
average_accumulator m_job_time;
// average time to ask for physical offset on disk
// and insert into queue
average_accumulator m_sort_time;
// the last time we reset the average time and store the
// latest value in m_cache_stats
ptime m_last_stats_flip;
typedef std::multimap<size_type, disk_io_job> read_jobs_t;
read_jobs_t m_sorted_read_jobs;
#ifdef TORRENT_DISK_STATS
std::ofstream m_log;
#endif
// the amount of physical ram in the machine
boost::uint64_t m_physical_ram;
// if we exceeded the max queue disk write size
// this is set to true. It remains true until the
// queue is smaller than the low watermark
bool m_exceeded_write_queue;
io_service& m_ios;
boost::function<void()> m_queue_callback;
// this keeps the io_service::run() call blocked from
// returning. When shutting down, it's possible that
// the event queue is drained before the disk_io_thread
// has posted its last callback. When this happens, the
// io_service will have a pending callback from the
// disk_io_thread, but the event loop is not running.
// this means that the event is destructed after the
// disk_io_thread. If the event refers to a disk buffer
// it will try to free it, but the buffer pool won't
// exist anymore, and crash. This prevents that.
boost::optional<io_service::work> m_work;
// reference to the file_pool which is a member of
// the session_impl object
file_pool& m_file_pool;
// when completion notifications are queued, they're stuck
// in this list
std::list<std::pair<disk_io_job, int> > m_queued_completions;
#if TORRENT_USE_ASSERTS
int m_magic;
#endif
// thread for performing blocking disk io operations
thread m_disk_io_thread;
};
}
#endif

View File

@@ -0,0 +1,32 @@
#ifndef ED25519_HPP
#define ED25519_HPP
#include "libtorrent/export.hpp" // for TORRENT_EXPORT
#include <stddef.h> // for size_t
enum
{
ed25519_seed_size = 32,
ed25519_private_key_size = 64,
ed25519_public_key_size = 32,
ed25519_signature_size = 64,
ed25519_scalar_size = 32,
ed25519_shared_secret_size = 32
};
extern "C" {
#ifndef ED25519_NO_SEED
int TORRENT_EXPORT ed25519_create_seed(unsigned char *seed);
#endif
void TORRENT_EXPORT ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed);
void TORRENT_EXPORT ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key);
int TORRENT_EXPORT ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *private_key);
void TORRENT_EXPORT ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar);
void TORRENT_EXPORT ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key);
}
#endif // ED25519_HPP

View File

@@ -0,0 +1,310 @@
/*
Copyright (c) 2003-2014, 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_ENTRY_HPP_INCLUDED
#define TORRENT_ENTRY_HPP_INCLUDED
/*
*
* This file declares the entry class. It is a
* variant-type that can be an integer, list,
* dictionary (map) or a string. This type is
* used to hold bdecoded data (which is the
* encoding BitTorrent messages uses).
*
* it has 4 accessors to access the actual
* type of the object. They are:
* integer()
* string()
* list()
* dict()
* The actual type has to match the type you
* are asking for, otherwise you will get an
* assertion failure.
* When you default construct an entry, it is
* uninitialized. You can initialize it through the
* assignment operator, copy-constructor or
* the constructor that takes a data_type enum.
*
*
*/
#include <map>
#include <list>
#include <string>
#include <stdexcept>
#include "libtorrent/size_type.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/error_code.hpp"
#include "libtorrent/max.hpp"
#if TORRENT_USE_IOSTREAM
#include <iosfwd>
#endif
namespace libtorrent
{
struct lazy_entry;
// thrown by any accessor function of entry if the accessor
// function requires a type different than the actual type
// of the entry object.
struct TORRENT_EXPORT type_error: std::runtime_error
{
// internal
type_error(const char* error): std::runtime_error(error) {}
};
// The ``entry`` class represents one node in a bencoded hierarchy. It works as a
// variant type, it can be either a list, a dictionary (``std::map``), an integer
// or a string.
class TORRENT_EXPORT entry
{
public:
// the key is always a string. If a generic entry would be allowed
// as a key, sorting would become a problem (e.g. to compare a string
// to a list). The definition doesn't mention such a limit though.
typedef std::map<std::string, entry> dictionary_type;
typedef std::string string_type;
typedef std::list<entry> list_type;
typedef size_type integer_type;
// the types an entry can have
enum data_type
{
int_t,
string_t,
list_t,
dictionary_t,
undefined_t
};
// returns the concrete type of the entry
data_type type() const;
// constructors directly from a specific type.
// The content of the argument is copied into the
// newly constructed entry
entry(dictionary_type const&);
entry(string_type const&);
entry(list_type const&);
entry(integer_type const&);
// construct an empty entry of the specified type.
// see data_type enum.
entry(data_type t);
// hidden
entry(entry const& e);
// hidden
entry();
// hidden
~entry();
// hidden
bool operator==(entry const& e) const;
bool operator!=(entry const& e) const { return !(*this == e); }
// copies the structure of the right hand side into this
// entry.
void operator=(lazy_entry const&);
void operator=(entry const&);
void operator=(dictionary_type const&);
void operator=(string_type const&);
void operator=(list_type const&);
void operator=(integer_type const&);
// The ``integer()``, ``string()``, ``list()`` and ``dict()`` functions
// are accessors that return the respective type. If the ``entry`` object
// isn't of the type you request, the accessor will throw
// libtorrent_exception (which derives from ``std::runtime_error``). You
// can ask an ``entry`` for its type through the ``type()`` function.
//
// If you want to create an ``entry`` 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.
//
// The typical code to get info from a torrent file will then look like
// this:
//
// .. code:: c++
//
// 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";
// }
//
//
// The following code is equivalent, but a little bit shorter:
//
// .. code:: c++
//
// 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";
// }
//
//
// To make it easier to extract information from a torrent file, the
// class torrent_info exists.
integer_type& integer();
const integer_type& integer() const;
string_type& string();
const string_type& string() const;
list_type& list();
const list_type& list() const;
dictionary_type& dict();
const dictionary_type& dict() const;
// swaps the content of *this* with ``e``.
void swap(entry& e);
// All of these functions requires the entry to be a dictionary, if it
// isn't they will throw ``libtorrent::type_error``.
//
// The non-const versions of the ``operator[]`` 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.
//
// The const version of ``operator[]`` will only return a reference to an
// existing element at the given key. If the key is not found, it will
// throw ``libtorrent::type_error``.
entry& operator[](char const* key);
entry& operator[](std::string const& key);
#ifndef BOOST_NO_EXCEPTIONS
const entry& operator[](char const* key) const;
const entry& operator[](std::string const& key) const;
#endif
// These functions requires the entry to be a dictionary, if it isn't
// they will throw ``libtorrent::type_error``.
//
// 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.
entry* find_key(char const* key);
entry const* find_key(char const* key) const;
entry* find_key(std::string const& key);
entry const* find_key(std::string const& key) const;
// returns a pretty-printed string representation
// of the bencoded structure, with JSON-style syntax
std::string to_string() const;
protected:
void construct(data_type t);
void copy(const entry& e);
void destruct();
private:
void to_string_impl(std::string& out, int indent) const;
#if (defined(_MSC_VER) && _MSC_VER < 1310) || TORRENT_COMPLETE_TYPES_REQUIRED
// workaround for msvc-bug.
// assumes sizeof(map<string, char>) == sizeof(map<string, entry>)
// and sizeof(list<char>) == sizeof(list<entry>)
enum { union_size
= max4<sizeof(std::list<char>)
, sizeof(std::map<std::string, char>)
, sizeof(string_type)
, sizeof(integer_type)>::value
};
#else
enum { union_size
= max4<sizeof(list_type)
, sizeof(dictionary_type)
, sizeof(string_type)
, sizeof(integer_type)>::value
};
#endif
integer_type data[(union_size + sizeof(integer_type) - 1)
/ sizeof(integer_type)];
// the bitfield is used so that the m_type_queried field still fits, so
// that the ABI is the same for debug builds and release builds. It
// appears to be very hard to match debug builds with debug versions of
// libtorrent
boost::uint8_t m_type:7;
public:
// in debug mode this is set to false by bdecode to indicate that the
// program has not yet queried the type of this entry, 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.
mutable boost::uint8_t m_type_queried:1;
};
#if TORRENT_USE_IOSTREAM
// prints the bencoded structure to the ostream as a JSON-style structure.
inline std::ostream& operator<<(std::ostream& os, const entry& e)
{
os << e.to_string();
return os;
}
#endif
#ifndef BOOST_NO_EXCEPTIONS
// internal
inline void throw_type_error()
{
throw libtorrent_exception(error_code(errors::invalid_entry_type
, get_libtorrent_category()));
}
#endif
}
#endif // TORRENT_ENTRY_HPP_INCLUDED

View File

@@ -0,0 +1,83 @@
/*
Copyright (c) 2007-2014, 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_ENUM_NET_HPP_INCLUDED
#define TORRENT_ENUM_NET_HPP_INCLUDED
#include "libtorrent/config.hpp"
#include <vector>
#include "libtorrent/io_service_fwd.hpp"
#include "libtorrent/address.hpp"
#include "libtorrent/error_code.hpp"
namespace libtorrent
{
// the interface should not have a netmask
struct ip_interface
{
address interface_address;
address netmask;
char name[64];
int mtu;
};
struct ip_route
{
address destination;
address netmask;
address gateway;
char name[64];
int mtu;
};
// returns a list of the configured IP interfaces
// on the machine
TORRENT_EXTRA_EXPORT std::vector<ip_interface> enum_net_interfaces(io_service& ios
, error_code& ec);
TORRENT_EXTRA_EXPORT std::vector<ip_route> enum_routes(io_service& ios, error_code& ec);
// return (a1 & mask) == (a2 & mask)
TORRENT_EXTRA_EXPORT bool match_addr_mask(address const& a1, address const& a2, address const& mask);
// returns true if the specified address is on the same
// local network as us
TORRENT_EXTRA_EXPORT bool in_local_network(io_service& ios, address const& addr
, error_code& ec);
TORRENT_EXTRA_EXPORT address get_default_gateway(io_service& ios
, error_code& ec);
}
#endif

View File

@@ -0,0 +1,62 @@
/*
Copyright (c) 2009-2014, 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_ERROR_HPP_INCLUDED
#define TORRENT_ERROR_HPP_INCLUDED
#include <boost/version.hpp>
#include "libtorrent/config.hpp"
#if defined TORRENT_WINDOWS || defined TORRENT_CYGWIN
// asio assumes that the windows error codes are defined already
#include <winsock2.h>
#endif
#if BOOST_VERSION < 103500
#include <asio/error.hpp>
#else
#include <boost/asio/error.hpp>
#endif
namespace libtorrent
{
#if BOOST_VERSION < 103500
namespace error = asio::error;
#else
namespace error = boost::asio::error;
#endif
}
#endif

View File

@@ -0,0 +1,562 @@
/*
Copyright (c) 2008-2014, 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_ERROR_CODE_HPP_INCLUDED
#define TORRENT_ERROR_CODE_HPP_INCLUDED
#include <boost/version.hpp>
#include "libtorrent/config.hpp"
#if defined TORRENT_WINDOWS || defined TORRENT_CYGWIN
// asio assumes that the windows error codes are defined already
#include <winsock2.h>
#endif
#if BOOST_VERSION < 103500
#include <asio/error_code.hpp>
#else
#include <boost/system/error_code.hpp>
#endif
#include "libtorrent/string_util.hpp" // for allocate_string_copy
#include <stdlib.h> // free
#ifndef BOOST_SYSTEM_NOEXCEPT
#define BOOST_SYSTEM_NOEXCEPT throw()
#endif
namespace libtorrent
{
namespace errors
{
// libtorrent uses boost.system's ``error_code`` class to represent errors. libtorrent has
// its own error category get_libtorrent_category() whith the error codes defined by error_code_enum.
enum error_code_enum
{
// Not an error
no_error = 0,
// Two torrents has files which end up overwriting each other
file_collision,
// A piece did not match its piece hash
failed_hash_check,
// The .torrent file does not contain a bencoded dictionary at
// its top level
torrent_is_no_dict,
// The .torrent file does not have an ``info`` dictionary
torrent_missing_info,
// The .torrent file's ``info`` entry is not a dictionary
torrent_info_no_dict,
// The .torrent file does not have a ``piece length`` entry
torrent_missing_piece_length,
// The .torrent file does not have a ``name`` entry
torrent_missing_name,
// The .torrent file's name entry is invalid
torrent_invalid_name,
// The length of a file, or of the whole .torrent file is invalid.
// Either negative or not an integer
torrent_invalid_length,
// Failed to parse a file entry in the .torrent
torrent_file_parse_failed,
// The ``pieces`` field is missing or invalid in the .torrent file
torrent_missing_pieces,
// The ``pieces`` string has incorrect length
torrent_invalid_hashes,
// The .torrent file has more pieces than is supported by libtorrent
too_many_pieces_in_torrent,
// The metadata (.torrent file) that was received from the swarm
// matched the info-hash, but failed to be parsed
invalid_swarm_metadata,
// The file or buffer is not correctly bencoded
invalid_bencoding,
// The .torrent file does not contain any files
no_files_in_torrent,
// The string was not properly url-encoded as expected
invalid_escaped_string,
// Operation is not permitted since the session is shutting down
session_is_closing,
// There's already a torrent with that info-hash added to the
// session
duplicate_torrent,
// The supplied torrent_handle is not referring to a valid torrent
invalid_torrent_handle,
// The type requested from the entry did not match its type
invalid_entry_type,
// The specified URI does not contain a valid info-hash
missing_info_hash_in_uri,
// One of the files in the torrent was unexpectadly small. This
// might be caused by files being changed by an external process
file_too_short,
// The URL used an unknown protocol. Currently ``http`` and
// ``https`` (if built with openssl support) are recognized. For
// trackers ``udp`` is recognized as well.
unsupported_url_protocol,
// The URL did not conform to URL syntax and failed to be parsed
url_parse_error,
// The peer sent a 'piece' message of length 0
peer_sent_empty_piece,
// A bencoded structure was currupt and failed to be parsed
parse_failed,
// The fast resume file was missing or had an invalid file version
// tag
invalid_file_tag,
// The fast resume file was missing or had an invalid info-hash
missing_info_hash,
// The info-hash did not match the torrent
mismatching_info_hash,
// The URL contained an invalid hostname
invalid_hostname,
// The URL had an invalid port
invalid_port,
// The port is blocked by the port-filter, and prevented the
// connection
port_blocked,
// The IPv6 address was expected to end with ']'
expected_close_bracket_in_address,
// The torrent is being destructed, preventing the operation to
// succeed
destructing_torrent,
// The connection timed out
timed_out,
// The peer is upload only, and we are upload only. There's no point
// in keeping the connection
upload_upload_connection,
// The peer is upload only, and we're not interested in it. There's
// no point in keeping the connection
uninteresting_upload_peer,
// The peer sent an unknown info-hash
invalid_info_hash,
// The torrent is paused, preventing the operation from succeeding
torrent_paused,
// The peer sent an invalid have message, either wrong size or
// referring to a piece that doesn't exist in the torrent
invalid_have,
// The bitfield message had the incorrect size
invalid_bitfield_size,
// The peer kept requesting pieces after it was choked, possible
// abuse attempt.
too_many_requests_when_choked,
// The peer sent a piece message that does not correspond to a
// piece request sent by the client
invalid_piece,
// memory allocation failed
no_memory,
// The torrent is aborted, preventing the operation to succeed
torrent_aborted,
// The peer is a connection to ourself, no point in keeping it
self_connection,
// The peer sent a piece message with invalid size, either negative
// or greater than one block
invalid_piece_size,
// The peer has not been interesting or interested in us for too
// long, no point in keeping it around
timed_out_no_interest,
// The peer has not said anything in a long time, possibly dead
timed_out_inactivity,
// The peer did not send a handshake within a reasonable amount of
// time, it might not be a bittorrent peer
timed_out_no_handshake,
// The peer has been unchoked for too long without requesting any
// data. It might be lying about its interest in us
timed_out_no_request,
// The peer sent an invalid choke message
invalid_choke,
// The peer send an invalid unchoke message
invalid_unchoke,
// The peer sent an invalid interested message
invalid_interested,
// The peer sent an invalid not-interested message
invalid_not_interested,
// The peer sent an invalid piece request message
invalid_request,
// The peer sent an invalid hash-list message (this is part of the
// merkle-torrent extension)
invalid_hash_list,
// The peer sent an invalid hash-piece message (this is part of the
// merkle-torrent extension)
invalid_hash_piece,
// The peer sent an invalid cancel message
invalid_cancel,
// The peer sent an invalid DHT port-message
invalid_dht_port,
// The peer sent an invalid suggest piece-message
invalid_suggest,
// The peer sent an invalid have all-message
invalid_have_all,
// The peer sent an invalid have none-message
invalid_have_none,
// The peer sent an invalid reject message
invalid_reject,
// The peer sent an invalid allow fast-message
invalid_allow_fast,
// The peer sent an invalid extesion message ID
invalid_extended,
// The peer sent an invalid message ID
invalid_message,
// The synchronization hash was not found in the encrypted handshake
sync_hash_not_found,
// The encryption constant in the handshake is invalid
invalid_encryption_constant,
// The peer does not support plaintext, which is the selected mode
no_plaintext_mode,
// The peer does not support rc4, which is the selected mode
no_rc4_mode,
// The peer does not support any of the encryption modes that the
// client supports
unsupported_encryption_mode,
// The peer selected an encryption mode that the client did not
// advertise and does not support
unsupported_encryption_mode_selected,
// The pad size used in the encryption handshake is of invalid size
invalid_pad_size,
// The encryption handshake is invalid
invalid_encrypt_handshake,
// The client is set to not support incoming encrypted connections
// and this is an encrypted connection
no_incoming_encrypted,
// The client is set to not support incoming regular bittorrent
// connections, and this is a regular connection
no_incoming_regular,
// The client is already connected to this peer-ID
duplicate_peer_id,
// Torrent was removed
torrent_removed,
// The packet size exceeded the upper sanity check-limit
packet_too_large,
reserved,
// The web server responded with an error
http_error,
// The web server response is missing a location header
missing_location,
// The web seed redirected to a path that no longer matches the
// .torrent directory structure
invalid_redirection,
// The connection was closed becaused it redirected to a different
// URL
redirecting,
// The HTTP range header is invalid
invalid_range,
// The HTTP response did not have a content length
no_content_length,
// The IP is blocked by the IP filter
banned_by_ip_filter,
// At the connection limit
too_many_connections,
// The peer is marked as banned
peer_banned,
// The torrent is stopping, causing the operation to fail
stopping_torrent,
// The peer has sent too many corrupt pieces and is banned
too_many_corrupt_pieces,
// The torrent is not ready to receive peers
torrent_not_ready,
// The peer is not completely constructed yet
peer_not_constructed,
// The session is closing, causing the operation to fail
session_closing,
// The peer was disconnected in order to leave room for a
// potentially better peer
optimistic_disconnect,
// The torrent is finished
torrent_finished,
// No UPnP router found
no_router,
// The metadata message says the metadata exceeds the limit
metadata_too_large,
// The peer sent an invalid metadata request message
invalid_metadata_request,
// The peer advertised an invalid metadata size
invalid_metadata_size,
// The peer sent a message with an invalid metadata offset
invalid_metadata_offset,
// The peer sent an invalid metadata message
invalid_metadata_message,
// The peer sent a peer exchange message that was too large
pex_message_too_large,
// The peer sent an invalid peer exchange message
invalid_pex_message,
// The peer sent an invalid tracker exchange message
invalid_lt_tracker_message,
// The peer sent an pex messages too often. This is a possible
// attempt of and attack
too_frequent_pex,
// The operation failed because it requires the torrent to have
// the metadata (.torrent file) and it doesn't have it yet.
// This happens for magnet links before they have downloaded the
// metadata, and also torrents added by URL.
no_metadata,
// The peer sent an invalid ``dont_have`` message. The dont have
// message is an extension to allow peers to advertise that the
// no longer has a piece they previously had.
invalid_dont_have,
// The peer tried to connect to an SSL torrent without connecting
// over SSL.
requires_ssl_connection,
// The peer tried to connect to a torrent with a certificate
// for a different torrent.
invalid_ssl_cert,
// the torrent is not an SSL torrent, and the operation requires
// an SSL torrent
not_an_ssl_torrent,
// The NAT-PMP router responded with an unsupported protocol version
unsupported_protocol_version = 120,
// You are not authorized to map ports on this NAT-PMP router
natpmp_not_authorized,
// The NAT-PMP router failed because of a network failure
network_failure,
// The NAT-PMP router failed because of lack of resources
no_resources,
// The NAT-PMP router failed because an unsupported opcode was sent
unsupported_opcode,
// The resume data file is missing the 'file sizes' entry
missing_file_sizes = 130,
// The resume data file 'file sizes' entry is empty
no_files_in_resume_data,
// The resume data file is missing the 'pieces' and 'slots' entry
missing_pieces,
// The number of files in the resume data does not match the number
// of files in the torrent
mismatching_number_of_files,
// One of the files on disk has a different size than in the fast
// resume file
mismatching_file_size,
// One of the files on disk has a different timestamp than in the
// fast resume file
mismatching_file_timestamp,
// The resume data file is not a dictionary
not_a_dictionary,
// The 'blocks per piece' entry is invalid in the resume data file
invalid_blocks_per_piece,
// The resume file is missing the 'slots' entry, which is required
// for torrents with compact allocation
missing_slots,
// The resume file contains more slots than the torrent
too_many_slots,
// The 'slot' entry is invalid in the resume data
invalid_slot_list,
// One index in the 'slot' list is invalid
invalid_piece_index,
// The pieces on disk needs to be re-ordered for the specified
// allocation mode. This happens if you specify sparse allocation
// and the files on disk are using compact storage. The pieces needs
// to be moved to their right position
pieces_need_reorder,
// The HTTP header was not correctly formatted
http_parse_error = 150,
// The HTTP response was in the 300-399 range but lacked a location
// header
http_missing_location,
// The HTTP response was encoded with gzip or deflate but
// decompressing it failed
http_failed_decompress,
// The URL specified an i2p address, but no i2p router is configured
no_i2p_router = 160,
// The tracker URL doesn't support transforming it into a scrape
// URL. i.e. it doesn't contain "announce.
scrape_not_available = 170,
// invalid tracker response
invalid_tracker_response,
// invalid peer dictionary entry. Not a dictionary
invalid_peer_dict,
// tracker sent a failure message
tracker_failure,
// missing or invalid 'files' entry
invalid_files_entry,
// missing or invalid 'hash' entry
invalid_hash_entry,
// missing or invalid 'peers' and 'peers6' entry
invalid_peers_entry,
// udp tracker response packet has invalid size
invalid_tracker_response_length,
// invalid transaction id in udp tracker response
invalid_tracker_transaction_id,
// invalid action field in udp tracker response
invalid_tracker_action,
#ifndef TORRENT_NO_DEPRECATE
// expected string in bencoded string
expected_string = 190,
// expected colon in bencoded string
expected_colon,
// unexpected end of file in bencoded string
unexpected_eof,
// expected value (list, dict, int or string) in bencoded string
expected_value,
// bencoded recursion depth limit exceeded
depth_exceeded,
// bencoded item count limit exceeded
limit_exceeded,
// integer overflow
overflow,
#endif
// the number of error codes
error_code_max
};
// HTTP errors are reported in the libtorrent::http_category, with error code enums in
// the ``libtorrent::errors`` namespace.
enum http_errors
{
cont = 100,
ok = 200,
created = 201,
accepted = 202,
no_content = 204,
multiple_choices = 300,
moved_permanently = 301,
moved_temporarily = 302,
not_modified = 304,
bad_request = 400,
unauthorized = 401,
forbidden = 403,
not_found = 404,
internal_server_error = 500,
not_implemented = 501,
bad_gateway = 502,
service_unavailable = 503
};
// hidden
TORRENT_EXPORT boost::system::error_code make_error_code(error_code_enum e);
} // namespace errors
#if BOOST_VERSION < 103500
typedef asio::error_code error_code;
// hidden
inline asio::error::error_category get_posix_category()
{ return asio::error::system_category; }
// hidden
inline asio::error::error_category get_system_category()
{ return asio::error::system_category; }
// hidden
boost::system::error_category const& get_libtorrent_category()
{
static ::asio::error::error_category libtorrent_category(20);
return libtorrent_category;
}
// hidden
boost::system::error_category const& get_http_category()
{
static ::asio::error::error_category http_category(21);
return http_category;
}
#else
// return the instance of the libtorrent_error_category which
// maps libtorrent error codes to human readable error messages.
TORRENT_EXPORT boost::system::error_category& get_libtorrent_category();
// returns the error_category for HTTP errors
TORRENT_EXPORT boost::system::error_category& get_http_category();
using boost::system::error_code;
// hidden
inline boost::system::error_category const& get_system_category()
#if BOOST_VERSION < 104400
{ return boost::system::get_system_category(); }
#else
{ return boost::system::system_category(); }
#endif
// hidden
inline boost::system::error_category const& get_posix_category()
#if BOOST_VERSION < 103600
{ return boost::system::get_posix_category(); }
#elif BOOST_VERSION < 104400
{ return boost::system::get_generic_category(); }
#else
{ return boost::system::generic_category(); }
#endif // BOOST_VERSION < 103600
#endif // BOOST_VERSION < 103500
// internal
inline boost::system::error_category const& generic_category()
{ return get_posix_category(); }
#ifndef BOOST_NO_EXCEPTIONS
struct TORRENT_EXPORT libtorrent_exception: std::exception
{
libtorrent_exception(error_code const& s): m_error(s), m_msg(0) {}
virtual const char* what() const throw();
virtual ~libtorrent_exception() throw();
error_code error() const { return m_error; }
private:
error_code m_error;
mutable char* m_msg;
};
#endif
}
#if BOOST_VERSION >= 103500
namespace boost { namespace system {
template<> struct is_error_code_enum<libtorrent::errors::error_code_enum>
{ static const bool value = true; };
template<> struct is_error_condition_enum<libtorrent::errors::error_code_enum>
{ static const bool value = true; };
template<> struct is_error_code_enum<libtorrent::errors::http_errors>
{ static const bool value = true; };
template<> struct is_error_condition_enum<libtorrent::errors::http_errors>
{ static const bool value = true; };
} }
#endif // BOOST_VERSION
#endif

View File

@@ -0,0 +1,111 @@
/*
Copyright (c) 2003-2014, 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_ESCAPE_STRING_HPP_INCLUDED
#define TORRENT_ESCAPE_STRING_HPP_INCLUDED
#include <string>
#include <boost/limits.hpp>
#include <boost/array.hpp>
#include "libtorrent/config.hpp"
#include "libtorrent/size_type.hpp"
#include "libtorrent/error_code.hpp"
namespace libtorrent
{
TORRENT_EXTRA_EXPORT boost::array<char, 4 + std::numeric_limits<size_type>::digits10> to_string(size_type n);
TORRENT_EXTRA_EXPORT std::string unescape_string(std::string const& s, error_code& ec);
// replaces all disallowed URL characters by their %-encoding
TORRENT_EXTRA_EXPORT std::string escape_string(const char* str, int len);
// same as escape_string but does not encode '/'
TORRENT_EXTRA_EXPORT std::string escape_path(const char* str, int len);
// if the url does not appear to be encoded, and it contains illegal url characters
// it will be encoded
TORRENT_EXTRA_EXPORT std::string maybe_url_encode(std::string const& url);
// returns true if the given string (not null terminated) contains
// characters that would need to be escaped if used in a URL
TORRENT_EXTRA_EXPORT bool need_encoding(char const* str, int len);
// encodes a string using the base64 scheme
TORRENT_EXTRA_EXPORT std::string base64encode(std::string const& s);
// encodes a string using the base32 scheme
TORRENT_EXTRA_EXPORT std::string base32encode(std::string const& s);
TORRENT_EXTRA_EXPORT std::string base32decode(std::string const& s);
TORRENT_EXTRA_EXPORT std::string url_has_argument(
std::string const& url, std::string argument, std::string::size_type* out_pos = 0);
// replaces \ with /
TORRENT_EXTRA_EXPORT void convert_path_to_posix(std::string& path);
TORRENT_EXTRA_EXPORT std::string read_until(char const*& str, char delim, char const* end);
TORRENT_EXTRA_EXPORT int hex_to_int(char in);
TORRENT_EXTRA_EXPORT bool is_hex(char const *in, int len);
// converts (binary) the string ``s`` to hexadecimal representation and
// returns it.
TORRENT_EXPORT std::string to_hex(std::string const& s);
// converts the binary buffer [``in``, ``in`` + len) to hexadecimal
// and prints it to the buffer ``out``. The caller is responsible for
// making sure the buffer pointed to by ``out`` is large enough,
// i.e. has at least len * 2 bytes of space.
TORRENT_EXPORT void to_hex(char const *in, int len, char* out);
// converts the buffer [``in``, ``in`` + len) from hexadecimal to
// binary. The binary output is written to the buffer pointed to
// by ``out``. The caller is responsible for making sure the buffer
// at ``out`` has enough space for the result to be written to, i.e.
// (len + 1) / 2 bytes.
TORRENT_EXPORT bool from_hex(char const *in, int len, char* out);
#if defined TORRENT_WINDOWS && TORRENT_USE_WSTRING
TORRENT_EXTRA_EXPORT std::wstring convert_to_wstring(std::string const& s);
TORRENT_EXTRA_EXPORT std::string convert_from_wstring(std::wstring const& s);
#endif
#if TORRENT_USE_ICONV || TORRENT_USE_LOCALE || defined TORRENT_WINDOWS
TORRENT_EXTRA_EXPORT std::string convert_to_native(std::string const& s);
TORRENT_EXTRA_EXPORT std::string convert_from_native(std::string const& s);
#else
// internal
inline std::string const& convert_to_native(std::string const& s) { return s; }
// internal
inline std::string const& convert_from_native(std::string const& s) { return s; }
#endif
}
#endif // TORRENT_ESCAPE_STRING_HPP_INCLUDED

View File

@@ -0,0 +1,89 @@
/*
Copyright (c) 2005-2014, 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_EXPORT_HPP_INCLUDED
#define TORRENT_EXPORT_HPP_INCLUDED
#if !defined(BOOST_COMPILER_CONFIG) && !defined(BOOST_NO_COMPILER_CONFIG)
# include <boost/config/select_compiler_config.hpp>
#endif
#ifdef BOOST_COMPILER_CONFIG
# include BOOST_COMPILER_CONFIG
#endif
#if !defined(BOOST_PLATFORM_CONFIG) && !defined(BOOST_NO_PLATFORM_CONFIG)
# include <boost/config/select_platform_config.hpp>
#endif
#ifdef BOOST_PLATFORM_CONFIG
# include BOOST_PLATFORM_CONFIG
#endif
// backwards compatibility with older versions of boost
#if !defined BOOST_SYMBOL_EXPORT && !defined BOOST_SYMBOL_IMPORT
# if defined _MSC_VER || defined __MINGW32__
# define BOOST_SYMBOL_EXPORT __declspec(dllexport)
# define BOOST_SYMBOL_IMPORT __declspec(dllimport)
# elif __GNU__ >= 4
# define BOOST_SYMBOL_EXPORT __attribute__((visibility("default")))
# define BOOST_SYMBOL_IMPORT __attribute__((visibility("default")))
# else
# define BOOST_SYMBOL_EXPORT
# define BOOST_SYMBOL_IMPORT
# endif
#endif
#if defined TORRENT_BUILDING_SHARED
# define TORRENT_EXPORT BOOST_SYMBOL_EXPORT
#elif defined TORRENT_LINKING_SHARED
# define TORRENT_EXPORT BOOST_SYMBOL_IMPORT
#endif
// when this is specified, export a bunch of extra
// symbols, mostly for the unit tests to reach
#if TORRENT_EXPORT_EXTRA
# if defined TORRENT_BUILDING_SHARED
# define TORRENT_EXTRA_EXPORT BOOST_SYMBOL_EXPORT
# elif defined TORRENT_LINKING_SHARED
# define TORRENT_EXTRA_EXPORT BOOST_SYMBOL_IMPORT
# endif
#endif
#ifndef TORRENT_EXPORT
# define TORRENT_EXPORT
#endif
#ifndef TORRENT_EXTRA_EXPORT
# define TORRENT_EXTRA_EXPORT
#endif
#endif

View File

@@ -0,0 +1,440 @@
/*
Copyright (c) 2006-2014, 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_EXTENSIONS_HPP_INCLUDED
#define TORRENT_EXTENSIONS_HPP_INCLUDED
// OVERVIEW
//
// libtorrent has a plugin 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.
//
// In short, the plugin interface makes it possible to:
//
// * register extension messages (sent in the extension handshake), see
// extensions_.
// * add data and parse data from the extension handshake.
// * send extension messages and standard bittorrent messages.
// * override or block the handling of standard bittorrent messages.
// * save and restore state via the session state
// * see all alerts that are posted
//
// .. _extensions: extension_protocol.html
//
// a word of caution
// -----------------
//
// Writing your own plugin is a very easy way to introduce serious bugs such as
// dead locks and race conditions. Since a plugin has access to internal
// structures it is also quite easy to sabotage libtorrent's operation.
//
// 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 plugin 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 plugin, to make
// sure it is not accessed at the same time from the libtorrent thread (through a
// callback). See `boost thread's mutex`_. 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 ``tick()``.
//
// Since the plugin 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.
//
// .. _`boost thread's mutex`: http://www.boost.org/doc/html/mutex.html
//
//
// plugin-interface
// ================
//
// The plugin interface consists of three base classes that the plugin may
// implement. These are called plugin, torrent_plugin and peer_plugin.
// They are found in the ``<libtorrent/extensions.hpp>`` header.
//
// These plugins are instantiated for each session, torrent and possibly each peer,
// respectively.
//
// For plugins that only need per torrent state, it is enough to only implement
// ``torrent_plugin`` and pass a constructor function or function object to
// ``session::add_extension()`` or ``torrent_handle::add_extension()`` (if the
// torrent has already been started and you want to hook in the extension at
// run-time).
//
// The signature of the function is::
//
// boost::shared_ptr<torrent_plugin> (*)(torrent*, void*);
//
// The first argument is the internal torrent object, the second argument
// is the userdata passed to ``session::add_torrent()`` or
// ``torrent_handle::add_extension()``.
//
// The function should return a ``boost::shared_ptr<torrent_plugin>`` 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
// ``torrent_plugin``), it will be associated with this torrent and callbacks
// will be made on torrent events.
//
// For more elaborate plugins which require session wide state, you would
// implement ``plugin``, construct an object (in a ``boost::shared_ptr``) and pass
// it in to ``session::add_extension()``.
//
// custom alerts
// =============
//
// Since plugins are running within internal libtorrent threads, one convenient
// way to communicate with the client is to post custom alerts.
//
// The expected interface of any alert, apart from deriving from the alert
// base class, looks like this:
//
// .. parsed-literal::
//
// const static int alert_type = *<unique alert ID>*;
// 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 = *<bitmask of alert::category_t flags>*;
// virtual int category() const { return static_category; }
//
// virtual char const* what() const { return *<string literal of the name of this alert>*; }
//
// The ``alert_type`` is used for the type-checking in ``alert_cast``. It must
// not collide with any other alert. The built-in alerts in libtorrent will
// not use alert type IDs greater than ``user_alert_id``. When defining your
// own alert, make sure it's greater than this constant.
//
// ``type()`` is the run-time equivalence of the ``alert_type``.
//
// The ``message()`` virtual function is expected to construct a useful
// string representation of the alert and the event or data it represents.
// Something convenient to put in a log file for instance.
//
// ``clone()`` is used internally to copy alerts. The suggested implementation
// of simply allocating a new instance as a copy of ``*this`` is all that's
// expected.
//
// The static category is required for checking wether or not the category
// for a specific alert is enabled or not, without instantiating the alert.
// The ``category`` virtual function is the run-time equivalence.
//
// The ``what()`` virtual function may simply be a string literal of the class
// name of your alert.
//
// For more information, see the `alert section`_.
//
// .. _`alert section`: reference-Alerts.html
#ifndef TORRENT_DISABLE_EXTENSIONS
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/weak_ptr.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include <vector>
#include "libtorrent/config.hpp"
#include "libtorrent/buffer.hpp"
#include "libtorrent/socket.hpp"
#include "libtorrent/error_code.hpp"
#include "libtorrent/policy.hpp" // for policy::peer
namespace libtorrent
{
namespace aux { struct session_impl; }
struct peer_plugin;
class bt_peer_connection;
struct peer_request;
class peer_connection;
class entry;
struct lazy_entry;
struct disk_buffer_holder;
struct bitfield;
class alert;
struct torrent_plugin;
class torrent;
struct torrent_peer;
// this is the base class for a session plugin. One primary feature
// is that it is notified of all torrents that are added to the session,
// and can add its own torrent_plugins.
struct TORRENT_EXPORT plugin
{
// hidden
virtual ~plugin() {}
// this is called by the session every time a new torrent is added.
// The ``torrent*`` points to the internal torrent object created
// for the new torrent. The ``void*`` is the userdata pointer as
// passed in via add_torrent_params.
//
// If the plugin returns a torrent_plugin instance, it will be added
// to the new torrent. Otherwise, return an empty shared_ptr to a
// torrent_plugin (the default).
virtual boost::shared_ptr<torrent_plugin> new_torrent(torrent*, void*)
{ return boost::shared_ptr<torrent_plugin>(); }
// called when plugin is added to a session
virtual void added(aux::session_impl*) {}
// called when an alert is posted
// alerts that are filtered are not
// posted
virtual void on_alert(alert const*) {}
// called once per second
virtual void on_tick() {}
// 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 plugin returns true then the ordering provided will be
// used and no other plugin will be allowed to change it.
virtual bool on_optimistic_unchoke(std::vector<policy::peer*>& /* peers */)
{ return false; }
// called when saving settings state
virtual void save_state(entry&) const {}
// called when loading settings state
virtual void load_state(lazy_entry const&) {}
};
// 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.
struct TORRENT_EXPORT torrent_plugin
{
// hidden
virtual ~torrent_plugin() {}
// 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
// ``shared_ptr`` (in which case you don't need to override this member
// function).
//
// If you need an extension to the peer connection (which most plugins do) you
// are supposed to return an instance of your peer_plugin class. Which in
// turn will have its hook functions called on event specific to that peer.
//
// The ``peer_connection`` will be valid as long as the ``shared_ptr`` is being
// held by the torrent object. So, it is generally a good idea to not keep a
// ``shared_ptr`` to your own peer_plugin. If you want to keep references to it,
// use ``weak_ptr``.
//
// If this function throws an exception, the connection will be closed.
virtual boost::shared_ptr<peer_plugin> new_connection(peer_connection*)
{ return boost::shared_ptr<peer_plugin>(); }
// These hooks are called when a piece passes the hash check or fails the hash
// check, respectively. The ``index`` is the piece index that was downloaded.
// It is possible to access the list of peers that participated in sending the
// piece through the ``torrent`` and the ``piece_picker``.
virtual void on_piece_pass(int /*index*/) {}
virtual void on_piece_failed(int /*index*/) {}
// 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.
virtual void tick() {}
// 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
// ``true`` indicates that it was handled, and no other plugin 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.
//
// Note that if you call ``pause()`` or ``resume()`` 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.
virtual bool on_pause() { return false; }
virtual bool on_resume() { return false; }
// 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.
//
// i.e. This function is always called when the torrent is in a state where it
// can start downloading.
virtual void on_files_checked() {}
// called when the torrent changes state
// the state is one of torrent_status::state_t
// enum members
virtual void on_state(int /*s*/) {}
enum flags_t {
// this is the first time we see this peer
first_time = 1,
// this peer was not added because it was
// filtered by the IP filter
filtered = 2
};
// called every time a new peer is added to the peer list.
// This is before the peer is connected to. For ``flags``, see
// torrent_plugin::flags_t. The ``source`` 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 peer_info::peer_source_flags.
virtual void on_add_peer(tcp::endpoint const&,
int /*src*/, int /*flags*/) {}
};
// peer plugins are associated with a specific peer. A peer could be
// both a regular bittorrent peer (``bt_peer_connection``) or one of the
// web seed connections (``web_peer_connection`` or ``http_seed_connection``).
// In order to only attach to certain peers, make your
// torrent_plugin::new_connection only return a plugin for certain peer
// connection types
struct TORRENT_EXPORT peer_plugin
{
// hidden
virtual ~peer_plugin() {}
// This function is expected to return the name of
// the plugin.
virtual char const* type() const { return ""; }
// can add entries to the extension handshake
// this is not called for web seeds
virtual void add_handshake(entry&) {}
// called when the peer is being disconnected.
virtual void on_disconnect(error_code const& /*ec*/) {}
// called when the peer is successfully connected. Note that
// incoming connections will have been connected by the time
// the peer plugin is attached to it, and won't have this hook
// called.
virtual void on_connected() {}
// throwing an exception from any of the handlers (except add_handshake)
// closes the connection
// 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
virtual bool on_handshake(char const* /*reserved_bits*/) { return true; }
// 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 peer_plugin
// being removed from the peer_connection and destructed.
// this is not called for web seeds
virtual bool on_extension_handshake(lazy_entry const&) { return true; }
// returning true from any of the message handlers
// indicates that the plugin has handeled the message.
// it will break the plugin chain traversing and not let
// anyone else handle the message, including the default
// handler.
virtual bool on_choke() { return false; }
virtual bool on_unchoke() { return false; }
virtual bool on_interested() { return false; }
virtual bool on_not_interested() { return false; }
virtual bool on_have(int /*index*/) { return false; }
virtual bool on_dont_have(int /*index*/) { return false; }
virtual bool on_bitfield(bitfield const& /*bitfield*/) { return false; }
virtual bool on_have_all() { return false; }
virtual bool on_have_none() { return false; }
virtual bool on_allowed_fast(int /*index*/) { return false; }
virtual bool on_request(peer_request const&) { return false; }
virtual bool on_piece(peer_request const& /*piece*/
, disk_buffer_holder& /*data*/) { return false; }
virtual bool on_cancel(peer_request const&) { return false; }
virtual bool on_reject(peer_request const&) { return false; }
virtual bool on_suggest(int /*index*/) { return false; }
// called after a choke message has been sent to the peer
virtual void sent_unchoke() {}
// called when libtorrent think this peer should be disconnected.
// if the plugin returns false, the peer will not be disconnected.
virtual bool can_disconnect(error_code const& /*ec*/) { return true; }
// called when an extended message is received. If returning true,
// the message is not processed by any other plugin and if false
// is returned the next plugin in the chain will receive it to
// be able to handle it. This is not called for web seeds.
// thus function may be called more than once per incoming message, but
// only the last of the calls will the ``body`` size equal the ``length``.
// i.e. Every time another fragment of the message is received, this
// function will be called, until finally the whole message has been
// received. The purpose of this is to allow early disconnects for invalid
// messages and for reporting progress of receiving large messages.
virtual bool on_extended(int /*length*/, int /*msg*/,
buffer::const_interval /*body*/)
{ return false; }
// this is not called for web seeds
virtual bool on_unknown_message(int /*length*/, int /*msg*/,
buffer::const_interval /*body*/)
{ return false; }
// called when a piece that this peer participated in either
// fails or passes the hash_check
virtual void on_piece_pass(int /*index*/) {}
virtual void on_piece_failed(int /*index*/) {}
// called aproximately once every second
virtual void tick() {}
// 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 plugin will have this function called.
virtual bool write_request(peer_request const&) { return false; }
};
}
#endif
#endif // TORRENT_EXTENSIONS_HPP_INCLUDED

View File

@@ -0,0 +1,60 @@
/*
Copyright (c) 2006, 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_LOGGER_HPP_INCLUDED
#define TORRENT_LOGGER_HPP_INCLUDED
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/shared_ptr.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/config.hpp"
#if TORRENT_USE_IOSTREAM
namespace libtorrent
{
struct torrent_plugin;
class torrent;
boost::shared_ptr<torrent_plugin> create_logger_plugin(torrent*);
}
#endif
#endif // TORRENT_LOGGER_HPP_INCLUDED

View File

@@ -0,0 +1,63 @@
/*
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.
*/
#ifndef TORRENT_LT_TRACKERS_HPP_INCLUDED
#define TORRENT_LT_TRACKERS_HPP_INCLUDED
#ifndef TORRENT_DISABLE_EXTENSIONS
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/shared_ptr.hpp>
#include "libtorrent/config.hpp"
#ifdef _MSC_VER
#pragma warning(pop)
#endif
namespace libtorrent
{
struct torrent_plugin;
class torrent;
// constructor function for the trackers exchange extension. This can
// either be passed in the add_torrent_params::extensions field, or
// via torrent_handle::add_extension().
boost::shared_ptr<torrent_plugin> TORRENT_EXPORT create_lt_trackers_plugin(torrent*, void*);
}
#endif // TORRENT_DISABLE_EXTENSIONS
#endif // TORRENT_LT_TRACKERS_HPP_INCLUDED

View File

@@ -0,0 +1,69 @@
/*
Copyright (c) 2006, 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_METADATA_TRANSFER_HPP_INCLUDED
#define TORRENT_METADATA_TRANSFER_HPP_INCLUDED
#ifndef TORRENT_DISABLE_EXTENSIONS
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/shared_ptr.hpp>
#include "libtorrent/config.hpp"
#ifdef _MSC_VER
#pragma warning(pop)
#endif
namespace libtorrent
{
struct torrent_plugin;
class torrent;
#ifndef TORRENT_NO_DEPRECATE
// constructor function for the metadata transfer extension. This
// extension has been superceded by the ut_metadata extension and
// is deprecated. It can be either be passed in the
// add_torrent_params::extensions field, or
// via torrent_handle::add_extension().
TORRENT_DEPRECATED_PREFIX
TORRENT_EXPORT boost::shared_ptr<torrent_plugin>
create_metadata_plugin(torrent*, void*) TORRENT_DEPRECATED;
#endif
}
#endif // TORRENT_DISABLE_EXTENSIONS
#endif // TORRENT_METADATA_TRANSFER_HPP_INCLUDED

View File

@@ -0,0 +1,66 @@
/*
Copyright (c) 2007, 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_SMART_BAN_HPP_INCLUDED
#define TORRENT_SMART_BAN_HPP_INCLUDED
#ifndef TORRENT_DISABLE_EXTENSIONS
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/shared_ptr.hpp>
#include "libtorrent/config.hpp"
#ifdef _MSC_VER
#pragma warning(pop)
#endif
namespace libtorrent
{
struct torrent_plugin;
class torrent;
// 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 torrent_handle::add_extension().
TORRENT_EXPORT boost::shared_ptr<torrent_plugin> create_smart_ban_plugin(torrent*, void*);
}
#endif // TORRENT_DISABLE_EXTENSIONS
#endif // TORRENT_SMART_BAN_HPP_INCLUDED

View File

@@ -0,0 +1,68 @@
/*
Copyright (c) 2007, 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_UT_METADATA_HPP_INCLUDED
#define TORRENT_UT_METADATA_HPP_INCLUDED
#ifndef TORRENT_DISABLE_EXTENSIONS
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/shared_ptr.hpp>
#include "libtorrent/config.hpp"
#ifdef _MSC_VER
#pragma warning(pop)
#endif
namespace libtorrent
{
struct torrent_plugin;
class torrent;
// 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 session constructor.
//
// This can either be passed in the add_torrent_params::extensions field, or
// via torrent_handle::add_extension().
TORRENT_EXPORT boost::shared_ptr<torrent_plugin> create_ut_metadata_plugin(torrent*, void*);
}
#endif // TORRENT_DISABLE_EXTENSIONS
#endif // TORRENT_UT_METADATA_HPP_INCLUDED

View File

@@ -0,0 +1,67 @@
/*
Copyright (c) 2006, MassaRoddel
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_UT_PEX_EXTENSION_HPP_INCLUDED
#define TORRENT_UT_PEX_EXTENSION_HPP_INCLUDED
#ifndef TORRENT_DISABLE_EXTENSIONS
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/shared_ptr.hpp>
#include "libtorrent/config.hpp"
#ifdef _MSC_VER
#pragma warning(pop)
#endif
namespace libtorrent
{
struct torrent_plugin;
class torrent;
// 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 session constructor.
//
// This can either be passed in the add_torrent_params::extensions field, or
// via torrent_handle::add_extension().
TORRENT_EXPORT boost::shared_ptr<torrent_plugin> create_ut_pex_plugin(torrent*, void*);
}
#endif // TORRENT_DISABLE_EXTENSIONS
#endif // TORRENT_UT_PEX_EXTENSION_HPP_INCLUDED

View File

@@ -0,0 +1,333 @@
/*
Copyright (c) 2003-2014, 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_FILE_HPP_INCLUDED
#define TORRENT_FILE_HPP_INCLUDED
#include <memory>
#include <string>
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/noncopyable.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/error_code.hpp"
#include "libtorrent/size_type.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/intrusive_ptr_base.hpp"
#ifdef TORRENT_WINDOWS
// windows part
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <winioctl.h>
#include <sys/types.h>
#else
// posix part
#define _FILE_OFFSET_BITS 64
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 600
#endif
#include <unistd.h>
#include <sys/uio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <dirent.h> // for DIR
#undef _FILE_OFFSET_BITS
#endif
namespace libtorrent
{
struct file_status
{
size_type file_size;
boost::uint64_t atime;
boost::uint64_t mtime;
boost::uint64_t ctime;
enum {
#if defined TORRENT_WINDOWS
fifo = 0x1000, // named pipe (fifo)
character_special = 0x2000, // character special
directory = 0x4000, // directory
regular_file = 0x8000 // regular
#else
fifo = 0010000, // named pipe (fifo)
character_special = 0020000, // character special
directory = 0040000, // directory
block_special = 0060000, // block special
regular_file = 0100000, // regular
link = 0120000, // symbolic link
socket = 0140000 // socket
#endif
} modes_t;
int mode;
};
// internal flags for stat_file
enum { dont_follow_links = 1 };
TORRENT_EXTRA_EXPORT void stat_file(std::string f, file_status* s
, error_code& ec, int flags = 0);
TORRENT_EXTRA_EXPORT void rename(std::string const& f
, std::string const& newf, error_code& ec);
TORRENT_EXTRA_EXPORT void create_directories(std::string const& f
, error_code& ec);
TORRENT_EXTRA_EXPORT void create_directory(std::string const& f
, error_code& ec);
TORRENT_EXTRA_EXPORT void remove_all(std::string const& f
, error_code& ec);
TORRENT_EXTRA_EXPORT void remove(std::string const& f, error_code& ec);
TORRENT_EXTRA_EXPORT bool exists(std::string const& f);
TORRENT_EXTRA_EXPORT size_type file_size(std::string const& f);
TORRENT_EXTRA_EXPORT bool is_directory(std::string const& f
, error_code& ec);
TORRENT_EXTRA_EXPORT void recursive_copy(std::string const& old_path
, std::string const& new_path, error_code& ec);
TORRENT_EXTRA_EXPORT void copy_file(std::string const& f
, std::string const& newf, error_code& ec);
TORRENT_EXTRA_EXPORT std::string split_path(std::string const& f);
TORRENT_EXTRA_EXPORT char const* next_path_element(char const* p);
TORRENT_EXTRA_EXPORT std::string extension(std::string const& f);
TORRENT_EXTRA_EXPORT std::string remove_extension(std::string const& f);
TORRENT_EXTRA_EXPORT void replace_extension(std::string& f, std::string const& ext);
TORRENT_EXTRA_EXPORT bool is_root_path(std::string const& f);
// internal used by create_torrent.hpp
TORRENT_EXPORT std::string parent_path(std::string const& f);
TORRENT_EXTRA_EXPORT bool has_parent_path(std::string const& f);
// internal used by create_torrent.hpp
TORRENT_EXPORT std::string filename(std::string const& f);
TORRENT_EXTRA_EXPORT std::string combine_path(std::string const& lhs
, std::string const& rhs);
// internal used by create_torrent.hpp
TORRENT_EXPORT std::string complete(std::string const& f);
TORRENT_EXTRA_EXPORT bool is_complete(std::string const& f);
TORRENT_EXTRA_EXPORT std::string current_working_directory();
#if TORRENT_USE_UNC_PATHS
TORRENT_EXTRA_EXPORT std::string canonicalize_path(std::string const& f);
#endif
class TORRENT_EXTRA_EXPORT directory : public boost::noncopyable
{
public:
directory(std::string const& path, error_code& ec);
~directory();
void next(error_code& ec);
std::string file() const;
boost::uint64_t inode() const;
bool done() const { return m_done; }
private:
#ifdef TORRENT_WINDOWS
HANDLE m_handle;
int m_inode;
#if TORRENT_USE_WSTRING
WIN32_FIND_DATAW m_fd;
#else
WIN32_FIND_DATAA m_fd;
#endif
#else
DIR* m_handle;
// the dirent struct contains a zero-sized
// array at the end, it will end up referring
// to the m_name field
struct dirent m_dirent;
char m_name[TORRENT_MAX_PATH + 1]; // +1 to make room for null
#endif
bool m_done;
};
struct TORRENT_EXTRA_EXPORT file: boost::noncopyable, intrusive_ptr_base<file>
{
// the open mode for files. Used for the file constructor or
// file::open().
enum open_mode_t
{
// open the file for reading only
read_only = 0,
// open the file for writing only
write_only = 1,
// open the file for reading and writing
read_write = 2,
// the mask for the bits determining read or write mode
rw_mask = read_only | write_only | read_write,
// indicate that the file should be opened in
// *direct io* mode, i.e. bypassing the operating
// system's disk cache, or as much as possible of it
// depending on the system.
// when a file is opened with no_buffer,
// file offsets have to be aligned to
// pos_alignment() and buffer addresses
// to buf_alignment() and read/write sizes
// to size_alignment()
no_buffer = 4,
// open the file in sparse mode (if supported by the
// filesystem).
sparse = 8,
// don't update the access timestamps on the file (if
// supported by the operating system and filesystem).
// this generally improves disk performance.
no_atime = 16,
// open the file for random acces. This disables read-ahead
// logic
random_access = 32,
// prevent the file from being opened by another process
// while it's still being held open by this handle
lock_file = 64,
// when creating a file, set the hidden attribute (windows only)
attribute_hidden = 0x1000,
// when creating a file, set the executable attribute
attribute_executable = 0x2000,
// the mask of all attribute bits
attribute_mask = attribute_hidden | attribute_executable
};
#ifdef TORRENT_WINDOWS
struct iovec_t
{
void* iov_base;
size_t iov_len;
};
#else
typedef iovec iovec_t;
#endif
// use a typedef for the type of iovec_t::iov_base
// since it may differ
#ifdef TORRENT_SOLARIS
typedef char* iovec_base_t;
#else
typedef void* iovec_base_t;
#endif
file();
file(std::string const& p, int m, error_code& ec);
~file();
bool open(std::string const& p, int m, error_code& ec);
bool is_open() const;
void close();
bool set_size(size_type size, error_code& ec);
int open_mode() const { return m_open_mode; }
// when opened in unbuffered mode, this is the
// required alignment of file_offsets. i.e.
// any (file_offset & (pos_alignment()-1)) == 0
// is a precondition to read and write operations
int pos_alignment() const;
// when opened in unbuffered mode, this is the
// required alignment of buffer addresses
int buf_alignment() const;
// read/write buffer sizes needs to be aligned to
// this when in unbuffered mode
int size_alignment() const;
size_type writev(size_type file_offset, iovec_t const* bufs, int num_bufs, error_code& ec);
size_type readv(size_type file_offset, iovec_t const* bufs, int num_bufs, error_code& ec);
void hint_read(size_type file_offset, int len);
size_type get_size(error_code& ec) const;
// return the offset of the first byte that
// belongs to a data-region
size_type sparse_end(size_type start) const;
size_type phys_offset(size_type offset);
#ifdef TORRENT_WINDOWS
HANDLE native_handle() const { return m_file_handle; }
#else
int native_handle() const { return m_fd; }
#endif
private:
#ifdef TORRENT_WINDOWS
HANDLE m_file_handle;
#if TORRENT_USE_WSTRING
std::wstring m_path;
#else
std::string m_path;
#endif // TORRENT_USE_WSTRING
#else // TORRENT_WINDOWS
int m_fd;
#endif // TORRENT_WINDOWS
#if defined TORRENT_WINDOWS || defined TORRENT_LINUX || defined TORRENT_DEBUG
static void init_file();
static int m_page_size;
#endif
int m_open_mode;
#if defined TORRENT_WINDOWS || defined TORRENT_LINUX
mutable int m_sector_size;
#endif
#if defined TORRENT_WINDOWS
mutable int m_cluster_size;
static bool has_manage_volume_privs;
#endif
};
}
#endif // TORRENT_FILE_HPP_INCLUDED

View File

@@ -0,0 +1,123 @@
/*
Copyright (c) 2006-2014, 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_FILE_POOL_HPP
#define TORRENT_FILE_POOL_HPP
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/intrusive_ptr.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include <map>
#include "libtorrent/file.hpp"
#include "libtorrent/ptime.hpp"
#include "libtorrent/thread.hpp"
#include "libtorrent/file_storage.hpp"
namespace libtorrent
{
// this is an internal cache of open file handles. It's primarily used by
// storage_interface 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.
struct TORRENT_EXPORT file_pool : boost::noncopyable
{
// ``size`` specifies the number of allowed files handles
// to hold open at any given time.
file_pool(int size = 40);
~file_pool();
// return an open file handle to file at ``file_index`` in the
// file_storage ``fs`` opened at save path ``p``. ``m`` is the
// file open mode (see file::open_mode_t).
boost::intrusive_ptr<file> open_file(void* st, std::string const& p
, int file_index, file_storage const& fs, int m, error_code& ec);
// release all files belonging to the specified storage_interface (``st``)
// the overload that takes ``file_index`` releases only the file with
// that index in storage ``st``.
void release(void* st);
void release(void* st, int file_index);
// update the allowed number of open file handles to ``size``.
void resize(int size);
// returns the current limit of number of allowed open file handles held
// by the file_pool.
int size_limit() const { return m_size; }
// internal
void set_low_prio_io(bool b) { m_low_prio_io = b; }
private:
void remove_oldest();
int m_size;
bool m_low_prio_io;
struct lru_file_entry
{
lru_file_entry(): key(0), last_use(time_now()), mode(0) {}
mutable boost::intrusive_ptr<file> file_ptr;
void* key;
ptime last_use;
int mode;
};
// maps storage pointer, file index pairs to the
// lru entry for the file
typedef std::map<std::pair<void*, int>, lru_file_entry> file_set;
file_set m_files;
mutex m_mutex;
#if TORRENT_CLOSE_MAY_BLOCK
void closer_thread_fun();
mutex m_closer_mutex;
std::vector<boost::intrusive_ptr<file> > m_queued_for_close;
bool m_stop_thread;
// used to close files
thread m_closer_thread;
#endif
};
}
#endif

View File

@@ -0,0 +1,586 @@
/*
Copyright (c) 2003-2014, 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_FILE_STORAGE_HPP_INCLUDED
#define TORRENT_FILE_STORAGE_HPP_INCLUDED
#include <string>
#include <vector>
#include <ctime>
#include "libtorrent/size_type.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/peer_request.hpp"
#include "libtorrent/peer_id.hpp"
namespace libtorrent
{
struct file;
// information about a file in a file_storage
struct TORRENT_EXPORT file_entry
{
// hidden
file_entry();
// hidden
~file_entry();
// the full path of this file. The paths are unicode strings
// encoded in UTF-8.
std::string path;
// the path which this is a symlink to, or empty if this is
// not a symlink. This field is only used if the ``symlink_attribute`` is set.
std::string symlink_path;
// the offset of this file inside the torrent
size_type offset;
// the size of the file (in bytes) and ``offset`` 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.
size_type size;
// 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 ``file_base`` 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.
size_type file_base;
// the modification time of this file specified in posix time.
std::time_t mtime;
// 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.
sha1_hash filehash;
// 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.
bool pad_file:1;
// true if the file was marked as hidden (on windows).
bool hidden_attribute:1;
// true if the file was marked as executable (posix)
bool executable_attribute:1;
// true if the file was a symlink. If this is the case
// the ``symlink_index`` refers to a string which specifies the original location
// where the data for this file was found.
bool symlink_attribute:1;
};
// only export this type if deprecated functions are enabled
#ifdef TORRENT_NO_DEPRECATE
#define TORRENT_DEPRECATED_EXPORT
#else
#define TORRENT_DEPRECATED_EXPORT TORRENT_EXPORT
#endif
// internal
struct TORRENT_DEPRECATED_EXPORT internal_file_entry
{
friend class file_storage;
#ifdef TORRENT_DEBUG
// for torrent_info::invariant_check
friend class torrent_info;
#endif
internal_file_entry()
: offset(0)
, symlink_index(not_a_symlink)
, no_root_dir(false)
, size(0)
, name_len(name_is_owned)
, pad_file(false)
, hidden_attribute(false)
, executable_attribute(false)
, symlink_attribute(false)
, name(NULL)
, path_index(-1)
{}
internal_file_entry(file_entry const& e)
: offset(e.offset)
, symlink_index(not_a_symlink)
, no_root_dir(false)
, size(e.size)
, name_len(name_is_owned)
, pad_file(e.pad_file)
, hidden_attribute(e.hidden_attribute)
, executable_attribute(e.executable_attribute)
, symlink_attribute(e.symlink_attribute)
, name(NULL)
, path_index(-1)
{
set_name(e.path.c_str());
}
internal_file_entry(internal_file_entry const& fe);
internal_file_entry& operator=(internal_file_entry const& fe);
~internal_file_entry();
void set_name(char const* n, bool borrow_string = false, int string_len = 0);
std::string filename() const;
enum {
name_is_owned = (1<<12)-1,
not_a_symlink = (1<<15)-1
};
// the offset of this file inside the torrent
boost::uint64_t offset:48;
// index into file_storage::m_symlinks or not_a_symlink
// if this is not a symlink
boost::uint64_t symlink_index:15;
// if this is true, don't include m_name as part of the
// path to this file
boost::uint64_t no_root_dir:1;
// the size of this file
boost::uint64_t size:48;
// the number of characters in the name. If this is
// name_is_owned, name is null terminated and owned by this object
// (i.e. it should be freed in the destructor). If
// the len is not name_is_owned, the name pointer doesn not belong
// to this object, and it's not null terminated
boost::uint64_t name_len:12;
boost::uint64_t pad_file:1;
boost::uint64_t hidden_attribute:1;
boost::uint64_t executable_attribute:1;
boost::uint64_t symlink_attribute:1;
// make it available for logging
private:
// This string is not necessarily null terminated!
// that's why it's private, to keep people away from it
char const* name;
public:
// the index into file_storage::m_paths. To get
// the full path to this file, concatenate the path
// from that array with the 'name' field in
// this struct
// values for path_index include:
// -1 means no path (i.e. single file torrent)
// -2, it means the filename
// in this field contains the full, absolute path
// to the file
int path_index;
};
// represents a window of a file in a torrent.
//
// The ``file_index`` refers to the index of the file (in the torrent_info).
// To get the path and filename, use ``file_at()`` and give the ``file_index``
// as argument. The ``offset`` is the byte offset in the file where the range
// starts, and ``size`` is the number of bytes this range is. The size + offset
// will never be greater than the file size.
struct TORRENT_EXPORT file_slice
{
// the index of the file
int file_index;
// the offset from the start of the file, in bytes
size_type offset;
// the size of the window, in bytes
size_type size;
};
// The ``file_storage`` class represents a file list and the piece
// size. Everything necessary to interpret a regular bittorrent storage
// file structure.
class TORRENT_EXPORT file_storage
{
friend class torrent_info;
public:
// hidden
file_storage();
// hidden
~file_storage();
file_storage(file_storage const& f);
file_storage& operator=(file_storage const&);
// returns true if the piece length has been initialized
// on the file_storage. This is typically taken as a proxy
// of whether the file_storage as a whole is initialized or
// not.
bool is_valid() const { return m_piece_length > 0; }
// file attribute flags
enum flags_t
{
// 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.
pad_file = 1,
// this file has the hidden attribute set. This is primarily
// a windows attribute
attribute_hidden = 2,
// this file has the executable attribute set.
attribute_executable = 4,
// this file is a symbilic link. It should have a link
// target string associated with it.
attribute_symlink = 8
};
// allocates space for ``num_files`` 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.
void reserve(int num_files);
// Adds a file to the file storage. The ``flags`` argument sets
// attributes on the file. The file attributes is an extension and may
// not work in all bittorrent clients.
//
// For possible file attributes, see file_storage::flags_t.
//
// 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.
//
// 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 ``set_name``.
//
// The ``filehash`` argument is an optional pointer to a sha-1 hash (20
// bytes) of the file. The hash is not copied into the file_storage
// object, but the pointer is expected to point to memory that stays
// valid throughout the life time of the file_storage.
//
// Currently, the ``filehash`` from ``file_entry`` is not used.
void add_file(file_entry const& e, char const* filehash = 0);
void add_file(std::string const& p, size_type size, int flags = 0
, std::time_t mtime = 0, std::string const& s_p = "");
// renames the file at ``index`` to ``new_filename``. Keep in mind
// that filenames are expected to be UTF-8 encoded.
void rename_file(int index, std::string const& new_filename);
// 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 file_storage.
// it's an optimization used when loading .torrent files, to not
// duplicate names in memory.
void rename_file_borrow(int index, char const* new_filename, int len);
#if TORRENT_USE_WSTRING
// all wstring APIs are deprecated since 0.16.11
// instead, use the wchar -> utf8 conversion functions
// and pass in utf8 strings
#ifndef TORRENT_NO_DEPRECATE
TORRENT_DEPRECATED_PREFIX
void add_file(std::wstring const& p, size_type size, int flags = 0
, std::time_t mtime = 0, std::string const& s_p = "") TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX
void rename_file(int index, std::wstring const& new_filename) TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX
void set_name(std::wstring const& n) TORRENT_DEPRECATED;
void rename_file_deprecated(int index, std::wstring const& new_filename);
#endif // TORRENT_NO_DEPRECATE
#endif // TORRENT_USE_WSTRING
// returns a list of file_slice objects representing the portions of
// files the specified piece index, byte offset and size range overlaps.
// this is the inverse mapping of map_file().
std::vector<file_slice> map_block(int piece, size_type offset
, int size) const;
// returns a peer_request representing the piece index, byte offset
// and size the specified file range overlaps. This is the inverse
// mapping ove map_block(). Note that the ``peer_request`` return type
// is meant to hold bittorrent block requests, which may not be larger
// than 16 kiB. Mapping a range larger than that may return an overflown
// integer.
peer_request map_file(int file, size_type offset, int size) const;
#ifndef TORRENT_NO_DEPRECATE
// all functions depending on internal_file_entry
// were deprecated in 1.0. Use the variants that take an
// index instead
typedef std::vector<internal_file_entry>::const_iterator iterator;
typedef std::vector<internal_file_entry>::const_reverse_iterator reverse_iterator;
TORRENT_DEPRECATED_PREFIX
iterator file_at_offset(size_type offset) const TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX
iterator begin() const TORRENT_DEPRECATED { return m_files.begin(); }
TORRENT_DEPRECATED_PREFIX
iterator end() const TORRENT_DEPRECATED { return m_files.end(); }
TORRENT_DEPRECATED_PREFIX
reverse_iterator rbegin() const TORRENT_DEPRECATED { return m_files.rbegin(); }
TORRENT_DEPRECATED_PREFIX
reverse_iterator rend() const TORRENT_DEPRECATED { return m_files.rend(); }
TORRENT_DEPRECATED_PREFIX
internal_file_entry const& internal_at(int index) const TORRENT_DEPRECATED
{
TORRENT_ASSERT(index >= 0);
TORRENT_ASSERT(index < int(m_files.size()));
return m_files[index];
}
TORRENT_DEPRECATED_PREFIX
file_entry at(iterator i) const TORRENT_DEPRECATED;
iterator begin_deprecated() const { return m_files.begin(); }
iterator end_deprecated() const { return m_files.end(); }
reverse_iterator rbegin_deprecated() const { return m_files.rbegin(); }
reverse_iterator rend_deprecated() const { return m_files.rend(); }
iterator file_at_offset_deprecated(size_type offset) const;
#endif // TORRENT_NO_DEPRECATE
// returns the number of files in the file_storage
int num_files() const
{ return int(m_files.size()); }
// returns a file_entry with information about the file
// at ``index``. Index must be in the range [0, ``num_files()`` ).
file_entry at(int index) const;
// returns the total number of bytes all the files in this torrent spans
size_type total_size() const { return m_total_size; }
// set and get the number of pieces in the torrent
void set_num_pieces(int n) { m_num_pieces = n; }
int num_pieces() const { TORRENT_ASSERT(m_piece_length > 0); return m_num_pieces; }
// 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.
void set_piece_length(int l) { m_piece_length = l; }
int piece_length() const { TORRENT_ASSERT(m_piece_length > 0); return m_piece_length; }
// returns the piece size of ``index``. This will be the same as piece_length(), except
// for the last piece, which may be shorter.
int piece_size(int index) const;
// 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.
void set_name(std::string const& n) { m_name = n; }
const std::string& name() const { return m_name; }
// swap all content of *this* with *ti*.
void swap(file_storage& ti)
{
using std::swap;
swap(ti.m_files, m_files);
swap(ti.m_file_hashes, m_file_hashes);
swap(ti.m_symlinks, m_symlinks);
swap(ti.m_mtime, m_mtime);
swap(ti.m_file_base, m_file_base);
swap(ti.m_paths, m_paths);
swap(ti.m_name, m_name);
swap(ti.m_total_size, m_total_size);
swap(ti.m_num_pieces, m_num_pieces);
swap(ti.m_piece_length, m_piece_length);
}
// 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).
void optimize(int pad_file_limit = -1, int alignment = -1);
// These functions are used to query attributes of files at
// a given index.
//
// The ``hash()`` 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.
//
// The ``mtime()`` 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.
//
// ``file_path()`` returns the full path to a file.
//
// ``file_size()`` returns the size of a file.
//
// ``pad_file_at()`` returns true if the file at the given
// index is a pad-file.
//
// ``file_name()`` returns *just* the name of the file, whereas
// ``file_path()`` returns the path (inside the torrent file) with
// the filename appended.
//
// ``file_offset()`` 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).
sha1_hash hash(int index) const;
std::string const& symlink(int index) const;
time_t mtime(int index) const;
std::string file_path(int index, std::string const& save_path = "") const;
std::string file_name(int index) const;
size_type file_size(int index) const;
bool pad_file_at(int index) const;
size_type file_offset(int index) const;
// flags indicating various attributes for files in
// a file_storage.
enum file_flags_t
{
// 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.
flag_pad_file = 1,
// this file is hiddent (sets the hidden attribute
// on windows)
flag_hidden = 2,
// this file is executable (sets the executable bit
// on posix like systems)
flag_executable = 4,
// this file is a symlink. The symlink target is
// specified in a separate field
flag_symlink = 8
};
// returns a bitmask of flags from file_flags_t that apply
// to file at ``index``.
int file_flags(int index) const;
// 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.
// torrent_info::remap_files() can be used to use a new file layout.
size_type file_base(int index) const;
void set_file_base(int index, size_type off);
// returns the index of the file at the given offset in the torrent
int file_index_at_offset(size_type offset) const;
// low-level function. returns a pointer to the internal storage for
// the filename. This string may not be null terinated!
// the ``file_name_len()`` function returns the length of the filename.
char const* file_name_ptr(int index) const;
int file_name_len(int index) const;
#ifndef TORRENT_NO_DEPRECATE
// these were deprecated in 1.0. Use the versions that take an index instead
TORRENT_DEPRECATED_PREFIX
sha1_hash hash(internal_file_entry const& fe) const TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX
std::string const& symlink(internal_file_entry const& fe) const TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX
time_t mtime(internal_file_entry const& fe) const TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX
int file_index(internal_file_entry const& fe) const TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX
size_type file_base(internal_file_entry const& fe) const TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX
void set_file_base(internal_file_entry const& fe, size_type off) TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX
std::string file_path(internal_file_entry const& fe, std::string const& save_path = "") const TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX
std::string file_name(internal_file_entry const& fe) const TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX
size_type file_size(internal_file_entry const& fe) const TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX
bool pad_file_at(internal_file_entry const& fe) const TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX
size_type file_offset(internal_file_entry const& fe) const TORRENT_DEPRECATED;
#endif
private:
void update_path_index(internal_file_entry& e);
void reorder_file(int index, int dst);
// the list of files that this torrent consists of
std::vector<internal_file_entry> m_files;
// if there are sha1 hashes for each individual file
// there are as many entries in this array as the
// m_files array. Each entry in m_files has a corresponding
// hash pointer in this array. The reason to split it up
// in separate arrays is to save memory in case the torrent
// doesn't have file hashes
std::vector<char const*> m_file_hashes;
// for files that are symlinks, the symlink
// path_index in the internal_file_entry indexes
// this vector of strings
std::vector<std::string> m_symlinks;
// the modification times of each file. This vector
// is empty if no file have a modification time.
// each element corresponds to the file with the same
// index in m_files
std::vector<time_t> m_mtime;
// if any file has a non-zero file base (i.e. multiple
// files residing in the same physical file at different
// offsets)
std::vector<size_type> m_file_base;
// all unique paths files have. The internal_file_entry::path_index
// points into this array. The paths don't include the root directory
// name for multi-file torrents. The m_name field need to be
// prepended to these paths, and the filename of a specific file
// entry appended, to form full file paths
std::vector<std::string> m_paths;
// name of torrent. For multi-file torrents
// this is always the root directory
std::string m_name;
// the sum of all filesizes
size_type m_total_size;
// the number of pieces in the torrent
int m_num_pieces;
int m_piece_length;
};
}
#endif // TORRENT_FILE_STORAGE_HPP_INCLUDED

View File

@@ -0,0 +1,129 @@
/*
Copyright (c) 2003-2014, 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_FINGERPRINT_HPP_INCLUDED
#define TORRENT_FINGERPRINT_HPP_INCLUDED
#include <string>
#include <cstdio>
#include "libtorrent/config.hpp"
#include "libtorrent/peer_id.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent
{
// The fingerprint class represents information about a client and its version. It is used
// to encode this information into the client's peer id.
struct fingerprint
{
// The constructor takes a ``char const*`` that should point to a string constant containing
// exactly two characters. These are the characters that should be unique for your client. Make
// sure not to clash with anybody else. Here are some taken id's:
//
// +----------+-----------------------+
// | id chars | client |
// +==========+=======================+
// | 'AZ' | Azureus |
// +----------+-----------------------+
// | 'LT' | libtorrent (default) |
// +----------+-----------------------+
// | 'BX' | BittorrentX |
// +----------+-----------------------+
// | 'MT' | Moonlight Torrent |
// +----------+-----------------------+
// | 'TS' | Torrent Storm |
// +----------+-----------------------+
// | 'SS' | Swarm Scope |
// +----------+-----------------------+
// | 'XT' | Xan Torrent |
// +----------+-----------------------+
//
// There's an informal directory of client id's here_.
//
// .. _here: http://wiki.theory.org/BitTorrentSpecification#peer_id
//
// The ``major``, ``minor``, ``revision`` and ``tag`` parameters are used to identify the
// version of your client.
fingerprint(const char* id_string, int major, int minor, int revision, int tag)
: major_version(major)
, minor_version(minor)
, revision_version(revision)
, tag_version(tag)
{
TORRENT_ASSERT(id_string);
TORRENT_ASSERT(major >= 0);
TORRENT_ASSERT(minor >= 0);
TORRENT_ASSERT(revision >= 0);
TORRENT_ASSERT(tag >= 0);
TORRENT_ASSERT(std::strlen(id_string) == 2);
name[0] = id_string[0];
name[1] = id_string[1];
}
// generates the actual string put in the peer-id, and return it.
std::string to_string() const
{
char s[100];
snprintf(s, 100, "-%c%c%c%c%c%c-"
, name[0], name[1]
, version_to_char(major_version)
, version_to_char(minor_version)
, version_to_char(revision_version)
, version_to_char(tag_version));
return s;
}
char name[2];
int major_version;
int minor_version;
int revision_version;
int tag_version;
private:
char version_to_char(int v) const
{
if (v >= 0 && v < 10) return '0' + v;
else if (v >= 10) return 'A' + (v - 10);
TORRENT_ASSERT(false);
return '0';
}
};
}
#endif // TORRENT_FINGERPRINT_HPP_INCLUDED

View File

@@ -0,0 +1,133 @@
/*
Copyright (c) 2007-2014, 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_GZIP_HPP_INCLUDED
#define TORRENT_GZIP_HPP_INCLUDED
#include "libtorrent/config.hpp"
#include "libtorrent/error_code.hpp"
#include <vector>
namespace libtorrent
{
TORRENT_EXTRA_EXPORT void inflate_gzip(
char const* in, int size
, std::vector<char>& buffer
, int maximum_size
, error_code& error);
// get the ``error_category`` for zip errors
TORRENT_EXPORT boost::system::error_category& get_gzip_category();
namespace gzip_errors
{
// libtorrent uses boost.system's ``error_code`` class to represent errors. libtorrent has
// its own error category get_gzip_category() whith the error codes defined by error_code_enum.
enum error_code_enum
{
// Not an error
no_error = 0,
// the supplied gzip buffer has invalid header
invalid_gzip_header,
// the gzip buffer would inflate to more bytes than the specified
// maximum size, and was rejected.
inflated_data_too_large,
// available inflate data did not terminate
data_did_not_terminate,
// output space exhausted before completing inflate
space_exhausted,
// invalid block type (type == 3)
invalid_block_type,
// stored block length did not match one's complement
invalid_stored_block_length,
// dynamic block code description: too many length or distance codes
too_many_length_or_distance_codes,
// dynamic block code description: code lengths codes incomplete
code_lengths_codes_incomplete,
// dynamic block code description: repeat lengths with no first length
repeat_lengths_with_no_first_length,
// dynamic block code description: repeat more than specified lengths
repeat_more_than_specified_lengths,
// dynamic block code description: invalid literal/length code lengths
invalid_literal_length_code_lengths,
// dynamic block code description: invalid distance code lengths
invalid_distance_code_lengths,
// invalid literal/length or distance code in fixed or dynamic block
invalid_literal_code_in_block,
// distance is too far back in fixed or dynamic block
distance_too_far_back_in_block,
// an unknown error occurred during gzip inflation
unknown_gzip_error,
// the number of error codes
error_code_max
};
// hidden
TORRENT_EXPORT boost::system::error_code make_error_code(error_code_enum e);
}
}
#if BOOST_VERSION >= 103500
namespace boost { namespace system {
template<>
struct is_error_code_enum<libtorrent::gzip_errors::error_code_enum>
{ static const bool value = true; };
template<>
struct is_error_condition_enum<libtorrent::gzip_errors::error_code_enum>
{ static const bool value = true; };
} }
#endif // BOOST_VERSION
#endif

View File

@@ -0,0 +1,139 @@
/*
Copyright (c) 2003-2014, 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_HASHER_HPP_INCLUDED
#define TORRENT_HASHER_HPP_INCLUDED
#include <boost/cstdint.hpp>
#include "libtorrent/peer_id.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
#ifdef TORRENT_USE_GCRYPT
#include <gcrypt.h>
#elif TORRENT_USE_COMMONCRYPTO
#include <CommonCrypto/CommonDigest.h>
#elif defined TORRENT_USE_OPENSSL
extern "C"
{
#include <openssl/sha.h>
}
#else
// from sha1.cpp
namespace libtorrent
{
struct TORRENT_EXTRA_EXPORT sha_ctx
{
boost::uint32_t state[5];
boost::uint32_t count[2];
boost::uint8_t buffer[64];
};
TORRENT_EXTRA_EXPORT void SHA1_init(sha_ctx* context);
TORRENT_EXTRA_EXPORT void SHA1_update(sha_ctx* context, boost::uint8_t const* data, boost::uint32_t len);
TORRENT_EXTRA_EXPORT void SHA1_final(boost::uint8_t* digest, sha_ctx* context);
} // namespace libtorrent
#endif
namespace libtorrent
{
// this is a SHA-1 hash class.
//
// You use it by first instantiating it, then call ``update()`` to feed it
// with data. i.e. you don't have to keep the entire buffer of which you want to
// create the hash in memory. You can feed the hasher parts of it at a time. When
// You have fed the hasher with all the data, you call ``final()`` and it
// will return the sha1-hash of the data.
//
// The constructor that takes a ``char const*`` and an integer will construct the
// sha1 context and feed it the data passed in.
//
// If you want to reuse the hasher object once you have created a hash, you have to
// call ``reset()`` to reinitialize it.
//
// The sha1-algorithm used was implemented by Steve Reid and released as public domain.
// For more info, see ``src/sha1.cpp``.
class TORRENT_EXPORT hasher
{
public:
hasher();
// this is the same as default constructing followed by a call to
// ``update(data, len)``.
hasher(const char* data, int len);
#ifdef TORRENT_USE_GCRYPT
hasher(hasher const& h);
hasher& operator=(hasher const& h);
#endif
// append the following bytes to what is being hashed
hasher& update(std::string const& data) { update(data.c_str(), int(data.size())); return *this; }
hasher& update(const char* data, int len);
// returns the SHA-1 digest of the buffers previously passed to
// update() and the hasher constructor.
sha1_hash final();
// restore the hasher state to be as if the hasher has just been
// default constructed.
void reset();
#ifdef TORRENT_USE_GCRYPT
~hasher();
#endif
private:
#ifdef TORRENT_USE_GCRYPT
gcry_md_hd_t m_context;
#elif TORRENT_USE_COMMONCRYPTO
CC_SHA1_CTX m_context;
#elif defined TORRENT_USE_OPENSSL
SHA_CTX m_context;
#else
sha_ctx m_context;
#endif
};
}
#endif // TORRENT_HASHER_HPP_INCLUDED

View File

@@ -0,0 +1,225 @@
/*
Copyright (c) 2007-2014, 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_HTTP_CONNECTION
#define TORRENT_HTTP_CONNECTION
#include <boost/function/function1.hpp>
#include <boost/function/function2.hpp>
#include <boost/function/function5.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/noncopyable.hpp>
#include <vector>
#include <list>
#include <string>
#include "libtorrent/socket.hpp"
#include "libtorrent/error_code.hpp"
#include "libtorrent/http_parser.hpp"
#include "libtorrent/deadline_timer.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/socket_type.hpp"
#include "libtorrent/session_settings.hpp"
#include "libtorrent/i2p_stream.hpp"
#ifdef TORRENT_USE_OPENSSL
#include <boost/asio/ssl/context.hpp>
#endif
namespace libtorrent
{
struct http_connection;
class connection_queue;
const int default_max_bottled_buffer_size = 2*1024*1024;
typedef boost::function<void(error_code const&
, http_parser const&, char const* data, int size, http_connection&)> http_handler;
typedef boost::function<void(http_connection&)> http_connect_handler;
typedef boost::function<void(http_connection&, std::list<tcp::endpoint>&)> http_filter_handler;
// when bottled, the last two arguments to the handler
// will always be 0
struct TORRENT_EXTRA_EXPORT http_connection
: boost::enable_shared_from_this<http_connection>
, boost::noncopyable
{
http_connection(io_service& ios, connection_queue& cc
, http_handler const& handler, bool bottled = true
, int max_bottled_buffer_size = default_max_bottled_buffer_size
, http_connect_handler const& ch = http_connect_handler()
, http_filter_handler const& fh = http_filter_handler()
#ifdef TORRENT_USE_OPENSSL
, boost::asio::ssl::context* ssl_ctx = 0
#endif
);
~http_connection();
void rate_limit(int limit);
int rate_limit() const
{ return m_rate_limit; }
std::string sendbuffer;
void get(std::string const& url, time_duration timeout = seconds(30)
, int prio = 0, proxy_settings const* ps = 0, int handle_redirects = 5
, std::string const& user_agent = "", address const& bind_addr = address_v4::any()
#if TORRENT_USE_I2P
, i2p_connection* i2p_conn = 0
#endif
);
void start(std::string const& hostname, std::string const& port
, time_duration timeout, int prio = 0, proxy_settings const* ps = 0
, bool ssl = false, int handle_redirect = 5
, address const& bind_addr = address_v4::any()
#if TORRENT_USE_I2P
, i2p_connection* i2p_conn = 0
#endif
);
void close(bool force = false);
socket_type const& socket() const { return m_sock; }
std::list<tcp::endpoint> const& endpoints() const { return m_endpoints; }
private:
#if TORRENT_USE_I2P
void on_i2p_resolve(error_code const& e
, char const* destination);
#endif
void on_resolve(error_code const& e
, tcp::resolver::iterator i);
void queue_connect();
void connect(int ticket, tcp::endpoint target_address);
void on_connect_timeout();
void on_connect(error_code const& e);
void on_write(error_code const& e);
void on_read(error_code const& e, std::size_t bytes_transferred);
static void on_timeout(boost::weak_ptr<http_connection> p
, error_code const& e);
void on_assign_bandwidth(error_code const& e);
void callback(error_code e, char* data = 0, int size = 0);
std::vector<char> m_recvbuffer;
socket_type m_sock;
#if TORRENT_USE_I2P
i2p_connection* m_i2p_conn;
#endif
int m_read_pos;
tcp::resolver m_resolver;
http_parser m_parser;
http_handler m_handler;
http_connect_handler m_connect_handler;
http_filter_handler m_filter_handler;
deadline_timer m_timer;
time_duration m_read_timeout;
time_duration m_completion_timeout;
ptime m_last_receive;
ptime m_start_time;
// bottled means that the handler is called once, when
// everything is received (and buffered in memory).
// non bottled means that once the headers have been
// received, data is streamed to the handler
bool m_bottled;
// maximum size of bottled buffer
int m_max_bottled_buffer_size;
// set to true the first time the handler is called
bool m_called;
std::string m_hostname;
std::string m_port;
std::string m_url;
std::string m_user_agent;
std::list<tcp::endpoint> m_endpoints;
#ifdef TORRENT_USE_OPENSSL
asio::ssl::context* m_ssl_ctx;
bool m_own_ssl_context;
#endif
// the current download limit, in bytes per second
// 0 is unlimited.
int m_rate_limit;
// the number of bytes we are allowed to receive
int m_download_quota;
// only hand out new quota 4 times a second if the
// quota is 0. If it isn't 0 wait for it to reach
// 0 and continue to hand out quota at that time.
bool m_limiter_timer_active;
// the timer fires every 250 millisecond as long
// as all the quota was used.
deadline_timer m_limiter_timer;
// the number of redirects to follow (in sequence)
int m_redirects;
int m_connection_ticket;
connection_queue& m_cc;
// specifies whether or not the connection is
// configured to use a proxy
proxy_settings m_proxy;
// true if the connection is using ssl
bool m_ssl;
// the address to bind to. address_v4::any()
// means do not bind
address m_bind_addr;
// the priority we have in the connection queue.
// 0 is normal, 1 is high
int m_priority;
bool m_abort;
};
}
#endif

View File

@@ -0,0 +1,180 @@
/*
Copyright (c) 2008-2014, 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_HTTP_PARSER_HPP_INCLUDED
#define TORRENT_HTTP_PARSER_HPP_INCLUDED
#include <map>
#include <string>
#include <utility>
#include <vector>
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/cstdint.hpp>
#include <boost/tuple/tuple.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/config.hpp"
#include "libtorrent/buffer.hpp"
#include "libtorrent/size_type.hpp"
namespace libtorrent
{
// return true if the status code is 200, 206, or in the 300-400 range
bool is_ok_status(int http_status);
// return true if the status code is a redirect
bool is_redirect(int http_status);
TORRENT_EXTRA_EXPORT std::string resolve_redirect_location(std::string referrer
, std::string location);
class TORRENT_EXTRA_EXPORT http_parser
{
public:
enum flags_t { dont_parse_chunks = 1 };
http_parser(int flags = 0);
~http_parser();
std::string const& header(char const* key) const
{
static std::string empty;
std::multimap<std::string, std::string>::const_iterator i
= m_header.find(key);
if (i == m_header.end()) return empty;
return i->second;
}
std::string const& protocol() const { return m_protocol; }
int status_code() const { return m_status_code; }
std::string const& method() const { return m_method; }
std::string const& path() const { return m_path; }
std::string const& message() const { return m_server_message; }
buffer::const_interval get_body() const;
bool header_finished() const { return m_state == read_body; }
bool finished() const { return m_finished; }
boost::tuple<int, int> incoming(buffer::const_interval recv_buffer
, bool& error);
int body_start() const { return m_body_start_pos; }
size_type content_length() const { return m_content_length; }
std::pair<size_type, size_type> content_range() const
{ return std::make_pair(m_range_start, m_range_end); }
// returns true if this response is using chunked encoding.
// in this case the body is split up into chunks. You need
// to call parse_chunk_header() for each chunk, starting with
// the start of the body.
bool chunked_encoding() const { return m_chunked_encoding; }
// removes the chunk headers from the supplied buffer. The buffer
// must be the stream received from the http server this parser
// instanced parsed. It will use the internal chunk list to determine
// where the chunks are in the buffer. It returns the new length of
// the buffer
int collapse_chunk_headers(char* buffer, int size) const;
// returns false if the buffer doesn't contain a complete
// chunk header. In this case, call the function again with
// a bigger buffer once more bytes have been received.
// chunk_size is filled in with the number of bytes in the
// chunk that follows. 0 means the response terminated. In
// this case there might be additional headers in the parser
// object.
// header_size is filled in with the number of bytes the header
// itself was. Skip this number of bytes to get to the actual
// chunk data.
// if the function returns false, the chunk size and header
// size may still have been modified, but their values are
// undefined
bool parse_chunk_header(buffer::const_interval buf
, size_type* chunk_size, int* header_size);
// reset the whole state and start over
void reset();
bool connection_close() const { return m_connection_close; }
std::multimap<std::string, std::string> const& headers() const { return m_header; }
std::vector<std::pair<size_type, size_type> > const& chunks() const { return m_chunked_ranges; }
private:
size_type m_recv_pos;
int m_status_code;
std::string m_method;
std::string m_path;
std::string m_protocol;
std::string m_server_message;
size_type m_content_length;
size_type m_range_start;
size_type m_range_end;
enum { read_status, read_header, read_body, error_state } m_state;
std::multimap<std::string, std::string> m_header;
buffer::const_interval m_recv_buffer;
int m_body_start_pos;
// this is true if the server is HTTP/1.0 or
// if it sent "connection: close"
bool m_connection_close;
bool m_chunked_encoding;
bool m_finished;
// contains offsets of the first and one-past-end of
// each chunked range in the response
std::vector<std::pair<size_type, size_type> > m_chunked_ranges;
// while reading a chunk, this is the offset where the
// current chunk will end (it refers to the first character
// in the chunk tail header or the next chunk header)
size_type m_cur_chunk_end;
// the sum of all chunk headers read so far
int m_chunk_header_size;
int m_partial_chunk_header;
// controls some behaviors of the parser
int m_flags;
};
}
#endif // TORRENT_HTTP_PARSER_HPP_INCLUDED

View File

@@ -0,0 +1,137 @@
/*
Copyright (c) 2008-2014, 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_HTTP_SEED_CONNECTION_HPP_INCLUDED
#define TORRENT_HTTP_SEED_CONNECTION_HPP_INCLUDED
#include <ctime>
#include <algorithm>
#include <deque>
#include <string>
#include "libtorrent/debug.hpp"
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/smart_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/noncopyable.hpp>
#include <boost/array.hpp>
#include <boost/optional.hpp>
#include <boost/cstdint.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/config.hpp"
#include "libtorrent/web_connection_base.hpp"
#include "libtorrent/disk_buffer_holder.hpp"
#include "libtorrent/torrent.hpp"
#include "libtorrent/piece_block_progress.hpp"
#include "libtorrent/http_parser.hpp"
namespace libtorrent
{
class torrent;
struct peer_request;
namespace detail
{
struct session_impl;
}
class TORRENT_EXTRA_EXPORT http_seed_connection
: public web_connection_base
{
friend class invariant_access;
public:
// this is the constructor where the we are the active part.
// The peer_conenction should handshake and verify that the
// other end has the correct id
http_seed_connection(
aux::session_impl& ses
, boost::weak_ptr<torrent> t
, boost::shared_ptr<socket_type> s
, tcp::endpoint const& remote
, web_seed_entry& web);
virtual int type() const { return peer_connection::http_seed_connection; }
// called from the main loop when this connection has any
// work to do.
void on_receive(error_code const& error
, std::size_t bytes_transferred);
std::string const& url() const { return m_url; }
virtual void get_specific_peer_info(peer_info& p) const;
virtual void disconnect(error_code const& ec, int error = 0);
void write_request(peer_request const& r);
private:
// returns the block currently being
// downloaded. And the progress of that
// block. If the peer isn't downloading
// a piece for the moment, the boost::optional
// will be invalid.
boost::optional<piece_block_progress> downloading_piece_progress() const;
// this is const since it's used as a key in the web seed list in the torrent
// if it's changed referencing back into that list will fail
const std::string m_url;
// the number of bytes left to receive of the response we're
// currently parsing
size_type m_response_left;
// this is the offset inside the current receive
// buffer where the next chunk header will be.
// this is updated for each chunk header that's
// parsed. It does not necessarily point to a valid
// offset in the receive buffer, if we haven't received
// it yet. This offset never includes the HTTP header
size_type m_chunk_pos;
// this is the number of bytes we've already received
// from the next chunk header we're waiting for
int m_partial_chunk_header;
};
}
#endif // TORRENT_WEB_PEER_CONNECTION_HPP_INCLUDED

View File

@@ -0,0 +1,124 @@
/*
Copyright (c) 2007-2014, 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_HTTP_STREAM_HPP_INCLUDED
#define TORRENT_HTTP_STREAM_HPP_INCLUDED
#include <boost/function/function1.hpp>
#include "libtorrent/proxy_base.hpp"
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
namespace libtorrent {
class http_stream : public proxy_base
{
public:
explicit http_stream(io_service& io_service)
: proxy_base(io_service)
, m_no_connect(false)
{}
void set_no_connect(bool c) { m_no_connect = c; }
void set_username(std::string const& user
, std::string const& password)
{
m_user = user;
m_password = password;
}
void set_dst_name(std::string const& host)
{
m_dst_name = host;
}
void close(error_code& ec)
{
m_dst_name.clear();
proxy_base::close(ec);
}
#ifndef BOOST_NO_EXCEPTIONS
void close()
{
m_dst_name.clear();
proxy_base::close();
}
#endif
typedef boost::function<void(error_code const&)> handler_type;
template <class Handler>
void async_connect(endpoint_type const& endpoint, Handler const& handler)
{
m_remote_endpoint = endpoint;
// the connect is split up in the following steps:
// 1. resolve name of proxy server
// 2. connect to proxy server
// 3. send HTTP CONNECT method and possibly username+password
// 4. read CONNECT response
// to avoid unnecessary copying of the handler,
// store it in a shared_ptr
boost::shared_ptr<handler_type> h(new handler_type(handler));
tcp::resolver::query q(m_hostname, to_string(m_port).elems);
m_resolver.async_resolve(q, boost::bind(
&http_stream::name_lookup, this, _1, _2, h));
}
private:
void name_lookup(error_code const& e, tcp::resolver::iterator i
, boost::shared_ptr<handler_type> h);
void connected(error_code const& e, boost::shared_ptr<handler_type> h);
void handshake1(error_code const& e, boost::shared_ptr<handler_type> h);
void handshake2(error_code const& e, boost::shared_ptr<handler_type> h);
// send and receive buffer
std::vector<char> m_buffer;
// proxy authentication
std::string m_user;
std::string m_password;
std::string m_dst_name;
// this is true if the connection is HTTP based and
// want to talk directly to the proxy
bool m_no_connect;
};
}
#endif

View File

@@ -0,0 +1,117 @@
/*
Copyright (c) 2003-2014, 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_HTTP_TRACKER_CONNECTION_HPP_INCLUDED
#define TORRENT_HTTP_TRACKER_CONNECTION_HPP_INCLUDED
#include <string>
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/shared_ptr.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/config.hpp"
#include "libtorrent/lazy_entry.hpp"
#include "libtorrent/peer_id.hpp"
#include "libtorrent/tracker_manager.hpp"
#include "libtorrent/i2p_stream.hpp"
namespace libtorrent
{
struct http_connection;
class entry;
class http_parser;
class connection_queue;
struct session_settings;
namespace aux { struct session_impl; }
class TORRENT_EXTRA_EXPORT http_tracker_connection
: public tracker_connection
{
friend class tracker_manager;
public:
http_tracker_connection(
io_service& ios
, connection_queue& cc
, tracker_manager& man
, tracker_request const& req
, boost::weak_ptr<request_callback> c
, aux::session_impl const& ses
, proxy_settings const& ps
, std::string const& password = ""
#if TORRENT_USE_I2P
, i2p_connection* i2p_conn = 0
#endif
);
void start();
void close();
private:
boost::intrusive_ptr<http_tracker_connection> self()
{ return boost::intrusive_ptr<http_tracker_connection>(this); }
void on_filter(http_connection& c, std::list<tcp::endpoint>& endpoints);
void on_connect(http_connection& c);
void on_response(error_code const& ec, http_parser const& parser
, char const* data, int size);
virtual void on_timeout(error_code const& ec) {}
void parse(int status_code, lazy_entry const& e);
bool extract_peer_info(lazy_entry const& e, peer_entry& ret);
tracker_manager& m_man;
boost::shared_ptr<http_connection> m_tracker_connection;
aux::session_impl const& m_ses;
address m_tracker_ip;
proxy_settings const& m_ps;
connection_queue& m_cc;
io_service& m_ios;
#if TORRENT_USE_I2P
i2p_connection* m_i2p_conn;
#endif
};
}
#endif // TORRENT_HTTP_TRACKER_CONNECTION_HPP_INCLUDED

View File

@@ -0,0 +1,238 @@
/*
Copyright (c) 2009-2014, 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_I2P_STREAM_HPP_INCLUDED
#define TORRENT_I2P_STREAM_HPP_INCLUDED
#include "libtorrent/config.hpp"
#if TORRENT_USE_I2P
#include <list>
#include <string>
#include <vector>
#include <boost/function/function1.hpp>
#include <boost/function/function2.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include "libtorrent/proxy_base.hpp"
#include "libtorrent/session_settings.hpp"
namespace libtorrent {
namespace i2p_error {
// error values for the i2p_category error_category.
enum i2p_error_code
{
no_error = 0,
parse_failed,
cant_reach_peer,
i2p_error,
invalid_key,
invalid_id,
timeout,
key_not_found,
duplicated_id,
num_errors
};
// hidden
TORRENT_EXPORT boost::system::error_code make_error_code(i2p_error_code e);
}
// returns the error category for I2P errors
TORRENT_EXPORT boost::system::error_category& get_i2p_category();
class i2p_stream : public proxy_base
{
public:
explicit i2p_stream(io_service& io_service);
~i2p_stream();
enum command_t
{
cmd_none,
cmd_create_session,
cmd_connect,
cmd_accept,
cmd_name_lookup,
cmd_incoming
};
void set_command(command_t c) { m_command = c; }
void set_session_id(char const* id) { m_id = id; }
void set_destination(std::string const& d) { m_dest = d; }
std::string const& destination() { return m_dest; }
typedef boost::function<void(error_code const&)> handler_type;
template <class Handler>
void async_connect(endpoint_type const& endpoint, Handler const& handler)
{
// since we don't support regular endpoints, just ignore the one
// provided and use m_dest.
// the connect is split up in the following steps:
// 1. resolve name of proxy server
// 2. connect to SAM bridge
// 4 send command message (CONNECT/ACCEPT)
// to avoid unnecessary copying of the handler,
// store it in a shaed_ptr
boost::shared_ptr<handler_type> h(new handler_type(handler));
tcp::resolver::query q(m_hostname, to_string(m_port).elems);
m_resolver.async_resolve(q, boost::bind(
&i2p_stream::do_connect, this, _1, _2, h));
}
std::string name_lookup() const { return m_name_lookup; }
void set_name_lookup(char const* name) { m_name_lookup = name; }
void send_name_lookup(boost::shared_ptr<handler_type> h);
private:
bool handle_error(error_code const& e, boost::shared_ptr<handler_type> const& h);
void do_connect(error_code const& e, tcp::resolver::iterator i
, boost::shared_ptr<handler_type> h);
void connected(error_code const& e, boost::shared_ptr<handler_type> h);
void start_read_line(error_code const& e, boost::shared_ptr<handler_type> h);
void read_line(error_code const& e, boost::shared_ptr<handler_type> h);
void send_connect(boost::shared_ptr<handler_type> h);
void send_accept(boost::shared_ptr<handler_type> h);
void send_session_create(boost::shared_ptr<handler_type> h);
// send and receive buffer
std::vector<char> m_buffer;
char const* m_id;
int m_command; // 0 = connect, 1 = accept
std::string m_dest;
std::string m_name_lookup;
enum state_t
{
read_hello_response,
read_connect_response,
read_accept_response,
read_session_create_response,
read_name_lookup_response
};
int m_state;
#if TORRENT_USE_ASSERTS
int m_magic;
#endif
};
class i2p_connection
{
public:
i2p_connection(io_service& ios);
~i2p_connection();
proxy_settings const& proxy() const { return m_sam_router; }
bool is_open() const
{
return m_sam_socket
&& m_sam_socket->is_open()
&& m_state != sam_connecting;
}
void open(proxy_settings const& s, i2p_stream::handler_type const& h);
void close(error_code&);
char const* session_id() const { return m_session_id.c_str(); }
std::string const& local_endpoint() const { return m_i2p_local_endpoint; }
typedef boost::function<void(error_code const&, char const*)> name_lookup_handler;
void async_name_lookup(char const* name, name_lookup_handler handler);
private:
void on_sam_connect(error_code const& ec, i2p_stream::handler_type const& h
, boost::shared_ptr<i2p_stream>);
void do_name_lookup(std::string const& name
, name_lookup_handler const& h);
void on_name_lookup(error_code const& ec
, name_lookup_handler handler
, boost::shared_ptr<i2p_stream>);
void set_local_endpoint(error_code const& ec, char const* dest
, i2p_stream::handler_type const& h);
// to talk to i2p SAM bridge
boost::shared_ptr<i2p_stream> m_sam_socket;
proxy_settings m_sam_router;
// our i2p endpoint key
std::string m_i2p_local_endpoint;
std::string m_session_id;
std::list<std::pair<std::string, name_lookup_handler> > m_name_lookup;
enum state_t
{
sam_connecting,
sam_name_lookup,
sam_idle
};
state_t m_state;
io_service& m_io_service;
};
}
#if BOOST_VERSION >= 103500
namespace boost { namespace system {
template<>
struct is_error_code_enum<libtorrent::i2p_error::i2p_error_code>
{ static const bool value = true; };
template<>
struct is_error_condition_enum<libtorrent::i2p_error::i2p_error_code>
{ static const bool value = true; };
} }
#endif // BOOST_VERSION
#endif // TORRENT_USE_I2P
#endif

View File

@@ -0,0 +1,67 @@
/*
Copyright (c) 2003-2014, 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_IDENTIFY_CLIENT_HPP_INCLUDED
#define TORRENT_IDENTIFY_CLIENT_HPP_INCLUDED
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/optional.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/peer_id.hpp"
#include "libtorrent/fingerprint.hpp"
#include "libtorrent/config.hpp"
namespace libtorrent
{
// 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.
TORRENT_EXPORT std::string identify_client(const peer_id& 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.
TORRENT_EXPORT boost::optional<fingerprint> client_fingerprint(peer_id const& p);
}
#endif // TORRENT_IDENTIFY_CLIENT_HPP_INCLUDED

View File

@@ -0,0 +1,54 @@
/*
Copyright (c) 2007-2014, 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_INSTANTIATE_CONNECTION
#define TORRENT_INSTANTIATE_CONNECTION
#include "libtorrent/socket_type.hpp"
#include <boost/shared_ptr.hpp>
namespace libtorrent
{
struct proxy_settings;
struct utp_socket_manager;
struct socket_type;
// instantiate a socket_type (s) according to the specified criteria
TORRENT_EXTRA_EXPORT bool instantiate_connection(io_service& ios
, proxy_settings const& ps, socket_type& s
, void* ssl_context = 0
, utp_socket_manager* sm = 0
, bool peer_connection = false);
}
#endif

View File

@@ -0,0 +1,84 @@
/*
Copyright (c) 2007-2014, 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_INTRUSIVE_PTR_BASE
#define TORRENT_INTRUSIVE_PTR_BASE
#include <boost/detail/atomic_count.hpp>
#include <boost/checked_delete.hpp>
#include <boost/intrusive_ptr.hpp>
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent
{
template<class T>
struct intrusive_ptr_base
{
intrusive_ptr_base(intrusive_ptr_base<T> const&)
: m_refs(0) {}
friend void intrusive_ptr_add_ref(intrusive_ptr_base<T> const* s)
{
TORRENT_ASSERT(s != 0);
TORRENT_ASSERT(s->m_refs >= 0);
++s->m_refs;
}
friend void intrusive_ptr_release(intrusive_ptr_base<T> const* s)
{
TORRENT_ASSERT(s != 0);
TORRENT_ASSERT(s->m_refs > 0);
if (--s->m_refs == 0)
boost::checked_delete(static_cast<T const*>(s));
}
boost::intrusive_ptr<T> self()
{ return boost::intrusive_ptr<T>((T*)this); }
boost::intrusive_ptr<const T> self() const
{ return boost::intrusive_ptr<const T>((T const*)this); }
int refcount() const { return m_refs; }
intrusive_ptr_base(): m_refs(0) {}
private:
// reference counter for intrusive_ptr
mutable boost::detail::atomic_count m_refs;
};
}
#endif

View File

@@ -0,0 +1,81 @@
// Copyright Daniel Wallin 2004. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef TORRENT_INVARIANT_ACCESS_HPP_INCLUDED
#define TORRENT_INVARIANT_ACCESS_HPP_INCLUDED
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/config.hpp"
#if TORRENT_USE_INVARIANT_CHECKS
namespace libtorrent
{
class invariant_access
{
public:
template<class T>
static void check_invariant(T const& self)
{
self.check_invariant();
}
};
template<class T>
void check_invariant(T const& x)
{
invariant_access::check_invariant(x);
}
struct invariant_checker {};
template<class T>
struct invariant_checker_impl : invariant_checker
{
invariant_checker_impl(T const& self_)
: self(self_)
{
TORRENT_TRY
{
check_invariant(self);
}
TORRENT_CATCH_ALL
{
TORRENT_ASSERT(false);
}
}
~invariant_checker_impl()
{
TORRENT_TRY
{
check_invariant(self);
}
TORRENT_CATCH_ALL
{
TORRENT_ASSERT(false);
}
}
T const& self;
};
template<class T>
invariant_checker_impl<T> make_invariant_checker(T const& x)
{
return invariant_checker_impl<T>(x);
}
}
#define INVARIANT_CHECK \
invariant_checker const& _invariant_check = make_invariant_checker(*this); \
(void)_invariant_check; \
do {} while (false)
#else
#define INVARIANT_CHECK do {} while (false)
#endif
#endif // TORRENT_INVARIANT_ACCESS_HPP_INCLUDED

View File

@@ -0,0 +1,170 @@
/*
Copyright (c) 2003-2014, 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_IO_HPP_INCLUDED
#define TORRENT_IO_HPP_INCLUDED
#include <boost/cstdint.hpp>
#include <string>
#include <algorithm> // for copy
#include <cstring> // for memcpy
namespace libtorrent
{
namespace detail
{
template <class T> struct type {};
// reads an integer from a byte stream
// in big endian byte order and converts
// it to native endianess
template <class T, class InIt>
inline T read_impl(InIt& start, type<T>)
{
T ret = 0;
for (int i = 0; i < (int)sizeof(T); ++i)
{
ret <<= 8;
ret |= static_cast<boost::uint8_t>(*start);
++start;
}
return ret;
}
template <class InIt>
boost::uint8_t read_impl(InIt& start, type<boost::uint8_t>)
{
return static_cast<boost::uint8_t>(*start++);
}
template <class InIt>
boost::int8_t read_impl(InIt& start, type<boost::int8_t>)
{
return static_cast<boost::int8_t>(*start++);
}
template <class T, class OutIt>
inline void write_impl(T val, OutIt& start)
{
for (int i = (int)sizeof(T)-1; i >= 0; --i)
{
*start = static_cast<unsigned char>((val >> (i * 8)) & 0xff);
++start;
}
}
// -- adaptors
template <class InIt>
boost::int64_t read_int64(InIt& start)
{ return read_impl(start, type<boost::int64_t>()); }
template <class InIt>
boost::uint64_t read_uint64(InIt& start)
{ return read_impl(start, type<boost::uint64_t>()); }
template <class InIt>
boost::uint32_t read_uint32(InIt& start)
{ return read_impl(start, type<boost::uint32_t>()); }
template <class InIt>
boost::int32_t read_int32(InIt& start)
{ return read_impl(start, type<boost::int32_t>()); }
template <class InIt>
boost::int16_t read_int16(InIt& start)
{ return read_impl(start, type<boost::int16_t>()); }
template <class InIt>
boost::uint16_t read_uint16(InIt& start)
{ return read_impl(start, type<boost::uint16_t>()); }
template <class InIt>
boost::int8_t read_int8(InIt& start)
{ return read_impl(start, type<boost::int8_t>()); }
template <class InIt>
boost::uint8_t read_uint8(InIt& start)
{ return read_impl(start, type<boost::uint8_t>()); }
template <class OutIt>
void write_uint64(boost::uint64_t val, OutIt& start)
{ write_impl(val, start); }
template <class OutIt>
void write_int64(boost::int64_t val, OutIt& start)
{ write_impl(val, start); }
template <class OutIt>
void write_uint32(boost::uint32_t val, OutIt& start)
{ write_impl(val, start); }
template <class OutIt>
void write_int32(boost::int32_t val, OutIt& start)
{ write_impl(val, start); }
template <class OutIt>
void write_uint16(boost::uint16_t val, OutIt& start)
{ write_impl(val, start); }
template <class OutIt>
void write_int16(boost::int16_t val, OutIt& start)
{ write_impl(val, start); }
template <class OutIt>
void write_uint8(boost::uint8_t val, OutIt& start)
{ write_impl(val, start); }
template <class OutIt>
void write_int8(boost::int8_t val, OutIt& start)
{ write_impl(val, start); }
inline int write_string(std::string const& str, char*& start)
{
std::memcpy((void*)start, str.c_str(), str.size());
start += str.size();
return str.size();
}
template <class OutIt>
int write_string(std::string const& val, OutIt& out)
{
for (std::string::const_iterator i = val.begin()
, end(val.end()); i != end; ++i)
*out++ = *i;
return int(val.length());
}
}
}
#endif // TORRENT_IO_HPP_INCLUDED

View File

@@ -0,0 +1,77 @@
/*
Copyright (c) 2009-2014, 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_IO_SERVICE_HPP_INCLUDED
#define TORRENT_IO_SERVICE_HPP_INCLUDED
#ifdef __OBJC__
#define Protocol Protocol_
#endif
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/version.hpp>
#if defined TORRENT_WINDOWS || defined TORRENT_CYGWIN
// asio assumes that the windows error codes are defined already
#include <winsock2.h>
#endif
#if BOOST_VERSION < 103500
#include <asio/io_service.hpp>
#else
#include <boost/asio/io_service.hpp>
#endif
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#ifdef __OBJC__
#undef Protocol
#endif
namespace libtorrent
{
#if BOOST_VERSION < 103500
typedef ::asio::io_service io_service;
#else
typedef boost::asio::io_service io_service;
#endif
}
#endif

View File

@@ -0,0 +1,77 @@
/*
Copyright (c) 2009-2014, 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_IO_SERVICE_FWD_HPP_INCLUDED
#define TORRENT_IO_SERVICE_FWD_HPP_INCLUDED
#ifdef __OBJC__
#define Protocol Protocol_
#endif
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/version.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#ifdef __OBJC__
#undef Protocol
#endif
#if BOOST_VERSION >= 103500
namespace boost {
#endif
namespace asio {
class io_service;
}
#if BOOST_VERSION >= 103500
}
#endif
namespace libtorrent
{
#if BOOST_VERSION < 103500
typedef ::asio::io_service io_service;
#else
typedef boost::asio::io_service io_service;
#endif
}
#endif

View File

@@ -0,0 +1,362 @@
/*
Copyright (c) 2005-2014, 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_IP_FILTER_HPP
#define TORRENT_IP_FILTER_HPP
#include <set>
#include <vector>
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/limits.hpp>
#include <boost/utility.hpp>
#include <boost/tuple/tuple.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/config.hpp"
#include "libtorrent/address.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent
{
// hidden
inline bool operator<=(address const& lhs
, address const& rhs)
{
return lhs < rhs || lhs == rhs;
}
template <class Addr>
struct ip_range
{
Addr first;
Addr last;
int flags;
};
namespace detail
{
template<class Addr>
Addr zero()
{
Addr zero;
std::fill(zero.begin(), zero.end(), 0);
return zero;
}
template<>
inline boost::uint16_t zero<boost::uint16_t>() { return 0; }
template<class Addr>
Addr plus_one(Addr const& a)
{
Addr tmp(a);
for (int i = int(tmp.size()) - 1; i >= 0; --i)
{
if (tmp[i] < (std::numeric_limits<typename Addr::value_type>::max)())
{
tmp[i] += 1;
break;
}
tmp[i] = 0;
}
return tmp;
}
inline boost::uint16_t plus_one(boost::uint16_t val) { return val + 1; }
template<class Addr>
Addr minus_one(Addr const& a)
{
Addr tmp(a);
for (int i = int(tmp.size()) - 1; i >= 0; --i)
{
if (tmp[i] > 0)
{
tmp[i] -= 1;
break;
}
tmp[i] = (std::numeric_limits<typename Addr::value_type>::max)();
}
return tmp;
}
inline boost::uint16_t minus_one(boost::uint16_t val) { return val - 1; }
template<class Addr>
Addr max_addr()
{
Addr tmp;
std::fill(tmp.begin(), tmp.end()
, (std::numeric_limits<typename Addr::value_type>::max)());
return Addr(tmp);
}
template<>
inline boost::uint16_t max_addr<boost::uint16_t>()
{ return (std::numeric_limits<boost::uint16_t>::max)(); }
// this is the generic implementation of
// a filter for a specific address type.
// it works with IPv4 and IPv6
template<class Addr>
class filter_impl
{
public:
filter_impl()
{
// make the entire ip-range non-blocked
m_access_list.insert(range(zero<Addr>(), 0));
}
void add_rule(Addr first, Addr last, int flags)
{
TORRENT_ASSERT(!m_access_list.empty());
TORRENT_ASSERT(first < last || first == last);
typename range_t::iterator i = m_access_list.upper_bound(first);
typename range_t::iterator j = m_access_list.upper_bound(last);
if (i != m_access_list.begin()) --i;
TORRENT_ASSERT(j != m_access_list.begin());
TORRENT_ASSERT(j != i);
int first_access = i->access;
int last_access = boost::prior(j)->access;
if (i->start != first && first_access != flags)
{
i = m_access_list.insert(i, range(first, flags));
}
else if (i != m_access_list.begin() && boost::prior(i)->access == flags)
{
--i;
first_access = i->access;
}
TORRENT_ASSERT(!m_access_list.empty());
TORRENT_ASSERT(i != m_access_list.end());
if (i != j) m_access_list.erase(boost::next(i), j);
if (i->start == first)
{
// we can do this const-cast because we know that the new
// start address will keep the set correctly ordered
const_cast<Addr&>(i->start) = first;
const_cast<int&>(i->access) = flags;
}
else if (first_access != flags)
{
m_access_list.insert(i, range(first, flags));
}
if ((j != m_access_list.end()
&& minus_one(j->start) != last)
|| (j == m_access_list.end()
&& last != max_addr<Addr>()))
{
TORRENT_ASSERT(j == m_access_list.end() || last < minus_one(j->start));
if (last_access != flags)
j = m_access_list.insert(j, range(plus_one(last), last_access));
}
if (j != m_access_list.end() && j->access == flags) m_access_list.erase(j);
TORRENT_ASSERT(!m_access_list.empty());
}
int access(Addr const& addr) const
{
TORRENT_ASSERT(!m_access_list.empty());
typename range_t::const_iterator i = m_access_list.upper_bound(addr);
if (i != m_access_list.begin()) --i;
TORRENT_ASSERT(i != m_access_list.end());
TORRENT_ASSERT(i->start <= addr && (boost::next(i) == m_access_list.end()
|| addr < boost::next(i)->start));
return i->access;
}
template <class ExternalAddressType>
std::vector<ip_range<ExternalAddressType> > export_filter() const
{
std::vector<ip_range<ExternalAddressType> > ret;
ret.reserve(m_access_list.size());
for (typename range_t::const_iterator i = m_access_list.begin()
, end(m_access_list.end()); i != end;)
{
ip_range<ExternalAddressType> r;
r.first = ExternalAddressType(i->start);
r.flags = i->access;
++i;
if (i == end)
r.last = ExternalAddressType(max_addr<Addr>());
else
r.last = ExternalAddressType(minus_one(i->start));
ret.push_back(r);
}
return ret;
}
private:
struct range
{
range(Addr addr, int a = 0): start(addr), access(a) {}
bool operator<(range const& r) const
{ return start < r.start; }
bool operator<(Addr const& a) const
{ return start < a; }
Addr start;
// the end of the range is implicit
// and given by the next entry in the set
int access;
};
typedef std::set<range> range_t;
range_t m_access_list;
};
}
// The ``ip_filter`` 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).
//
// A default constructed ip_filter does not filter any address.
struct TORRENT_EXPORT ip_filter
{
// the flags defined for an IP range
enum access_flags
{
// indicates that IPs in this range should not be connected
// to nor accepted as incoming connections
blocked = 1
};
// Adds a rule to the filter. ``first`` and ``last`` defines a range of
// ip addresses that will be marked with the given flags. The ``flags``
// can currently be 0, which means allowed, or ``ip_filter::blocked``, which
// means disallowed.
//
// precondition:
// ``first.is_v4() == last.is_v4() && first.is_v6() == last.is_v6()``
//
// postcondition:
// ``access(x) == flags`` for every ``x`` in the range [``first``, ``last``]
//
// This means that in a case of overlapping ranges, the last one applied takes
// precedence.
void add_rule(address first, address last, int flags);
// Returns the access permissions for the given address (``addr``). The permission
// can currently be 0 or ``ip_filter::blocked``. The complexity of this operation
// is O(``log`` n), where n is the minimum number of non-overlapping ranges to describe
// the current filter.
int access(address const& addr) const;
#if TORRENT_USE_IPV6
typedef boost::tuple<std::vector<ip_range<address_v4> >
, std::vector<ip_range<address_v6> > > filter_tuple_t;
#else
typedef std::vector<ip_range<address_v4> > filter_tuple_t;
#endif
// 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
// entry in the returned vector is a range with the access control specified in its
// ``flags`` field.
//
// The return value is a tuple containing two range-lists. One for IPv4 addresses
// and one for IPv6 addresses.
filter_tuple_t export_filter() const;
// void print() const;
private:
detail::filter_impl<address_v4::bytes_type> m_filter4;
#if TORRENT_USE_IPV6
detail::filter_impl<address_v6::bytes_type> m_filter6;
#endif
};
// 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.
class TORRENT_EXPORT port_filter
{
public:
// the defined flags for a port range
enum access_flags
{
// this flag indicates that destination ports in the
// range should not be connected to
blocked = 1
};
// set the flags for the specified port range (``first``, ``last``) to
// ``flags`` overwriting any existing rule for those ports. The range
// is inclusive, i.e. the port ``last`` also has the flag set on it.
void add_rule(boost::uint16_t first, boost::uint16_t last, int flags);
// test the specified port (``port``) for whether it is blocked
// or not. The returned value is the flags set for this port.
// see acces_flags.
int access(boost::uint16_t port) const;
private:
detail::filter_impl<boost::uint16_t> m_filter;
};
}
#endif

View File

@@ -0,0 +1,131 @@
/*
Copyright (c) 2013-2014, 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_IP_VOTER_HPP_INCLUDED
#define TORRENT_IP_VOTER_HPP_INCLUDED
#include <vector>
#include "libtorrent/address.hpp"
#include "libtorrent/bloom_filter.hpp"
#include "libtorrent/time.hpp" // for ptime
namespace libtorrent
{
// this is an object that keeps the state for a single external IP
// based on peoples votes
struct TORRENT_EXTRA_EXPORT ip_voter
{
ip_voter();
// returns true if a different IP is the top vote now
// i.e. we changed our idea of what our external IP is
bool cast_vote(address const& ip, int source_type, address const& sorce);
address external_address() const { return m_external_address; }
private:
bool maybe_rotate();
struct external_ip_t
{
external_ip_t(): sources(0), num_votes(0) {}
bool add_vote(sha1_hash const& k, int type);
// we want to sort decending
bool operator<(external_ip_t const& rhs) const
{
if (num_votes > rhs.num_votes) return true;
if (num_votes < rhs.num_votes) return false;
return sources > rhs.sources;
}
// this is a bloom filter of the IPs that have
// reported this address
bloom_filter<16> voters;
// this is the actual external address
address addr;
// a bitmask of sources the reporters have come from
boost::uint16_t sources;
// the total number of votes for this IP
boost::uint16_t num_votes;
};
// this is a bloom filter of all the IPs that have
// been the first to report an external address. Each
// IP only gets to add a new item once.
bloom_filter<32> m_external_address_voters;
std::vector<external_ip_t> m_external_addresses;
address m_external_address;
// the total number of unique IPs that have voted
int m_total_votes;
// this is true from the first time we rotate. Before
// we rotate for the first time, we keep updating the
// external address as we go, since we don't have any
// stable setting to fall back on. Once this is true,
// we stop updating it on the fly, and just use the
// address from when we rotated.
bool m_valid_external;
// the last time we rotated this ip_voter. i.e. threw
// away all the votes and started from scratch, in case
// our IP has changed
ptime m_last_rotate;
};
// this keeps track of multiple external IPs (for now, just IPv6 and IPv4, but
// it could be extended to deal with loopback and local network addresses as well)
struct TORRENT_EXTRA_EXPORT external_ip
{
// returns true if a different IP is the top vote now
// i.e. we changed our idea of what our external IP is
bool cast_vote(address const& ip, int source_type, address const& source);
// the external IP as it would be observed from `ip`
address external_address(address const& ip) const;
private:
// for now, assume one external IPv4 and one external IPv6 address
// 0 = IPv4 1 = IPv6
// TODO: 1 instead, have one instance per possible subnet, global IPv4, global IPv6, loopback, 192.168.x.x, 10.x.x.x, etc.
ip_voter m_vote_group[2];
};
}
#endif

View File

@@ -0,0 +1,48 @@
/*
Copyright (c) 2012-2014, 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 DHT_OBSERVER_HPP
#define DHT_OBSERVER_HPP
#include "libtorrent/address.hpp"
namespace libtorrent { namespace dht
{
struct dht_observer
{
virtual void set_external_address(address const& addr
, address const& source) = 0;
};
}}
#endif

View File

@@ -0,0 +1,191 @@
/*
Copyright (c) 2006-2014, 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_DISABLE_DHT
#ifndef TORRENT_DHT_TRACKER
#define TORRENT_DHT_TRACKER
#include <fstream>
#include <set>
#include <numeric>
#include <boost/bind.hpp>
#include <boost/ref.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/detail/atomic_count.hpp>
#include "libtorrent/kademlia/node.hpp"
#include "libtorrent/kademlia/node_id.hpp"
#include "libtorrent/kademlia/traversal_algorithm.hpp"
#include "libtorrent/session_settings.hpp"
#include "libtorrent/session_status.hpp"
#include "libtorrent/udp_socket.hpp"
#include "libtorrent/socket.hpp"
#include "libtorrent/thread.hpp"
#include "libtorrent/deadline_timer.hpp"
namespace libtorrent
{
namespace aux { struct session_impl; }
struct lazy_entry;
}
namespace libtorrent { namespace dht
{
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_DECLARE_LOG(dht_tracker);
#endif
struct dht_tracker;
TORRENT_EXTRA_EXPORT void intrusive_ptr_add_ref(dht_tracker const*);
TORRENT_EXTRA_EXPORT void intrusive_ptr_release(dht_tracker const*);
struct dht_tracker : udp_socket_interface, udp_socket_observer
{
friend void intrusive_ptr_add_ref(dht_tracker const*);
friend void intrusive_ptr_release(dht_tracker const*);
dht_tracker(libtorrent::aux::session_impl& ses, rate_limited_udp_socket& sock
, dht_settings const& settings, entry const* state = 0);
virtual ~dht_tracker();
void start(entry const& bootstrap
, find_data::nodes_callback const& f);
void stop();
void add_node(udp::endpoint node);
void add_node(std::pair<std::string, int> const& node);
void add_router_node(udp::endpoint const& node);
entry state() const;
enum flags_t { flag_seed = 1, flag_implied_port = 2 };
void announce(sha1_hash const& ih, int listen_port, int flags
, boost::function<void(std::vector<tcp::endpoint> const&)> f);
void get_item(sha1_hash const& target
, boost::function<void(item const&)> cb);
// key is a 32-byte binary string, the public key to look up.
// the salt is optional
void get_item(char const* key
, boost::function<void(item const&)> cb
, std::string salt = std::string());
void put_item(entry data
, boost::function<void()> cb);
void put_item(char const* key
, boost::function<void(item&)> cb, std::string salt = std::string());
void dht_status(session_status& s);
void network_stats(int& sent, int& received);
// translate bittorrent kademlia message into the generic kademlia message
// used by the library
virtual bool incoming_packet(error_code const& ec
, udp::endpoint const&, char const* buf, int size);
private:
boost::intrusive_ptr<dht_tracker> self()
{ return boost::intrusive_ptr<dht_tracker>(this); }
void on_name_lookup(error_code const& e
, udp::resolver::iterator host);
void on_router_name_lookup(error_code const& e
, udp::resolver::iterator host);
void connection_timeout(error_code const& e);
void refresh_timeout(error_code const& e);
void tick(error_code const& e);
// implements udp_socket_interface
virtual bool send_packet(libtorrent::entry& e, udp::endpoint const& addr
, int send_flags);
node_impl m_dht;
rate_limited_udp_socket& m_sock;
std::vector<char> m_send_buf;
ptime m_last_new_key;
deadline_timer m_timer;
deadline_timer m_connection_timer;
deadline_timer m_refresh_timer;
dht_settings const& m_settings;
int m_refresh_bucket;
bool m_abort;
// used to resolve hostnames for nodes
udp::resolver m_host_resolver;
// sent and received bytes since queried last time
int m_sent_bytes;
int m_received_bytes;
// used to ignore abusive dht nodes
struct node_ban_entry
{
node_ban_entry(): count(0) {}
address src;
ptime limit;
int count;
};
enum { num_ban_nodes = 20 };
node_ban_entry m_ban_nodes[num_ban_nodes];
// reference counter for intrusive_ptr
mutable boost::detail::atomic_count m_refs;
#ifdef TORRENT_DHT_VERBOSE_LOGGING
int m_replies_sent[5];
int m_queries_received[5];
int m_replies_bytes_sent[5];
int m_queries_bytes_received[5];
int m_counter;
int m_total_message_input;
int m_total_in_bytes;
int m_total_out_bytes;
int m_queries_out_bytes;
#endif
};
}}
#endif
#endif

View File

@@ -0,0 +1,100 @@
/*
Copyright (c) 2006-2014, Arvid Norberg & Daniel Wallin
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 FIND_DATA_050323_HPP
#define FIND_DATA_050323_HPP
#include <vector>
#include <map>
#include <libtorrent/kademlia/traversal_algorithm.hpp>
#include <libtorrent/kademlia/node_id.hpp>
#include <libtorrent/kademlia/routing_table.hpp>
#include <libtorrent/kademlia/rpc_manager.hpp>
#include <libtorrent/kademlia/observer.hpp>
#include <libtorrent/kademlia/msg.hpp>
#include <boost/optional.hpp>
#include <boost/function/function1.hpp>
#include <boost/function/function2.hpp>
namespace libtorrent { namespace dht
{
typedef std::vector<char> packet_t;
class rpc_manager;
class node_impl;
// -------- find data -----------
struct find_data : traversal_algorithm
{
typedef boost::function<void(std::vector<std::pair<node_entry, std::string> > const&)> nodes_callback;
find_data(node_impl& node, node_id target
, nodes_callback const& ncallback);
void got_write_token(node_id const& n, std::string const& write_token);
virtual void start();
virtual char const* name() const;
node_id const target() const { return m_target; }
protected:
virtual void done();
virtual observer_ptr new_observer(void* ptr, udp::endpoint const& ep
, node_id const& id);
nodes_callback m_nodes_callback;
std::map<node_id, std::string> m_write_tokens;
bool m_done;
};
struct find_data_observer : traversal_observer
{
find_data_observer(
boost::intrusive_ptr<traversal_algorithm> const& algorithm
, udp::endpoint const& ep, node_id const& id)
: traversal_observer(algorithm, ep, id)
{}
virtual void reply(msg const&);
};
} } // namespace libtorrent::dht
#endif // FIND_DATA_050323_HPP

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