Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ set(libtorrent_aux_include_files
bandwidth_socket.hpp
bencoder.hpp
bind_to_device.hpp
bitmask.hpp
bloom_filter.hpp
bt_peer_connection.hpp
buffer.hpp
Expand All @@ -156,6 +157,13 @@ set(libtorrent_aux_include_files
copy_ptr.hpp
cpuid.hpp
crc32c.hpp
curl.hpp
curl_basic_request.hpp
curl_boost_socket.hpp
curl_pool.hpp
curl_request.hpp
curl_tracker_manager.hpp
curl_tracker_request.hpp
deadline_timer.hpp
debug.hpp
debug_disk_thread.hpp
Expand Down Expand Up @@ -192,7 +200,9 @@ set(libtorrent_aux_include_files
http_parser.hpp
http_stream.hpp
http_tracker_connection.hpp
http_tracker_request.hpp
instantiate_connection.hpp
intrusive_list.hpp
invariant_check.hpp
io.hpp
io_bytes.hpp
Expand All @@ -203,6 +213,7 @@ set(libtorrent_aux_include_files
link.hpp
listen_socket_handle.hpp
lsd.hpp
memory.hpp
merkle.hpp
merkle_tree.hpp
mmap_storage.hpp
Expand Down Expand Up @@ -325,6 +336,12 @@ set(sources
cpuid.cpp
crc32c.cpp
create_torrent.cpp
curl_basic_request.cpp
curl_boost_socket.cpp
curl_pool.cpp
curl_request.cpp
curl_tracker_manager.cpp
curl_tracker_request.cpp
directory.cpp
disabled_disk_io.cpp
disk_buffer_holder.cpp
Expand Down Expand Up @@ -352,6 +369,7 @@ set(sources
http_connection.cpp
http_parser.cpp
http_tracker_connection.cpp
http_tracker_request.cpp
i2p_stream.cpp
identify_client.cpp
instantiate_connection.cpp
Expand Down Expand Up @@ -738,6 +756,8 @@ target_optional_compile_definitions(torrent-rasterbar PUBLIC FEATURE NAME i2p DE
DESCRIPTION "build with I2P support" DISABLED TORRENT_USE_I2P=0)
target_optional_compile_definitions(torrent-rasterbar PUBLIC FEATURE NAME webtorrent DEFAULT OFF
DESCRIPTION "build with WebTorrent support" DISABLED TORRENT_USE_RTC=0)
target_optional_compile_definitions(torrent-rasterbar PUBLIC FEATURE NAME curl DEFAULT OFF
DESCRIPTION "Enable support for connection reuse and advanced HTTP features towards trackers" ENABLED TORRENT_USE_CURL=1)
target_optional_compile_definitions(torrent-rasterbar PUBLIC FEATURE NAME logging DEFAULT ON
DESCRIPTION "build with logging" DISABLED TORRENT_DISABLE_LOGGING)
target_optional_compile_definitions(torrent-rasterbar PUBLIC FEATURE NAME mutable-torrents DEFAULT ON
Expand Down Expand Up @@ -858,6 +878,21 @@ if (webtorrent)
endif()
endif()

if (curl)
find_public_dependency(CURL REQUIRED)
set_package_properties(CURL
PROPERTIES
URL "https://curl.se/"
DESCRIPTION "Command line tool and library for transferring data with URLs"
TYPE RECOMMENDED
PURPOSE "Enable support for connection reuse and advanced HTTP features towards tracker"
)
target_link_libraries(torrent-rasterbar PUBLIC CURL::libcurl)

target_optional_compile_definitions(torrent-rasterbar PUBLIC FEATURE NAME curl_debug DEFAULT OFF
DESCRIPTION "Enable curl logging connection details to stderr" ENABLED TORRENT_DEBUG_LIBCURL=1)
endif()

# Boost
find_public_dependency(Boost REQUIRED)
target_link_libraries(torrent-rasterbar PUBLIC Boost::headers)
Expand Down
1 change: 1 addition & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
2.1.0 not released

* (opt-in) use curl for tracker communication
* make the save path for part files configurable
* retry failed SAM connection (for i2p)
* deprecated remap_files(), and prevent it from breaking v2 torrents
Expand Down
46 changes: 46 additions & 0 deletions Jamfile
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,11 @@ rule linking ( properties * )
result += <library>wolfssl ;
}

if <curl>on in $(properties)
{
result += <library>curl ;
}

if <target-os>windows in $(properties)
|| <target-os>cygwin in $(properties)
{
Expand Down Expand Up @@ -608,6 +613,26 @@ rule wolfssl-include-path ( properties * )
return $(result) ;
}

rule curl-lib-path ( properties * )
{
local CURL_LIB = [ feature.get-values <curl-lib> : $(properties) ] ;
if $(CURL_LIB) != ""
{
return <search>$(CURL_LIB) ;
}
return ;
}

rule curl-include-path ( properties * )
{
local CURL_INCLUDE = [ feature.get-values <curl-include> : $(properties) ] ;
if $(CURL_INCLUDE) != ""
{
return <include>$(CURL_INCLUDE) ;
}
return ;
}

path-constant blacklist-file : tools/sanitizer-blacklist.txt ;

feature openssl-lib : : free path ;
Expand Down Expand Up @@ -642,6 +667,17 @@ feature webtorrent : off on : composite propagated ;
feature.compose <webtorrent>on : <define>TORRENT_USE_RTC=1 ;
feature.compose <webtorrent>off : <define>TORRENT_USE_RTC=0 ;

feature curl : off on : composite propagated ;
feature.compose <curl>on : <define>TORRENT_USE_CURL=1 ;
feature.compose <curl>off : <define>TORRENT_USE_CURL=0 ;

feature curl-lib : : free path ;
feature curl-include : : free path ;

feature curl_debug : off on : composite propagated ;
feature.compose <curl_debug>on : <define>TORRENT_DEBUG_LIBCURL=1 ;
feature.compose <curl_debug>off : <define>TORRENT_DEBUG_LIBCURL=0 ;

feature asserts : off on production system : composite propagated ;
feature.compose <asserts>on : <define>TORRENT_USE_ASSERTS=1 ;
feature.compose <asserts>production : <define>TORRENT_USE_ASSERTS=1 <define>TORRENT_PRODUCTION_ASSERTS=1 ;
Expand Down Expand Up @@ -816,6 +852,9 @@ lib gnutls : : <name>gnutls <conditional>@gnutls-lib-path : :
lib wolfssl : : <name>wolfssl <conditional>@wolfssl-lib-path : :
<conditional>@wolfssl-include-path ;

lib curl : : <name>curl <conditional>@curl-lib-path : :
<conditional>@curl-include-path ;

lib dbghelp : : <name>dbghelp ;

# required for networking on beos
Expand Down Expand Up @@ -853,6 +892,12 @@ SOURCES =
cpuid
crc32c
create_torrent
curl_basic_request
curl_boost_socket
curl_pool
curl_request
curl_tracker_manager
curl_tracker_request
directory
disk_buffer_holder
disk_buffer_pool
Expand Down Expand Up @@ -928,6 +973,7 @@ SOURCES =
time
tracker_manager
http_tracker_connection
http_tracker_request
udp_tracker_connection
timestamp_history
udp_socket
Expand Down
18 changes: 18 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,12 @@ SOURCES = \
cpuid.cpp \
crc32c.cpp \
create_torrent.cpp \
curl_basic_request.cpp \
curl_boost_socket.cpp \
curl_pool.cpp \
curl_request.cpp \
curl_tracker_manager.cpp \
curl_tracker_request.cpp \
directory.cpp \
disabled_disk_io.cpp \
disk_buffer_holder.cpp \
Expand Down Expand Up @@ -346,6 +352,7 @@ SOURCES = \
http_connection.cpp \
http_parser.cpp \
http_tracker_connection.cpp \
http_tracker_request.cpp \
i2p_stream.cpp \
identify_client.cpp \
instantiate_connection.cpp \
Expand Down Expand Up @@ -541,6 +548,7 @@ HEADERS = \
aux_/bandwidth_socket.hpp \
aux_/bencoder.hpp \
aux_/bind_to_device.hpp \
aux_/bitmask.hpp \
aux_/buffer.hpp \
aux_/byteswap.hpp \
aux_/bloom_filter.hpp \
Expand All @@ -551,6 +559,13 @@ HEADERS = \
aux_/copy_ptr.hpp \
aux_/cpuid.hpp \
aux_/crc32c.hpp \
aux_/curl.hpp \
aux_/curl_basic_request.hpp \
aux_/curl_boost_socket.hpp \
aux_/curl_pool.hpp \
aux_/curl_request.hpp \
aux_/curl_tracker_manager.hpp \
aux_/curl_tracker_request.hpp \
aux_/deadline_timer.hpp \
aux_/debug.hpp \
aux_/debug_disk_thread.hpp \
Expand Down Expand Up @@ -589,7 +604,9 @@ HEADERS = \
aux_/http_parser.hpp \
aux_/http_stream.hpp \
aux_/http_tracker_connection.hpp \
aux_/http_tracker_request.hpp \
aux_/instantiate_connection.hpp \
aux_/intrusive_list.hpp \
aux_/invariant_check.hpp \
aux_/io.hpp \
aux_/io_bytes.hpp \
Expand All @@ -600,6 +617,7 @@ HEADERS = \
aux_/link.hpp \
aux_/listen_socket_handle.hpp \
aux_/lsd.hpp \
aux_/memory.hpp \
aux_/merkle.hpp \
aux_/merkle_tree.hpp \
aux_/mmap.hpp \
Expand Down
21 changes: 21 additions & 0 deletions docs/building.rst
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,10 @@ To customize the library path and include path for wolfSSL, set the features
To disable linking against any SSL library, set the ``crypto`` build feature to
``built-in``. This will use an embedded version if SHA-1.

When building with curl enabled, customize the library and include paths by
setting the features ``curl-lib`` and ``curl-include``, respectively. To enable
logging of curl's connection details to stderr, set ``curl_debug=on``.

Build features
~~~~~~~~~~~~~~

Expand Down Expand Up @@ -460,6 +464,15 @@ Build features
| | * ``off`` - disable mmap storage, and fall back to |
| | single-threaded, portable file operations. |
+--------------------------+----------------------------------------------------+
| ``curl`` | * ``off`` - default. HTTP connections to trackers |
| | don't support connection- and SSL session reuse. |
| | * ``on`` - libcurl is used for HTTP connections |
| | to trackers, enabling connection- and SSL |
| | session reuse. This includes support for the |
| | default libcurl HTTP features. |
| | Note that libcurl needs to be build against |
| | c-aris for async DNS support. |
+--------------------------+----------------------------------------------------+

The ``variant`` feature is *implicit*, which means you don't need to specify
the name of the feature, just the value.
Expand Down Expand Up @@ -599,6 +612,10 @@ Other build options are:

Options are set on the ``cmake`` command line with the ``-D`` option or later on using ``ccmake`` or ``cmake-gui`` applications. ``cmake`` run outputs a summary of all available options and their current values.

To link with a custom build of libcurl (or any other library), first build and install libcurl with
custom dependencies to a custom prefix path. Then use the option ``CMAKE_PREFIX_PATH=/path/to/custom/dependencies/prefix``
in libtorrent's cmake configuration.

Step 2: Building libtorrent
~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down Expand Up @@ -748,6 +765,10 @@ own code that compiles and links with libtorrent.
| | peers are connected over authenticated SSL |
| | streams. |
+----------------------------------------+-------------------------------------------------+
| ``TORRENT_USE_CURL=1`` | Libcurl is used for HTTP connections to |
| | trackers. This will enable connection- and SSL |
| | session reuse. |
+----------------------------------------+-------------------------------------------------+

.. _`BEP 38`: https://www.bittorrent.org/beps/bep_0038.html

Expand Down
43 changes: 43 additions & 0 deletions include/libtorrent/aux_/bitmask.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*

Copyright (c) 2026, Arvid Norberg
Copyright (c) 2026, The Baron Vladimir Harkonnen
All rights reserved.

You may use, distribute and modify this code under the terms of the BSD license,
see LICENSE file.
*/

#ifndef TORRENT_BITMASK_HPP_INCLUDED
#define TORRENT_BITMASK_HPP_INCLUDED

#include <type_traits>

template<typename E>
class bitmask {
using U = std::underlying_type_t<E>;
U bits;
public:
static_assert(std::is_enum_v<E>);
using option = E;

constexpr bitmask(E e = static_cast<E>(0)) noexcept : bits(static_cast<U>(e)) {}
constexpr explicit bitmask(U b) noexcept : bits(b) {}
[[nodiscard]] constexpr U raw() const noexcept { return bits; }

constexpr bool operator==(bitmask o) const noexcept { return bits == o.bits; }
constexpr bitmask operator|(bitmask o) const noexcept { return bitmask(bits | o.bits); }
constexpr bitmask operator&(bitmask o) const noexcept { return bitmask(bits & o.bits); }
constexpr bitmask operator^(bitmask o) const noexcept { return bitmask(bits ^ o.bits); }
constexpr bitmask operator~() const noexcept { return bitmask(~bits); }
constexpr bitmask& operator|=(bitmask o) noexcept { bits |= o.bits; return *this; }
constexpr bitmask& operator&=(bitmask o) noexcept { bits &= o.bits; return *this; }
constexpr bitmask& operator^=(bitmask o) noexcept { bits ^= o.bits; return *this; }

constexpr explicit operator bool() const noexcept { return bits != 0; }
[[nodiscard]] constexpr bool test(E e) const noexcept { return (bits & static_cast<U>(e)) != 0; }
[[nodiscard]] constexpr bool test(bitmask o) const noexcept { return (bits & o.bits) != 0; }
constexpr void unset(E e) noexcept { bits &= ~static_cast<U>(e); }
};

#endif //TORRENT_BITMASK_HPP_INCLUDED
58 changes: 58 additions & 0 deletions include/libtorrent/aux_/curl.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*

Copyright (c) 2026, Arvid Norberg
Copyright (c) 2026, The Baron Vladimir Harkonnen
All rights reserved.

You may use, distribute and modify this code under the terms of the BSD license,
see LICENSE file.
*/

#ifndef TORRENT_CURL_HPP_INCLUDED
#define TORRENT_CURL_HPP_INCLUDED
#include "libtorrent/config.hpp"

#if TORRENT_USE_CURL
#include <stdexcept>
#include <string>
#include <curl/curl.h>

namespace libtorrent::aux {

enum class curl_poll_t : int {
none = CURL_POLL_NONE,
in = CURL_POLL_IN,
out = CURL_POLL_OUT,
remove = CURL_POLL_REMOVE,
};
static_assert(CURL_POLL_INOUT == (CURL_POLL_IN | CURL_POLL_OUT));

enum class curl_cselect_t : int {
none = 0, // curl allows the value to be 0, but does not define a type for it
in = CURL_CSELECT_IN,
out = CURL_CSELECT_OUT,
err = CURL_CSELECT_ERR,
};

class curl_easy_error: public std::runtime_error
{
CURLcode code_;

public:
curl_easy_error( CURLcode const ec, std::string const & prefix ):
std::runtime_error( prefix + ": " + curl_easy_strerror(ec) ), code_( ec ) {}

[[nodiscard]] CURLcode code() const noexcept
{
return code_;
}
};

inline bool curl_version_lower_than(unsigned int version) {
const auto ver = curl_version_info(CURLVERSION_NOW);
return !ver || ver->version_num < version;
}
}

#endif //TORRENT_USE_CURL
#endif //TORRENT_CURL_HPP_INCLUDED
Loading