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
4 changes: 2 additions & 2 deletions .github/workflows/static-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
autoconf -i
autoheader
automake --add-missing
./configure
./configure --disable-webtorrent
make
sudo make install
cd ..
Expand All @@ -49,7 +49,7 @@ jobs:
autoconf -i
autoheader
automake --add-missing
./configure
./configure --disable-webtorrent
- name: Prepare compile_commands.json
run: |
bear -- make
Expand Down
77 changes: 69 additions & 8 deletions .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@ jobs:

ubuntu-base:
runs-on: ubuntu-22.04
strategy:
fail-fast: false
matrix:
libtorrent:
- name: default
libtorrent_repo: rakshasa/libtorrent
libtorrent_ref: master
libt_configure_flags: --disable-webtorrent
- name: webtorrent
libtorrent_repo: kingomarwashere/libtorrent
libtorrent_ref: webtorrent-support
libt_configure_flags: --enable-webtorrent
steps:
- name: Update Packages
run: |
Expand All @@ -15,21 +27,40 @@ jobs:
sudo apt-get install -y \
libcppunit-dev \
zlib1g-dev \
libcurl4-openssl-dev
libcurl4-openssl-dev \
libssl-dev \
nlohmann-json3-dev \
pkg-config \
cmake
- name: Install libdatachannel
if: matrix.libtorrent.name == 'webtorrent'
run: |
if apt-cache show libdatachannel-dev >/dev/null 2>&1; then
sudo apt-get install -y libdatachannel-dev
else
git clone --recursive --depth 1 https://github.com/paullouisageneau/libdatachannel
cmake -S libdatachannel -B libdatachannel/build \
-DNO_EXAMPLES=ON \
-DNO_TESTS=ON \
-DUSE_GNUTLS=0
cmake --build libdatachannel/build --parallel
sudo cmake --install libdatachannel/build
sudo ldconfig
fi
- name: Fetch libtorrent
run: |
git clone https://github.com/rakshasa/libtorrent
git clone --branch "${{ matrix.libtorrent.libtorrent_ref }}" "https://github.com/${{ matrix.libtorrent.libtorrent_repo }}" libtorrent
- name: Build libtorrent
run: |
cd libtorrent
autoreconf -fiv
./configure
./configure ${{ matrix.libtorrent.libt_configure_flags }}
make
sudo make install DESTDIR=$GITHUB_WORKSPACE/libtorrent-dist
- name: Upload Build Artifacts
uses: actions/upload-artifact@v4
with:
name: installed-libtorrent
name: installed-libtorrent-${{ matrix.libtorrent.name }}
path: libtorrent-dist/


Expand All @@ -46,7 +77,7 @@ jobs:
- name: Download Libtorrent Artifacts
uses: actions/download-artifact@v4
with:
name: installed-libtorrent
name: installed-libtorrent-default
path: ./libtorrent-dist
- name: Move Artifacts to System Path
run: |
Expand All @@ -57,7 +88,7 @@ jobs:
- name: Configure Project
run: |
autoreconf -fiv
./configure
./configure --disable-webtorrent
make
ls /usr/local/lib/
LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib" make check
Expand Down Expand Up @@ -85,7 +116,37 @@ jobs:
- name: Download Libtorrent Artifacts
uses: actions/download-artifact@v4
with:
name: installed-libtorrent
name: installed-libtorrent-default
path: ./libtorrent-dist
- name: Move Artifacts to System Path
run: |
sudo cp -r ./libtorrent-dist/usr/local/* /usr/local/
rm -rf ./libtorrent-dist
- uses: actions/checkout@v4
- name: Configure Project
run: |
autoreconf -fiv
./configure --disable-webtorrent ${{ matrix.config_flag }}
make
ls /usr/local/lib/
LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib" make check

unit-tests-webtorrent:
runs-on: ubuntu-22.04
needs: ubuntu-base
steps:
- name: Install Dependencies
run: |
sudo apt-get install -y \
libcppunit-dev \
zlib1g-dev \
libcurl4-openssl-dev \
libssl-dev \
nlohmann-json3-dev
- name: Download Libtorrent Artifacts
uses: actions/download-artifact@v4
with:
name: installed-libtorrent-webtorrent
path: ./libtorrent-dist
- name: Move Artifacts to System Path
run: |
Expand All @@ -95,7 +156,7 @@ jobs:
- name: Configure Project
run: |
autoreconf -fiv
./configure ${{ matrix.config_flag }}
./configure --enable-webtorrent
make
ls /usr/local/lib/
LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib" make check
36 changes: 36 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,42 @@ PKG_CHECK_MODULES([CPPUNIT], [cppunit],, [no_cppunit="yes"])
PKG_CHECK_MODULES([ZLIB], [zlib])
PKG_CHECK_MODULES([DEPENDENCIES], [libtorrent >= 0.16.15])

AC_ARG_ENABLE(webtorrent,
AS_HELP_STRING([--disable-webtorrent],
[disable WebTorrent support [[default=enable]]]),
[], [enable_webtorrent=yes])

AS_IF([test "x$enable_webtorrent" != "xno"], [
AC_LANG_PUSH([C++])
rtorrent_save_CXXFLAGS="$CXXFLAGS"
CXXFLAGS="$CXXFLAGS $DEPENDENCIES_CFLAGS"
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[[
#include <torrent/common.h>
#include <torrent/peer/peer.h>
#include <torrent/runtime/runtime.h>
#ifndef LIBTORRENT_HAS_WEBTORRENT
#error "libtorrent was not built with WebTorrent support"
#endif
]],
[[
bool supported = torrent::runtime::webtorrent_supported();
torrent::runtime::set_webtorrent_enabled(supported);
bool enabled = torrent::runtime::webtorrent_enabled();
torrent::tracker_enum tracker_type = torrent::TRACKER_WEBSOCKET;
torrent::Peer* peer = nullptr;
bool is_webtorrent = peer != nullptr && peer->is_webtorrent();
(void)enabled;
(void)tracker_type;
(void)is_webtorrent;
]])],
[AC_DEFINE([HAVE_LIBUTORRENT_WEBTORRENT], [1], [Define if libtorrent exposes WebTorrent support.])],
[AC_MSG_ERROR([WebTorrent support requested but installed libtorrent does not expose the required WebTorrent API. Install a WebTorrent-enabled rakshasa/libtorrent or configure with --disable-webtorrent.])])
CXXFLAGS="$rtorrent_save_CXXFLAGS"
AC_LANG_POP([C++])
])

AC_LANG_PUSH(C++)
TORRENT_WITH_XMLRPC_C
AC_LANG_POP(C++)
Expand Down
7 changes: 7 additions & 0 deletions doc/rtorrent.rc
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,13 @@
#
#protocol.pex.set = yes

# Enable WebTorrent support when built against a WebTorrent-enabled
# rakshasa/libtorrent. WebSocket trackers (ws:// and wss://) are handled by
# libtorrent. Enabled by default when available.
#
#protocol.webtorrent.set = yes
#protocol.webtorrent.set = no

# Set download list layout style ("full", "compact").
#
#ui.torrent_list.layout.set = "full"
Expand Down
4 changes: 4 additions & 0 deletions doc/rtorrent.rc-example
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ network.port_random.set = no
# (conservative settings for 'private' trackers, change for 'public')
dht.mode.set = disable
protocol.pex.set = no
# WebTorrent requires a WebTorrent-enabled rakshasa/libtorrent. WebSocket
# trackers (ws:// and wss://) are handled by libtorrent.
#protocol.webtorrent.set = yes
#protocol.webtorrent.set = no
trackers.use_udp.set = no

# Peer settings
Expand Down
4 changes: 4 additions & 0 deletions doc/rtorrent.rc.lua-example
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ rc.network.port_random = false
-- (conservative settings for 'private' trackers, change for 'public')
rc.dht.mode = 'disable'
rc.protocol.pex = false
-- WebTorrent requires a WebTorrent-enabled rakshasa/libtorrent. WebSocket
-- trackers (ws:// and wss://) are handled by libtorrent.
--rc.protocol.webtorrent = true
--rc.protocol.webtorrent = false
rc.trackers.use_udp = false

-- Peer settings
Expand Down
8 changes: 8 additions & 0 deletions src/command_local.cc
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,13 @@ initialize_command_local() {
CMD_VAR_C_STRING("system.api_version", (int64_t)API_VERSION);
CMD_VAR_C_STRING("system.client_version", PACKAGE_VERSION);
CMD_VAR_C_STRING("system.library_version", torrent::runtime::version());
CMD_VAR_C_STRING("system.has_webtorrent",
#ifdef HAVE_LIBUTORRENT_WEBTORRENT
int64_t(1)
#else
int64_t(0)
#endif
);

CMD_VAR_VALUE ("system.file.allocate", 0);
CMD_VAR_VALUE ("system.file.max_size", (int64_t)512 << 30);
Expand Down Expand Up @@ -344,6 +351,7 @@ initialize_command_local() {

rpc::rpc.mark_safe("system.api_version");
rpc::rpc.mark_safe("system.client_version");
rpc::rpc.mark_safe("system.has_webtorrent");
rpc::rpc.mark_safe("system.library_version");
rpc::rpc.mark_safe("system.file.max_size");
rpc::rpc.mark_safe("system.file.split_size");
Expand Down
24 changes: 24 additions & 0 deletions src/command_network.cc
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,27 @@ apply_tos(const torrent::Object::string_type& arg) {
return torrent::Object();
}

torrent::Object
retrieve_protocol_webtorrent() {
#ifdef HAVE_LIBUTORRENT_WEBTORRENT
return int64_t(torrent::runtime::webtorrent_supported() && torrent::runtime::webtorrent_enabled());
#else
return int64_t(0);
#endif
}

torrent::Object
apply_protocol_webtorrent(int64_t value) {
#ifdef HAVE_LIBUTORRENT_WEBTORRENT
torrent::runtime::set_webtorrent_enabled(value != 0);
#else
if (value != 0)
throw torrent::input_error("WebTorrent support is not available in this build.");
#endif

return torrent::Object();
}

void
initialize_rpc_handlers() {
rpc::rpc.initialize_handlers();
Expand Down Expand Up @@ -229,6 +250,8 @@ initialize_command_network() {
CMD2_ANY_VALUE_V ("network.listen.backlog.set", [nw_config](auto, auto& value) { return nw_config->set_listen_backlog(value); });

CMD2_VAR_BOOL ("protocol.pex", true);
CMD2_ANY ("protocol.webtorrent", [](auto, auto) { return retrieve_protocol_webtorrent(); });
CMD2_ANY_VALUE_V ("protocol.webtorrent.set", [](auto, auto& value) { return apply_protocol_webtorrent(value); });
CMD2_ANY_LIST ("protocol.encryption.set", [](auto, auto& args) { return apply_encryption(args); });

CMD2_VAR_STRING ("protocol.connection.leech", "leech");
Expand Down Expand Up @@ -340,6 +363,7 @@ initialize_command_network() {
rpc::rpc.mark_safe("network.proxy_address");
rpc::rpc.mark_safe("network.scgi.dont_route");
rpc::rpc.mark_safe("protocol.pex");
rpc::rpc.mark_safe("protocol.webtorrent");

rpc::rpc.mark_safe("network.rpc.use_xmlrpc");
rpc::rpc.mark_safe("network.rpc.use_jsonrpc");
Expand Down
22 changes: 22 additions & 0 deletions src/command_peer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,24 @@ retrieve_p_completed_percent(torrent::Peer* peer) {
return (100 * peer->bitfield()->size_set()) / peer->bitfield()->size_bits();
}

torrent::Object
retrieve_p_is_webtorrent(torrent::Peer* peer) {
#ifdef HAVE_LIBUTORRENT_WEBTORRENT
return int64_t(peer->is_webtorrent());
#else
return int64_t(0);
#endif
}

torrent::Object
retrieve_p_transport(torrent::Peer* peer) {
#ifdef HAVE_LIBUTORRENT_WEBTORRENT
return peer->is_webtorrent() ? std::string("webrtc") : std::string("tcp");
#else
return std::string("tcp");
#endif
}

void
initialize_command_peer() {
CMD2_PEER("p.id", [](auto* peer, auto) { return torrent::utils::transform_to_hex_str(peer->id()); });
Expand All @@ -56,6 +74,8 @@ initialize_command_peer() {
CMD2_PEER("p.is_encrypted", std::bind(&torrent::Peer::is_encrypted, std::placeholders::_1));
CMD2_PEER("p.is_incoming", std::bind(&torrent::Peer::is_incoming, std::placeholders::_1));
CMD2_PEER("p.is_obfuscated", std::bind(&torrent::Peer::is_obfuscated, std::placeholders::_1));
CMD2_PEER("p.is_webtorrent", std::bind(&retrieve_p_is_webtorrent, std::placeholders::_1));
CMD2_PEER("p.transport", std::bind(&retrieve_p_transport, std::placeholders::_1));
CMD2_PEER("p.is_snubbed", std::bind(&torrent::Peer::is_snubbed, std::placeholders::_1));

CMD2_PEER("p.is_unwanted", std::bind(&torrent::PeerInfo::is_unwanted, std::bind(&torrent::Peer::peer_info, std::placeholders::_1)));
Expand Down Expand Up @@ -96,6 +116,8 @@ initialize_command_peer() {
rpc::rpc.mark_safe("p.is_encrypted");
rpc::rpc.mark_safe("p.is_incoming");
rpc::rpc.mark_safe("p.is_obfuscated");
rpc::rpc.mark_safe("p.is_webtorrent");
rpc::rpc.mark_safe("p.transport");
rpc::rpc.mark_safe("p.is_snubbed");
rpc::rpc.mark_safe("p.is_unwanted");
rpc::rpc.mark_safe("p.is_preferred");
Expand Down
16 changes: 16 additions & 0 deletions src/command_tracker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,20 @@ apply_enable_trackers(int64_t arg) {
return torrent::Object();
}

const char*
tracker_type_name(torrent::tracker_enum type) {
switch (type) {
case torrent::TRACKER_HTTP: return "http";
case torrent::TRACKER_UDP: return "udp";
case torrent::TRACKER_DHT: return "dht";
#ifdef HAVE_LIBUTORRENT_WEBTORRENT
case torrent::TRACKER_WEBSOCKET: return "websocket";
#endif
case torrent::TRACKER_NONE:
default: return "none";
}
}

void
initialize_command_tracker() {
CMD2_TRACKER ("t.is_busy", [](auto* tracker, auto) { return tracker->is_requesting(); });
Expand All @@ -99,6 +113,7 @@ initialize_command_tracker() {
CMD2_TRACKER ("t.url", [](auto* tracker, auto) { return tracker->url(); });
CMD2_TRACKER ("t.group", [](auto* tracker, auto) { return tracker->group(); });
CMD2_TRACKER ("t.type", [](auto* tracker, auto) { return tracker->type(); });
CMD2_TRACKER ("t.type_str", [](auto* tracker, auto) { return std::string(tracker_type_name(tracker->type())); });
CMD2_TRACKER ("t.id", [](auto* tracker, auto) { return tracker->tracker_id(); });

CMD2_TRACKER ("t.latest_event", [](auto* tracker, auto) { return tracker->state().latest_event(); });
Expand Down Expand Up @@ -151,6 +166,7 @@ initialize_command_tracker() {
rpc::rpc.mark_safe("t.group");
rpc::rpc.mark_safe("t.id");
rpc::rpc.mark_safe("t.type");
rpc::rpc.mark_safe("t.type_str");
rpc::rpc.mark_safe("t.is_usable");
rpc::rpc.mark_safe("t.is_busy");
rpc::rpc.mark_safe("t.is_enabled");
Expand Down
Loading