mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-08-05 17:52:29 +00:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d8664e6b4c | |||
| 7e907616a2 | |||
| dcf13ab21a | |||
| 03c4467a33 | |||
| fc5ce92c46 | |||
| f1b22023a0 | |||
| 928f3e58a8 | |||
| 743363b405 |
@@ -1,65 +0,0 @@
|
||||
name: "Lint Commit Message Size"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
jobs:
|
||||
check-commit-bounds:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Validate Line Count, Width, and Spacing
|
||||
run: |
|
||||
# Fetch commit hashes unique to this PR branch
|
||||
COMMITS=$(git log --no-merges --pretty=format:"%H" origin/${{ github.base_ref }}..HEAD)
|
||||
|
||||
MAX_LINES=3
|
||||
MAX_CHARS=90
|
||||
FAILED=0
|
||||
|
||||
for commit in $COMMITS; do
|
||||
SUBJECT=$(git log --format="%s" -n 1 $commit)
|
||||
|
||||
# Extract clean commit message, trimming trailing blank lines
|
||||
RAW_MSG=$(git log --format="%B" -n 1 $commit)
|
||||
CLEAN_MSG=$(echo "$RAW_MSG" | awk '{msg[NR]=$0} END {while(NR>0 && msg[NR]=="") NR--; for(i=1;i<=NR;i++) print msg[i]}')
|
||||
|
||||
# 1. Check total line count
|
||||
LINE_COUNT=$(echo "$CLEAN_MSG" | wc -l)
|
||||
if [ "$LINE_COUNT" -gt "$MAX_LINES" ]; then
|
||||
echo "❌ Error: Commit message has too many lines ($LINE_COUNT/$MAX_LINES)."
|
||||
echo " Commit: '$SUBJECT'"
|
||||
FAILED=1
|
||||
fi
|
||||
|
||||
# 2. Check for multiple consecutive blank lines
|
||||
# This regex looks for 2 or more empty lines anywhere in the message
|
||||
if echo "$CLEAN_MSG" | grep -pz '(\r?\n){3,}'; then
|
||||
echo "❌ Error: Commit message contains multiple consecutive line breaks."
|
||||
echo " Commit: '$SUBJECT'"
|
||||
FAILED=1
|
||||
fi
|
||||
|
||||
# 3. Check maximum width of any individual line
|
||||
while IFS= read -r line; do
|
||||
LINE_LENGTH=${#line}
|
||||
if [ "$LINE_LENGTH" -gt "$MAX_CHARS" ]; then
|
||||
echo "❌ Error: Line length exceeds limit ($LINE_LENGTH / $MAX_CHARS chars)."
|
||||
echo " Offending line: '$line'"
|
||||
FAILED=1
|
||||
fi
|
||||
done <<< "$CLEAN_MSG"
|
||||
|
||||
done
|
||||
|
||||
# Fail the job if any check failed
|
||||
if [ "$FAILED" -ne 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ All commit messages passed style rules!"
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
m4_pattern_allow([PKG_CHECK_EXISTS])
|
||||
|
||||
AC_INIT([rtorrent],[0.16.19],[sundell.software@gmail.com])
|
||||
AC_INIT([rtorrent],[0.16.17],[sundell.software@gmail.com])
|
||||
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_MACRO_DIRS([scripts])
|
||||
@@ -14,7 +14,7 @@ AX_CXX_COMPILE_STDCXX(20, noext, mandatory)
|
||||
|
||||
PKG_PROG_PKG_CONFIG
|
||||
|
||||
AC_DEFINE([API_VERSION], [24], [api version])
|
||||
AC_DEFINE([API_VERSION], [23], [api version])
|
||||
|
||||
RAK_CHECK_CFLAGS
|
||||
RAK_CHECK_CXXFLAGS
|
||||
@@ -47,7 +47,7 @@ fi
|
||||
|
||||
PKG_CHECK_MODULES([CPPUNIT], [cppunit],, [no_cppunit="yes"])
|
||||
PKG_CHECK_MODULES([ZLIB], [zlib])
|
||||
PKG_CHECK_MODULES([DEPENDENCIES], [libtorrent >= 0.16.19])
|
||||
PKG_CHECK_MODULES([DEPENDENCIES], [libtorrent >= 0.16.17])
|
||||
|
||||
AC_LANG_PUSH(C++)
|
||||
TORRENT_WITH_XMLRPC_C
|
||||
|
||||
+9
-15
@@ -214,21 +214,15 @@ Add a preferred filename encoding to the list. The encodings are
|
||||
attempted in the order they are inserted, if none match the torrent
|
||||
default is used.
|
||||
.TP
|
||||
\fBencryption = \fIoption\fB,\fI\&...\fB\fR
|
||||
Set how rtorrent should deal with encrypted Bittorrent connections. By
|
||||
default, encryption is disabled, equivalent to specifying the option
|
||||
\fBnone\fR\&. Alternatively, any number of the following
|
||||
options may be specified:
|
||||
|
||||
\fBallow_incoming\fR (allow incoming encrypted connections),
|
||||
\fBtry_outgoing\fR (use encryption for outgoing connections),
|
||||
\fBrequire\fR (disable unencrypted handshakes),
|
||||
\fBrequire_RC4\fR (also disable plaintext transmission after the
|
||||
initial encrypted handshake),
|
||||
\fBenable_retry\fR (if the initial outgoing connection fails, retry
|
||||
with encryption turned on if it was off or off if it was on),
|
||||
\fBprefer_plaintext\fR (choose plaintext when peer offers a choice
|
||||
between plaintext transmission and RC4 encryption, otherwise RC4 will be used).
|
||||
\fBprotocol.encryption.handshake.set\fR (deny, allow, prefer, require)
|
||||
and \fBprotocol.encryption.stream.set\fR (deny, allow, prefer,
|
||||
require) control how rtorrent deals with encrypted Bittorrent
|
||||
connections. Handshake \fBallow\fR accepts plain or PE inbound and
|
||||
tries plain first outbound with one PE retry on failure.
|
||||
\fBprefer\fR tries PE first with one plain retry. Stream \fBallow\fR
|
||||
and \fBprefer\fR offer both handshake-only and RC4 on outgoing PE
|
||||
connections. The default is handshake=allow, stream=allow. Use
|
||||
\fBprotocol.encryption\fR to inspect the effective policy.
|
||||
.TP
|
||||
\fBpeer_exchange = \fIyes | no\fB\fR
|
||||
Enable/disable peer exchange for torrents that aren't marked private. Disabled by default.
|
||||
|
||||
+11
-17
@@ -484,25 +484,19 @@ default is used.
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>encryption = <replaceable>option</replaceable>,<replaceable>...</replaceable></term>
|
||||
<term>protocol.encryption.handshake.set = <replaceable>policy</replaceable></term>
|
||||
<listitem><para>
|
||||
|
||||
Set how rtorrent should deal with encrypted Bittorrent connections. By
|
||||
default, encryption is disabled, equivalent to specifying the option
|
||||
<emphasis>none</emphasis>. Alternatively, any number of the following
|
||||
options may be specified:
|
||||
|
||||
</para><para>
|
||||
|
||||
<emphasis>allow_incoming</emphasis> (allow incoming encrypted connections),
|
||||
<emphasis>try_outgoing</emphasis> (use encryption for outgoing connections),
|
||||
<emphasis>require</emphasis> (disable unencrypted handshakes),
|
||||
<emphasis>require_RC4</emphasis> (also disable plaintext transmission after the
|
||||
initial encrypted handshake),
|
||||
<emphasis>enable_retry</emphasis> (if the initial outgoing connection fails, retry
|
||||
with encryption turned on if it was off or off if it was on),
|
||||
<emphasis>prefer_plaintext</emphasis> (choose plaintext when peer offers a choice
|
||||
between plaintext transmission and RC4 encryption, otherwise RC4 will be used).
|
||||
Control how rtorrent deals with encrypted Bittorrent connections.
|
||||
<emphasis>protocol.encryption.handshake.set</emphasis> (deny, allow, prefer,
|
||||
require) and <emphasis>protocol.encryption.stream.set</emphasis> (deny, allow,
|
||||
prefer, require). Handshake <emphasis>allow</emphasis> accepts plain or PE
|
||||
inbound and tries plain first outbound with one PE retry on failure.
|
||||
<emphasis>prefer</emphasis> tries PE first with one plain retry. Stream
|
||||
<emphasis>allow</emphasis> and <emphasis>prefer</emphasis> offer both
|
||||
handshake-only and RC4 on outgoing PE connections. The default is
|
||||
handshake=allow, stream=allow. Use <emphasis>protocol.encryption</emphasis> to
|
||||
inspect the effective policy.
|
||||
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
+32
-6
@@ -95,14 +95,40 @@
|
||||
#schedule2 = ip_tick,0,1800,ip=rakshasa
|
||||
#schedule2 = bind_tick,0,1800,bind=rakshasa
|
||||
|
||||
# Encryption options, set to none (default) or any combination of the following:
|
||||
# allow_incoming, try_outgoing, require, require_RC4, enable_retry, prefer_plaintext
|
||||
# --- Protocol encryption (PE handshake / optional RC4 stream) ---
|
||||
# Default at startup: handshake=allow stream=allow
|
||||
#
|
||||
# The example value allows incoming encrypted connections, starts unencrypted
|
||||
# outgoing connections but retries with encryption if they fail, preferring
|
||||
# plain-text to RC4 encryption after the encrypted handshake.
|
||||
# Handshake (PE handshake; incoming accepts plain or PE for allow/prefer):
|
||||
# deny - plain BT handshake only both ways; no retry
|
||||
# allow - accept plain or PE inbound; plain first outbound with one PE retry
|
||||
# prefer - accept plain or PE inbound; PE first outbound with one plain retry
|
||||
# require - PE handshake required both ways; no retry
|
||||
#
|
||||
# protocol.encryption.set = allow_incoming,enable_retry,prefer_plaintext
|
||||
# protocol.encryption.handshake.set = allow
|
||||
#
|
||||
# Stream (cipher negotiation after PE handshake succeeds):
|
||||
# deny - offer handshake-only; require handshake-only (no RC4)
|
||||
# allow - incoming: prefer handshake-only if offered, else RC4
|
||||
# outgoing: offer both handshake-only and RC4
|
||||
# prefer - incoming: pick RC4 if offered, else handshake-only
|
||||
# outgoing: offer both handshake-only and RC4
|
||||
# require - offer RC4 only; require RC4
|
||||
#
|
||||
# Outgoing retry summary with handshake=allow (plain first):
|
||||
# stream=allow/prefer -> plain BT -> PE (both)
|
||||
# stream=deny -> plain BT -> PE (handshake-only)
|
||||
# stream=require -> plain BT -> PE (RC4-only)
|
||||
#
|
||||
# Outgoing retry summary with handshake=prefer (PE first):
|
||||
# stream=allow/prefer -> PE (both) -> plain BT
|
||||
# stream=deny -> PE (handshake-only) -> plain BT
|
||||
# stream=require -> PE (RC4-only) -> plain BT
|
||||
#
|
||||
# Negotiated stream cipher is logged at connection_handshake level.
|
||||
#
|
||||
# protocol.encryption.stream.set = allow
|
||||
#
|
||||
# Use protocol.encryption to inspect the effective policy.
|
||||
|
||||
# Enable DHT support for trackerless torrents or when all trackers are down.
|
||||
# May be set to "disable" (completely disable DHT), "off" (do not start DHT),
|
||||
|
||||
@@ -42,7 +42,8 @@ throttle.min_peers.seed.set = 30
|
||||
throttle.max_peers.seed.set = 80
|
||||
trackers.numwant.set = 80
|
||||
|
||||
protocol.encryption.set = allow_incoming,try_outgoing,enable_retry
|
||||
protocol.encryption.handshake.set = allow
|
||||
protocol.encryption.stream.set = prefer
|
||||
|
||||
# Limits for file handle resources, this is optimized for
|
||||
# an `ulimit` of 1024 (a common default). You MUST leave
|
||||
|
||||
@@ -72,7 +72,8 @@ rc.throttle.min_peers.seed = 30
|
||||
rc.throttle.max_peers.seed = 80
|
||||
rc.trackers.numwant = 80
|
||||
|
||||
rc.protocol.encryption.set('allow_incoming', 'try_outgoing', 'enable_retry')
|
||||
rc.protocol.encryption.handshake.set('allow')
|
||||
rc.protocol.encryption.stream.set('prefer')
|
||||
|
||||
-- Limits for file handle resources, this is optimized for
|
||||
-- an `ulimit` of 1024 (a common default). You MUST leave
|
||||
|
||||
@@ -12,7 +12,7 @@ echo "Client version: " `xmlrpc2scgi.py -p scgi://127.0.0.1:${PORT_NUMBER} syste
|
||||
echo
|
||||
echo "Generated by 'rtorrent/doc/scripts/print_option_string.sh' on `date -u`."
|
||||
|
||||
for i in strings.choke_heuristics strings.choke_heuristics.upload strings.choke_heuristics.download strings.connection_type strings.encryption strings.ip_filter strings.ip_tos strings.log_group strings.tracker_event strings.tracker_mode; do
|
||||
for i in strings.choke_heuristics strings.choke_heuristics.upload strings.choke_heuristics.download strings.connection_type strings.encryption.handshake strings.encryption.stream strings.ip_filter strings.ip_tos strings.log_group strings.tracker_event strings.tracker_mode; do
|
||||
echo
|
||||
echo $i
|
||||
echo `echo $i | tr 'a-z_.' '-'`
|
||||
|
||||
@@ -188,6 +188,8 @@ libsub_root_a_SOURCES = \
|
||||
command_local.cc \
|
||||
command_logging.cc \
|
||||
command_network.cc \
|
||||
encryption_config.cc \
|
||||
encryption_config.h \
|
||||
command_peer.cc \
|
||||
command_throttle.cc \
|
||||
command_tracker.cc \
|
||||
|
||||
@@ -974,7 +974,6 @@ initialize_command_download() {
|
||||
rpc::rpc.mark_safe("d.size_pex");
|
||||
rpc::rpc.mark_safe("d.completed_bytes");
|
||||
rpc::rpc.mark_safe("d.complete");
|
||||
rpc::rpc.mark_safe("d.timestamp.started");
|
||||
rpc::rpc.mark_safe("d.timestamp.finished");
|
||||
rpc::rpc.mark_safe("d.bytes_done");
|
||||
rpc::rpc.mark_safe("d.peers_accounted");
|
||||
|
||||
+13
-17
@@ -444,20 +444,17 @@ initialize_command_dynamic() {
|
||||
|
||||
CMD2_ANY ("catch", std::bind(&cmd_catch, std::placeholders::_1, std::placeholders::_2));
|
||||
|
||||
CMD2_ANY_STRING ("enum.log_group", [](auto, const auto& str) { return torrent::option_find_string_str(torrent::OPTION_LOG_GROUP, str); });
|
||||
|
||||
CMD2_ANY ("strings.choke_heuristics", [](auto, auto) { return torrent::option_list_strings(torrent::OPTION_CHOKE_HEURISTICS); });
|
||||
CMD2_ANY ("strings.choke_heuristics.upload", [](auto, auto) { return torrent::option_list_strings(torrent::OPTION_CHOKE_HEURISTICS_UPLOAD); });
|
||||
CMD2_ANY ("strings.choke_heuristics.download", [](auto, auto) { return torrent::option_list_strings(torrent::OPTION_CHOKE_HEURISTICS_DOWNLOAD); });
|
||||
CMD2_ANY ("strings.connection_type", [](auto, auto) { return torrent::option_list_strings(torrent::OPTION_CONNECTION_TYPE); });
|
||||
CMD2_ANY ("strings.encryption", [](auto, auto) { return torrent::Object::create_list(); });
|
||||
CMD2_ANY ("strings.encryption.handshake", [](auto, auto) { return torrent::option_list_strings(torrent::OPTION_ENCRYPTION_HANDSHAKE); });
|
||||
CMD2_ANY ("strings.encryption.stream", [](auto, auto) { return torrent::option_list_strings(torrent::OPTION_ENCRYPTION_STREAM); });
|
||||
CMD2_ANY ("strings.ip_filter", [](auto, auto) { return torrent::option_list_strings(torrent::OPTION_IP_FILTER); });
|
||||
CMD2_ANY ("strings.ip_tos", [](auto, auto) { return torrent::option_list_strings(torrent::OPTION_IP_TOS); });
|
||||
CMD2_ANY ("strings.log_group", [](auto, auto) { return torrent::option_list_strings(torrent::OPTION_LOG_GROUP); });
|
||||
CMD2_ANY ("strings.tracker_event", [](auto, auto) { return torrent::option_list_strings(torrent::OPTION_TRACKER_EVENT); });
|
||||
CMD2_ANY ("strings.tracker_mode", [](auto, auto) { return torrent::option_list_strings(torrent::OPTION_TRACKER_MODE); });
|
||||
CMD2_ANY ("strings.choke_heuristics", std::bind(&torrent::option_list_strings, torrent::OPTION_CHOKE_HEURISTICS));
|
||||
CMD2_ANY ("strings.choke_heuristics.upload", std::bind(&torrent::option_list_strings, torrent::OPTION_CHOKE_HEURISTICS_UPLOAD));
|
||||
CMD2_ANY ("strings.choke_heuristics.download", std::bind(&torrent::option_list_strings, torrent::OPTION_CHOKE_HEURISTICS_DOWNLOAD));
|
||||
CMD2_ANY ("strings.connection_type", std::bind(&torrent::option_list_strings, torrent::OPTION_CONNECTION_TYPE));
|
||||
CMD2_ANY ("strings.encryption.handshake", std::bind(&torrent::option_list_strings, torrent::OPTION_ENCRYPTION_MODE));
|
||||
CMD2_ANY ("strings.encryption.stream", std::bind(&torrent::option_list_strings, torrent::OPTION_ENCRYPTION_MODE));
|
||||
CMD2_ANY ("strings.ip_filter", std::bind(&torrent::option_list_strings, torrent::OPTION_IP_FILTER));
|
||||
CMD2_ANY ("strings.ip_tos", std::bind(&torrent::option_list_strings, torrent::OPTION_IP_TOS));
|
||||
CMD2_ANY ("strings.log_group", std::bind(&torrent::option_list_strings, torrent::OPTION_LOG_GROUP));
|
||||
CMD2_ANY ("strings.tracker_event", std::bind(&torrent::option_list_strings, torrent::OPTION_TRACKER_EVENT));
|
||||
CMD2_ANY ("strings.tracker_mode", std::bind(&torrent::option_list_strings, torrent::OPTION_TRACKER_MODE));
|
||||
// clang-format on
|
||||
|
||||
#ifdef HAVE_XMLRPC_TINYXML2
|
||||
@@ -472,13 +469,12 @@ initialize_command_dynamic() {
|
||||
rpc::rpc.mark_safe("method.rlookup");
|
||||
rpc::rpc.mark_safe("catch");
|
||||
|
||||
rpc::rpc.mark_safe("enum.log_group");
|
||||
|
||||
rpc::rpc.mark_safe("strings.choke_heuristics");
|
||||
rpc::rpc.mark_safe("strings.choke_heuristics.upload");
|
||||
rpc::rpc.mark_safe("strings.choke_heuristics.download");
|
||||
rpc::rpc.mark_safe("strings.connection_type");
|
||||
rpc::rpc.mark_safe("strings.encryption");
|
||||
rpc::rpc.mark_safe("strings.encryption.handshake");
|
||||
rpc::rpc.mark_safe("strings.encryption.stream");
|
||||
rpc::rpc.mark_safe("strings.ip_filter");
|
||||
rpc::rpc.mark_safe("strings.ip_tos");
|
||||
rpc::rpc.mark_safe("strings.log_group");
|
||||
|
||||
@@ -117,7 +117,7 @@ group_insert(const torrent::Object::list_type& args) {
|
||||
rpc::commands.call("method.insert", rpc::create_object_list("group." + name + ".ratio.enable", "simple",
|
||||
"schedule=group." + name + ".ratio,5,60,on_ratio=" + name));
|
||||
rpc::commands.call("method.insert", rpc::create_object_list("group." + name + ".ratio.disable", "simple",
|
||||
"schedule.remove=group." + name + ".ratio"));
|
||||
"schedule_remove=group." + name + ".ratio"));
|
||||
rpc::commands.call("method.insert", rpc::create_object_list("group." + name + ".ratio.command", "simple",
|
||||
"d.try_close= ;d.ignore_commands.set=1"));
|
||||
rpc::commands.call("method.insert", rpc::create_object_list("group." + name + ".view", "string", view));
|
||||
@@ -190,6 +190,10 @@ initialize_command_local() {
|
||||
core::DownloadList* dList = control->core()->download_list();
|
||||
torrent::FileManager* fileManager = torrent::file_manager();
|
||||
|
||||
if (rpc::call_command_value("method.use_deprecated") == 1) {
|
||||
CMD_ANY_LIST ("file.append", std::bind(&cmd_file_append, std::placeholders::_2));
|
||||
}
|
||||
|
||||
CMD_ANY ("system.hostname", std::bind(&system_hostname));
|
||||
CMD_ANY ("system.pid", std::bind(&getpid));
|
||||
|
||||
@@ -250,12 +254,12 @@ initialize_command_local() {
|
||||
|
||||
CMD_ANY (category_name + ".size", [category](auto, auto) { return torrent::runtime::socket_manager()->category_managed_size(category); });
|
||||
CMD_ANY (category_name + ".max_size", [category](auto, auto) { return torrent::runtime::socket_manager()->category_max_size(category); });
|
||||
CMD_ANY (category_name + ".min_alloc", [category](auto, auto) { return torrent::runtime::socket_manager()->category_min_allocation(category); });
|
||||
CMD_ANY (category_name + ".max_alloc", [category](auto, auto) { return torrent::runtime::socket_manager()->category_max_allocation(category); });
|
||||
|
||||
if (i == 0)
|
||||
continue;
|
||||
|
||||
CMD_ANY (category_name + ".min_alloc", [category](auto, auto) { return torrent::runtime::socket_manager()->category_min_allocation(category); });
|
||||
CMD_ANY (category_name + ".max_alloc", [category](auto, auto) { return torrent::runtime::socket_manager()->category_max_allocation(category); });
|
||||
CMD_ANY_VALUE_V(category_name + ".min_alloc.set", [category](auto, auto& value) { torrent::runtime::socket_manager()->set_category_min_allocation(category, value); });
|
||||
CMD_ANY_VALUE_V(category_name + ".max_alloc.set", [category](auto, auto& value) { torrent::runtime::socket_manager()->set_category_max_allocation(category, value); });
|
||||
}
|
||||
@@ -354,10 +358,6 @@ initialize_command_local() {
|
||||
|
||||
rpc::rpc.mark_safe(category_name + ".size");
|
||||
rpc::rpc.mark_safe(category_name + ".max_size");
|
||||
|
||||
if (i == 0)
|
||||
continue;
|
||||
|
||||
rpc::rpc.mark_safe(category_name + ".min_alloc");
|
||||
rpc::rpc.mark_safe(category_name + ".max_alloc");
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <iterator>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <torrent/data/chunk_utils.h>
|
||||
@@ -16,7 +15,6 @@
|
||||
#include "core/download.h"
|
||||
#include "core/download_list.h"
|
||||
#include "core/manager.h"
|
||||
#include "rpc/parse.h"
|
||||
#include "rpc/parse_commands.h"
|
||||
|
||||
torrent::Object
|
||||
@@ -40,32 +38,6 @@ apply_log_add_output(const torrent::Object::list_type& args) {
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
apply_log_print(const torrent::Object::list_type& args) {
|
||||
if (args.size() < 2)
|
||||
throw torrent::input_error("Invalid number of arguments.");
|
||||
|
||||
torrent::Object::value_type group;
|
||||
|
||||
if (args.front().is_value())
|
||||
group = args.front().as_value();
|
||||
else if (args.front().is_string())
|
||||
group = torrent::option_find_string_str(torrent::OPTION_LOG_GROUP, args.front().as_string());
|
||||
else
|
||||
throw torrent::input_error("Invalid log group.");
|
||||
|
||||
if (group < 0 || group >= torrent::LOG_GROUP_MAX_SIZE)
|
||||
throw torrent::input_error("Invalid log group.");
|
||||
|
||||
std::string message;
|
||||
|
||||
for (auto itr = std::next(args.begin()); itr != args.end(); ++itr)
|
||||
rpc::print_object_std(&message, &*itr, 0);
|
||||
|
||||
torrent::log_groups[group].internal_print(message);
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
// TODO: Deprecated.
|
||||
torrent::Object
|
||||
apply_log(const torrent::Object::string_type& arg, int logType) {
|
||||
@@ -140,7 +112,6 @@ initialize_command_logging() {
|
||||
CMD2_ANY_STRING_V("log.close", std::bind(&torrent::log_close_output_str, std::placeholders::_2));
|
||||
|
||||
CMD2_ANY_LIST ("log.add_output", std::bind(&apply_log_add_output, std::placeholders::_2));
|
||||
CMD2_ANY_LIST ("log.print", std::bind(&apply_log_print, std::placeholders::_2));
|
||||
|
||||
CMD2_ANY_STRING ("log.execute", std::bind(&apply_log, std::placeholders::_2, 0));
|
||||
CMD2_ANY_STRING ("log.vmmap.dump", std::bind(&log_vmmap_dump, std::placeholders::_2));
|
||||
|
||||
+5
-122
@@ -19,6 +19,7 @@
|
||||
#include <torrent/utils/log.h>
|
||||
#include <torrent/utils/option_strings.h>
|
||||
|
||||
#include "encryption_config.h"
|
||||
#include "globals.h"
|
||||
#include "control.h"
|
||||
#include "command_helpers.h"
|
||||
@@ -34,118 +35,6 @@
|
||||
#include <systemd/sd-daemon.h>
|
||||
#endif
|
||||
|
||||
torrent::Object
|
||||
listen_port_range() {
|
||||
auto port_range = torrent::runtime::client_config()->listen_port_range();
|
||||
|
||||
return std::to_string(port_range.first) + "-" + std::to_string(port_range.second);
|
||||
}
|
||||
|
||||
void
|
||||
set_listen_port_range(const std::string& arg) {
|
||||
unsigned int port_first{}, port_last{};
|
||||
|
||||
if (std::sscanf(arg.c_str(), "%i-%i", &port_first, &port_last) != 2)
|
||||
throw torrent::input_error("Invalid port_range argument.");
|
||||
|
||||
if (port_first >= (1 << 16) || port_last >= (1 << 16))
|
||||
throw torrent::input_error("Port range out-of-bounds.");
|
||||
|
||||
torrent::runtime::client_config()->set_listen_port_range(port_first, port_last);
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
get_encryption() {
|
||||
auto encryption_modes = torrent::runtime::network_config()->encryption_modes();
|
||||
|
||||
return torrent::option_to_str_or_throw(torrent::OPTION_ENCRYPTION_HANDSHAKE, encryption_modes.first) + "," +
|
||||
torrent::option_to_str_or_throw(torrent::OPTION_ENCRYPTION_STREAM, encryption_modes.second);
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
get_handshake_encryption() {
|
||||
auto encryption_modes = torrent::runtime::network_config()->encryption_modes();
|
||||
|
||||
return torrent::option_to_str_or_throw(torrent::OPTION_ENCRYPTION_MODE, encryption_modes.first);
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
get_stream_encryption() {
|
||||
auto encryption_modes = torrent::runtime::network_config()->encryption_modes();
|
||||
|
||||
return torrent::option_to_str_or_throw(torrent::OPTION_ENCRYPTION_MODE, encryption_modes.second);
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
apply_obsolete_encryption(const torrent::Object::list_type& args) {
|
||||
torrent::encryption_mode handshake_mode{torrent::ENCRYPTION_MODE_ALLOW};
|
||||
torrent::encryption_mode stream_mode{torrent::ENCRYPTION_MODE_ALLOW};
|
||||
|
||||
for (auto& itr : args) {
|
||||
auto arg = itr.as_string();
|
||||
|
||||
if (arg == "none") {
|
||||
handshake_mode = torrent::ENCRYPTION_MODE_DENY;
|
||||
stream_mode = torrent::ENCRYPTION_MODE_DENY;
|
||||
break;
|
||||
|
||||
} else if (arg == "allow_incoming") {
|
||||
} else if (arg == "try_outgoing") {
|
||||
} else if (arg == "require") {
|
||||
handshake_mode = torrent::ENCRYPTION_MODE_REQUIRE;
|
||||
|
||||
} else if (arg == "require_RC4" || arg == "require_rc4") {
|
||||
handshake_mode = torrent::ENCRYPTION_MODE_REQUIRE;
|
||||
stream_mode = torrent::ENCRYPTION_MODE_REQUIRE;
|
||||
break;
|
||||
|
||||
} else if (arg == "enable_retry") {
|
||||
} else if (arg == "prefer_plaintext") {
|
||||
} else {
|
||||
throw torrent::input_error("Invalid encryption option: '" + arg + "'");
|
||||
}
|
||||
}
|
||||
|
||||
lt_log_print(torrent::LOG_WARN, "Obsolete encryption options used, use 'handshake_{deny,allow,prefer,require}, stream_{deny,allow,prefer,require}' instead.");
|
||||
|
||||
torrent::runtime::network_config()->set_encryption_modes(handshake_mode, stream_mode);
|
||||
return {};
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
apply_encryption(const torrent::Object::list_type& args) {
|
||||
if (args.empty())
|
||||
throw torrent::input_error("No encryption options specified.");
|
||||
|
||||
torrent::encryption_mode encryption_mode, handshake_mode, stream_mode;
|
||||
|
||||
if (args.size() == 1) {
|
||||
try {
|
||||
encryption_mode = static_cast<torrent::encryption_mode>(torrent::option_find_string_str(torrent::OPTION_ENCRYPTION_MODE, args.front().as_string()));
|
||||
|
||||
} catch (torrent::input_error& e) {
|
||||
return apply_obsolete_encryption(args);
|
||||
}
|
||||
|
||||
torrent::runtime::network_config()->set_encryption_modes(encryption_mode, encryption_mode);
|
||||
return {};
|
||||
}
|
||||
|
||||
if (args.size() != 2)
|
||||
return apply_obsolete_encryption(args);
|
||||
|
||||
try {
|
||||
handshake_mode = static_cast<torrent::encryption_mode>(torrent::option_find_string_str(torrent::OPTION_ENCRYPTION_HANDSHAKE, args.front().as_string()));
|
||||
stream_mode = static_cast<torrent::encryption_mode>(torrent::option_find_string_str(torrent::OPTION_ENCRYPTION_STREAM, args.back().as_string()));
|
||||
|
||||
} catch (torrent::input_error& e) {
|
||||
return apply_obsolete_encryption(args);
|
||||
}
|
||||
|
||||
torrent::runtime::network_config()->set_encryption_modes(handshake_mode, stream_mode);
|
||||
return {};
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
apply_tos(const torrent::Object::string_type& arg) {
|
||||
rpc::command_base::value_type value;
|
||||
@@ -325,13 +214,9 @@ initialize_command_network() {
|
||||
CMD_ANY ("network.listen.backlog", [](auto, auto) { return torrent::runtime::network_config()->listen_backlog(); });
|
||||
CMD_ANY_VALUE_V ("network.listen.backlog.set", [](auto, auto& value) { return torrent::runtime::network_config()->set_listen_backlog(value); });
|
||||
|
||||
CMD_ANY ("protocol.pex", [](auto, auto) { return torrent::runtime::client_config()->is_pex_enabled(); });
|
||||
CMD_ANY_VALUE_V ("protocol.pex.set", [](auto, auto& value) { return torrent::runtime::client_config()->set_pex_enabled(value); });
|
||||
CMD_VAR_BOOL ("protocol.pex", true);
|
||||
|
||||
CMD_ANY_LIST ("protocol.encryption", [](auto, auto) { return get_encryption(); });
|
||||
CMD_ANY_LIST ("protocol.encryption.set", [](auto, auto& args) { return apply_encryption(args); });
|
||||
CMD_ANY_LIST ("protocol.encryption.handshake", [](auto, auto) { return get_handshake_encryption(); });
|
||||
CMD_ANY_LIST ("protocol.encryption.stream", [](auto, auto) { return get_stream_encryption(); });
|
||||
encryption_config::initialize_commands();
|
||||
|
||||
CMD_VAR_STRING ("protocol.connection.leech", "leech");
|
||||
CMD_VAR_STRING ("protocol.connection.seed", "seed");
|
||||
@@ -402,10 +287,8 @@ initialize_command_network() {
|
||||
CMD_ANY ("network.xmlrpc.size_limit", [](auto, auto) { return rpc::rpc.size_limit(); });
|
||||
CMD_ANY_VALUE_V ("network.xmlrpc.size_limit.set", [](auto, auto& arg) { return rpc::rpc.set_size_limit(arg); });
|
||||
|
||||
CMD_ANY ("network.rpc.use_xmlrpc", [](auto, auto) { return rpc::rpc.use_xmlrpc(); });
|
||||
CMD_ANY_VALUE_V ("network.rpc.use_xmlrpc.set", [](auto, auto& arg) { return rpc::rpc.set_use_xmlrpc(arg); });
|
||||
CMD_ANY ("network.rpc.use_jsonrpc", [](auto, auto) { return rpc::rpc.use_jsonrpc(); });
|
||||
CMD_ANY_VALUE_V ("network.rpc.use_jsonrpc.set", [](auto, auto& arg) { return rpc::rpc.set_use_jsonrpc(arg); });
|
||||
CMD_VAR_BOOL ("network.rpc.use_xmlrpc", true);
|
||||
CMD_VAR_BOOL ("network.rpc.use_jsonrpc", true);
|
||||
|
||||
CMD_ANY ("network.block.ipv4", [nw_config](auto, auto) { return nw_config->is_block_ipv4(); });
|
||||
CMD_ANY_VALUE_V ("network.block.ipv4.set", [nw_config](auto, auto& value) { return nw_config->set_block_ipv4(value); });
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include <torrent/rate.h>
|
||||
#include <torrent/data/file_utils.h>
|
||||
#include <torrent/net/http_stack.h>
|
||||
#include <torrent/runtime/client_config.h>
|
||||
#include <torrent/utils/string_manip.h>
|
||||
|
||||
#include "control.h"
|
||||
@@ -272,7 +271,7 @@ DownloadFactory::receive_success() {
|
||||
if (!m_session && m_variables["tied_to_file"].as_value())
|
||||
rpc::call_command("d.tied_to_file.set", m_uri.empty() ? m_variables["tied_file"] : m_uri, rpc::make_target(download));
|
||||
|
||||
rpc::call_command("d.peer_exchange.set", torrent::runtime::client_config()->is_pex_enabled(), rpc::make_target(download));
|
||||
rpc::call_command("d.peer_exchange.set", rpc::call_command_value("protocol.pex"), rpc::make_target(download));
|
||||
|
||||
torrent::resume_load_addresses(*download->download(), resumeObject);
|
||||
torrent::resume_load_file_priorities(*download->download(), resumeObject);
|
||||
|
||||
@@ -16,6 +16,21 @@
|
||||
|
||||
namespace display {
|
||||
|
||||
namespace {
|
||||
|
||||
char
|
||||
connection_type_char(const torrent::Peer* p) {
|
||||
if (p->is_encrypted())
|
||||
return p->is_incoming() ? 'R' : 'L';
|
||||
|
||||
if (p->is_obfuscated())
|
||||
return p->is_incoming() ? 'H' : 'h';
|
||||
|
||||
return p->is_incoming() ? 'r' : 'l';
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
WindowPeerList::WindowPeerList(core::Download* d, PList* l, PList::iterator* f) :
|
||||
Window(new Canvas, 0, 0, 0, extent_full, extent_full),
|
||||
m_download(d),
|
||||
@@ -35,6 +50,7 @@ WindowPeerList::redraw() {
|
||||
m_canvas->print(x, y, "UP"); x += 7;
|
||||
m_canvas->print(x, y, "DOWN"); x += 7;
|
||||
m_canvas->print(x, y, "PEER"); x += 7;
|
||||
// CT: R/H/r or L/h/l (RC4 / handshake-only / plain) + peer type (u/p/ )
|
||||
m_canvas->print(x, y, "CT/RE/LO"); x += 10;
|
||||
m_canvas->print(x, y, "QS"); x += 6;
|
||||
m_canvas->print(x, y, "DONE"); x += 6;
|
||||
@@ -95,7 +111,7 @@ WindowPeerList::redraw() {
|
||||
peerType = ' ';
|
||||
|
||||
m_canvas->print(x, y, "%c%c/%c%c/%c%c",
|
||||
p->is_encrypted() ? (p->is_incoming() ? 'R' : 'L') : (p->is_incoming() ? 'r' : 'l'),
|
||||
connection_type_char(p),
|
||||
peerType,
|
||||
p->is_down_choked() ? std::tolower(remoteChoked) : remoteChoked,
|
||||
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "encryption_config.h"
|
||||
|
||||
#include <torrent/runtime/network_config.h>
|
||||
#include <torrent/runtime/runtime.h>
|
||||
#include <torrent/utils/option_strings.h>
|
||||
|
||||
#include "command_helpers.h"
|
||||
#include "globals.h"
|
||||
|
||||
namespace encryption_config {
|
||||
namespace {
|
||||
|
||||
Policy
|
||||
current_policy() {
|
||||
return torrent::runtime::network_config()->encryption_policy();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Policy
|
||||
default_policy() {
|
||||
Policy policy;
|
||||
policy.handshake = Policy::Mode::allow;
|
||||
policy.stream = Policy::Mode::allow;
|
||||
return policy;
|
||||
}
|
||||
|
||||
std::string
|
||||
mode_to_string(Policy::Mode value) {
|
||||
return torrent::option_to_str_or_throw(torrent::OPTION_ENCRYPTION_MODE,
|
||||
static_cast<unsigned int>(value));
|
||||
}
|
||||
|
||||
void
|
||||
apply_mode_value(Policy& policy, Policy::Mode Policy::*field, const std::string& value) {
|
||||
policy.*field = static_cast<Policy::Mode>(
|
||||
torrent::option_find_string_str(torrent::OPTION_ENCRYPTION_MODE, value));
|
||||
}
|
||||
|
||||
std::string
|
||||
summary_string(const Policy& policy) {
|
||||
return "handshake=" + mode_to_string(policy.handshake)
|
||||
+ " stream=" + mode_to_string(policy.stream);
|
||||
}
|
||||
|
||||
void
|
||||
apply_policy(const Policy& policy) {
|
||||
torrent::runtime::network_config()->set_encryption_policy(policy);
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
apply_handshake_set(const std::string& value) {
|
||||
Policy policy = current_policy();
|
||||
apply_mode_value(policy, &Policy::handshake, value);
|
||||
apply_policy(policy);
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
apply_stream_set(const std::string& value) {
|
||||
Policy policy = current_policy();
|
||||
apply_mode_value(policy, &Policy::stream, value);
|
||||
apply_policy(policy);
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
void
|
||||
initialize_commands() {
|
||||
apply_policy(default_policy());
|
||||
|
||||
CMD2_ANY("protocol.encryption", [](auto, auto) { return summary_string(current_policy()); });
|
||||
|
||||
CMD2_ANY("protocol.encryption.handshake", [](auto, auto) { return mode_to_string(current_policy().handshake); });
|
||||
CMD2_ANY_STRING_V("protocol.encryption.handshake.set", [](auto, auto& str) { return apply_handshake_set(str); });
|
||||
|
||||
CMD2_ANY("protocol.encryption.stream", [](auto, auto) { return mode_to_string(current_policy().stream); });
|
||||
CMD2_ANY_STRING_V("protocol.encryption.stream.set", [](auto, auto& str) { return apply_stream_set(str); });
|
||||
|
||||
rpc::rpc.mark_safe("protocol.encryption");
|
||||
rpc::rpc.mark_safe("protocol.encryption.handshake");
|
||||
rpc::rpc.mark_safe("protocol.encryption.handshake.set");
|
||||
rpc::rpc.mark_safe("protocol.encryption.stream");
|
||||
rpc::rpc.mark_safe("protocol.encryption.stream.set");
|
||||
}
|
||||
|
||||
} // namespace encryption_config
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifndef RTORRENT_ENCRYPTION_CONFIG_H
|
||||
#define RTORRENT_ENCRYPTION_CONFIG_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include <torrent/runtime/encryption_policy.h>
|
||||
#include <torrent/object.h>
|
||||
|
||||
namespace encryption_config {
|
||||
|
||||
using Policy = torrent::EncryptionPolicy;
|
||||
|
||||
Policy default_policy();
|
||||
|
||||
std::string mode_to_string(Policy::Mode value);
|
||||
void apply_mode_value(Policy& policy, Policy::Mode Policy::*field, const std::string& value);
|
||||
|
||||
std::string summary_string(const Policy& policy);
|
||||
|
||||
void apply_policy(const Policy& policy);
|
||||
torrent::Object apply_handshake_set(const std::string& value);
|
||||
torrent::Object apply_stream_set(const std::string& value);
|
||||
|
||||
void initialize_commands();
|
||||
|
||||
} // namespace encryption_config
|
||||
|
||||
#endif
|
||||
@@ -2,11 +2,12 @@
|
||||
#define RTORRENT_INPUT_INPUT_EVENT_H
|
||||
|
||||
#include <functional>
|
||||
#include <torrent/system/event.h>
|
||||
|
||||
#include <torrent/event.h>
|
||||
|
||||
namespace input {
|
||||
|
||||
class InputEvent : public torrent::system::Event {
|
||||
class InputEvent : public torrent::Event {
|
||||
public:
|
||||
typedef std::function<void (int)> slot_int;
|
||||
|
||||
|
||||
+7
-5
@@ -301,6 +301,9 @@ main(int argc, char** argv) {
|
||||
"schedule = low_diskspace,5,60,((close_low_diskspace,500M))\n"
|
||||
"schedule = prune_file_status,3600,86400,((system.file_status_cache.prune))\n"
|
||||
|
||||
"protocol.encryption.handshake.set=allow\n"
|
||||
"protocol.encryption.stream.set=allow\n"
|
||||
|
||||
"ui.color.focus.set=reverse\n"
|
||||
);
|
||||
|
||||
@@ -319,8 +322,6 @@ main(int argc, char** argv) {
|
||||
CMD_REDIRECT("ratio.max.set", "group.seeding.ratio.max.set");
|
||||
CMD_REDIRECT("ratio.upload.set", "group.seeding.ratio.upload.set");
|
||||
|
||||
CMD_REDIRECT("encryption", "protocol.encryption.set");
|
||||
|
||||
CMD_REDIRECT("check_hash", "pieces.hash.on_completion.set");
|
||||
|
||||
CMD_REDIRECT("connection_leech", "protocol.connection.leech.set");
|
||||
@@ -344,9 +345,8 @@ main(int argc, char** argv) {
|
||||
CMD_REDIRECT("directory", "directory.default.set");
|
||||
CMD_REDIRECT("session", "session.path.set");
|
||||
|
||||
CMD_REDIRECT_NO_EXPORT("port_range", "network.listen.port.range.set");
|
||||
CMD_REDIRECT_NO_EXPORT("scgi_port", "network.scgi.open_port");
|
||||
CMD_REDIRECT_NO_EXPORT("scgi_local", "network.scgi.open_local");
|
||||
CMD_REDIRECT("scgi_port", "network.scgi.open_port");
|
||||
CMD_REDIRECT("scgi_local", "network.scgi.open_local");
|
||||
|
||||
CMD_REDIRECT("to_gm_time", "convert.gm_time");
|
||||
CMD_REDIRECT("to_gm_date", "convert.gm_date");
|
||||
@@ -390,6 +390,8 @@ main(int argc, char** argv) {
|
||||
CMD_REDIRECT("schedule2", "schedule");
|
||||
CMD_REDIRECT("schedule_remove2", "schedule.remove");
|
||||
|
||||
// TODO: Remove file.append when cleaning these up.
|
||||
|
||||
CMD_REDIRECT("bind", "network.bind_address.set");
|
||||
CMD_REDIRECT("ip", "network.local_address.set");
|
||||
CMD_REDIRECT("port_range", "network.port_range.set");
|
||||
|
||||
+37
-6
@@ -113,20 +113,25 @@ bool
|
||||
RpcManager::process(RPCType type, const char* in_buffer, uint32_t length, slot_response_callback callback) {
|
||||
switch (type) {
|
||||
case RPCType::XML:
|
||||
if (!m_xmlrpc.is_valid() || !m_use_xmlrpc) {
|
||||
// TODO: 'network.rpc.use_xmlrpc' should be a bool in RpcManager, not a command variable.
|
||||
if (m_xmlrpc.is_valid() && rpc::call_command_value("network.rpc.use_xmlrpc")) {
|
||||
return m_xmlrpc.process(in_buffer, length, callback);
|
||||
|
||||
} else {
|
||||
const std::string response = "<?xml version=\"1.0\"?><methodResponse><fault><value><struct><member><name>faultCode</name><value><i8>-501</i8></value></member><member><name>faultString</name><value><string>XML-RPC not supported</string></value></member></struct></value></fault></methodResponse>";
|
||||
return callback(response.c_str(), response.size());
|
||||
}
|
||||
|
||||
return m_xmlrpc.process(in_buffer, length, callback);
|
||||
break;
|
||||
|
||||
case RPCType::JSON:
|
||||
if (!m_use_jsonrpc) {
|
||||
if (rpc::call_command_value("network.rpc.use_jsonrpc")) {
|
||||
return m_jsonrpc.process(in_buffer, length, callback);
|
||||
|
||||
} else {
|
||||
const std::string response = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32601,\"message\":\"JSON-RPC not supported\"},\"id\":null}";
|
||||
return callback(response.c_str(), response.size());
|
||||
}
|
||||
|
||||
return m_jsonrpc.process(in_buffer, length, callback);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw torrent::input_error("invalid parameters: unknown RPC type");
|
||||
@@ -167,6 +172,32 @@ RpcManager::cleanup() {
|
||||
m_jsonrpc.cleanup();
|
||||
}
|
||||
|
||||
bool
|
||||
RpcManager::is_type_enabled(RPCType type) const {
|
||||
switch (type) {
|
||||
case RPCType::XML:
|
||||
return m_is_xmlrpc_enabled;
|
||||
case RPCType::JSON:
|
||||
return m_is_jsonrpc_enabled;
|
||||
default:
|
||||
throw torrent::input_error("invalid parameters: unknown RPC type");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RpcManager::set_type_enabled(RPCType type, bool enabled) {
|
||||
switch (type) {
|
||||
case RPCType::XML:
|
||||
m_is_xmlrpc_enabled = enabled;
|
||||
break;
|
||||
case RPCType::JSON:
|
||||
m_is_jsonrpc_enabled = enabled;
|
||||
break;
|
||||
default:
|
||||
throw torrent::input_error("invalid parameters: unknown RPC type");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RpcManager::insert_command(const char* name, const char* parm, const char* doc) {
|
||||
m_xmlrpc.insert_command(name, parm, doc);
|
||||
|
||||
+4
-13
@@ -67,11 +67,8 @@ public:
|
||||
int dialect() { return m_xmlrpc.dialect(); }
|
||||
void set_dialect(int dialect) { m_xmlrpc.set_dialect(dialect); }
|
||||
|
||||
bool use_xmlrpc() const;
|
||||
void set_use_xmlrpc(bool v);
|
||||
|
||||
bool use_jsonrpc() const;
|
||||
void set_use_jsonrpc(bool v);
|
||||
bool is_type_enabled(RPCType type) const;
|
||||
void set_type_enabled(RPCType type, bool enabled);
|
||||
|
||||
bool process(RPCType type, const char* in_buffer, uint32_t length, slot_response_callback callback);
|
||||
bool process_untrusted(RPCType type, const char* in_buffer, uint32_t length, slot_response_callback callback);
|
||||
@@ -105,9 +102,8 @@ private:
|
||||
JsonRpc m_jsonrpc;
|
||||
|
||||
bool m_handlers_initialized{};
|
||||
|
||||
bool m_use_jsonrpc{true};
|
||||
bool m_use_xmlrpc{true};
|
||||
bool m_is_jsonrpc_enabled{true};
|
||||
bool m_is_xmlrpc_enabled{true};
|
||||
|
||||
std::atomic<bool> m_scgi_allow_compression{true};
|
||||
std::atomic<unsigned int> m_scgi_min_compress_size{1000};
|
||||
@@ -120,11 +116,6 @@ private:
|
||||
|
||||
extern RpcManager rpc;
|
||||
|
||||
inline bool RpcManager::use_xmlrpc() const { return m_use_xmlrpc; }
|
||||
inline void RpcManager::set_use_xmlrpc(bool v) { m_use_xmlrpc = v; }
|
||||
inline bool RpcManager::use_jsonrpc() const { return m_use_jsonrpc; }
|
||||
inline void RpcManager::set_use_jsonrpc(bool v) { m_use_jsonrpc = v; }
|
||||
|
||||
} // namespace rpc
|
||||
|
||||
#endif
|
||||
|
||||
+2
-2
@@ -3,13 +3,13 @@
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <torrent/system/event.h>
|
||||
#include <torrent/event.h>
|
||||
|
||||
#include "rpc/scgi_task.h"
|
||||
|
||||
namespace rpc {
|
||||
|
||||
class SCgi : public torrent::system::Event {
|
||||
class SCgi : public torrent::Event {
|
||||
public:
|
||||
static const int max_tasks = 100;
|
||||
|
||||
|
||||
+2
-2
@@ -4,13 +4,13 @@
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
#include <torrent/system/event.h>
|
||||
#include <torrent/event.h>
|
||||
|
||||
namespace rpc {
|
||||
|
||||
class SCgi;
|
||||
|
||||
class SCgiTask : public torrent::system::Event {
|
||||
class SCgiTask : public torrent::Event {
|
||||
public:
|
||||
static constexpr int default_buffer_size = 8191;
|
||||
static constexpr int max_header_size = 2000;
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ parse_main_options(int argc, char** argv) {
|
||||
optionParser.insert_option('b', [](auto& arg) { rpc::call_command_set_string("network.bind_address.set", arg); });
|
||||
optionParser.insert_option('d', [](auto& arg) { rpc::call_command_set_string("directory.default.set", arg); });
|
||||
optionParser.insert_option('i', [](auto& arg) { rpc::call_command_set_string("ip", arg); });
|
||||
optionParser.insert_option('p', [](auto& arg) { rpc::call_command_set_string("network.listen.port.range.set", arg); });
|
||||
optionParser.insert_option('p', [](auto& arg) { rpc::call_command_set_string("network.port_range.set", arg); });
|
||||
optionParser.insert_option('s', [](auto& arg) { rpc::call_command_set_string("session", arg); });
|
||||
|
||||
optionParser.insert_option('O', [](auto& arg) { rpc::parse_command_single_std(arg); });
|
||||
|
||||
@@ -111,7 +111,7 @@ ElementPeerList::create_info() {
|
||||
element->push_column("Client:", te_command("p.client_version="));
|
||||
element->push_column("Options:", te_command("p.options_str="));
|
||||
element->push_column("Connected:", te_command("if=$p.is_incoming=,incoming,outgoing"));
|
||||
element->push_column("Encrypted:", te_command("if=$p.is_encrypted=,yes,$p.is_obfuscated=,handshake,no"));
|
||||
element->push_column("Encrypted:", te_command("if=$p.is_encrypted=,yes,$if=$p.is_obfuscated=\\,handshake\\,no"));
|
||||
|
||||
element->push_back("");
|
||||
element->push_column("Snubbed:", te_command("if=$p.is_snubbed=,yes,no"));
|
||||
|
||||
+2
-2
@@ -49,8 +49,8 @@ rtorrent_Test_Rpc_SOURCES = $(rtorrent_Test_Common) \
|
||||
rtorrent_Test_Src_SOURCES = $(rtorrent_Test_Common) \
|
||||
src/test_command_dynamic.cc \
|
||||
src/test_command_dynamic.h \
|
||||
src/test_command_local.cc \
|
||||
src/test_command_local.h \
|
||||
src/test_encryption_config.cc \
|
||||
src/test_encryption_config.h \
|
||||
src/test_watch_ready_queue.cc \
|
||||
src/test_watch_ready_queue.h
|
||||
|
||||
|
||||
@@ -2,10 +2,9 @@
|
||||
#define LIBTORRENT_HELPERS_MOCK_COMPARE_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <type_traits>
|
||||
#include <torrent/event.h>
|
||||
#include <torrent/net/socket_address.h>
|
||||
#include <torrent/system/event.h>
|
||||
|
||||
// Compare arguments to mock functions with what is expected. The lhs
|
||||
// are the expected arguments, rhs are the ones called with.
|
||||
@@ -14,13 +13,13 @@ template <typename Arg>
|
||||
inline bool mock_compare_arg(Arg lhs, Arg rhs) { return lhs == rhs; }
|
||||
|
||||
template <int I, typename A, typename... Args>
|
||||
std::enable_if_t<I == 1, int>
|
||||
typename std::enable_if<I == 1, int>::type
|
||||
mock_compare_tuple(const std::tuple<A, Args...>& lhs, const std::tuple<Args...>& rhs) {
|
||||
return mock_compare_arg(std::get<I>(lhs), std::get<I - 1>(rhs)) ? 0 : 1;
|
||||
}
|
||||
|
||||
template <int I, typename A, typename... Args>
|
||||
std::enable_if_t<1 < I, int>
|
||||
typename std::enable_if<1 < I, int>::type
|
||||
mock_compare_tuple(const std::tuple<A, Args...>& lhs, const std::tuple<Args...>& rhs) {
|
||||
auto res = mock_compare_tuple<I - 1>(lhs, rhs);
|
||||
|
||||
@@ -71,37 +70,24 @@ void mock_compare_add(T* v) {
|
||||
// Specialize:
|
||||
//
|
||||
|
||||
constexpr int mock_compare_gt_two_int = -0xFD30;
|
||||
|
||||
template <>
|
||||
inline bool mock_compare_arg<int>(int lhs, int rhs) {
|
||||
if (lhs == mock_compare_gt_two_int)
|
||||
return rhs > 2;
|
||||
if (rhs == mock_compare_gt_two_int)
|
||||
return lhs > 2;
|
||||
|
||||
return lhs == rhs;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool mock_compare_arg<sockaddr*>(sockaddr* lhs, sockaddr* rhs) {
|
||||
return lhs != nullptr && rhs != nullptr && torrent::sa_equal(lhs, rhs);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool mock_compare_arg<const sockaddr*>(const sockaddr* lhs, const sockaddr* rhs) {
|
||||
return lhs != nullptr && rhs != nullptr && torrent::sa_equal(lhs, rhs);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool mock_compare_arg<torrent::system::Event*>(torrent::system::Event* lhs, torrent::system::Event* rhs) {
|
||||
if (mock_compare_map<torrent::system::Event>::is_key(lhs)) {
|
||||
if (!mock_compare_map<torrent::system::Event>::has_value(rhs)) {
|
||||
mock_compare_map<torrent::system::Event>::values[lhs] = rhs;
|
||||
inline bool mock_compare_arg<torrent::Event*>(torrent::Event* lhs, torrent::Event* rhs) {
|
||||
if (mock_compare_map<torrent::Event>::is_key(lhs)) {
|
||||
if (!mock_compare_map<torrent::Event>::has_value(rhs)) {
|
||||
mock_compare_map<torrent::Event>::values[lhs] = rhs;
|
||||
return true;
|
||||
}
|
||||
|
||||
return mock_compare_map<torrent::system::Event>::has_key(lhs) && mock_compare_map<torrent::system::Event>::get(lhs) == rhs;
|
||||
return mock_compare_map<torrent::Event>::has_key(lhs) && mock_compare_map<torrent::Event>::get(lhs) == rhs;
|
||||
}
|
||||
|
||||
return lhs == rhs;
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "torrent/event.h"
|
||||
#include "torrent/net/socket_address.h"
|
||||
#include "torrent/net/fd.h"
|
||||
#include "torrent/system/event.h"
|
||||
#include "torrent/utils/log.h"
|
||||
#include "torrent/utils/random.h"
|
||||
|
||||
@@ -32,7 +32,7 @@ mock_clear(bool ignore_assert) {
|
||||
MOCK_CLEANUP_MAP(torrent::random_uniform_uint16);
|
||||
MOCK_CLEANUP_MAP(torrent::random_uniform_uint32);
|
||||
|
||||
mock_compare_map<torrent::system::Event>::values.clear();
|
||||
mock_compare_map<torrent::Event>::values.clear();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@@ -55,9 +55,7 @@ mock_redirect_defaults([[maybe_unused]] mock_redirect_flags flags) {
|
||||
|
||||
mock_redirect(torrent::fd__close, std::function<int(int fildes)>([](int fildes) { return ::close(fildes); }));
|
||||
mock_redirect(torrent::fd__fcntl_int, std::function<int(int fildes, int cmd, int arg)>([](int fildes, int cmd, int arg) { return ::fcntl(fildes, cmd, arg); }));
|
||||
mock_redirect(torrent::fd__setsockopt_int, std::function<int(int socket, int level, int option_name, int option_value)>([](int socket, int level, int option_name, int option_value) {
|
||||
return ::setsockopt(socket, level, option_name, &option_value, sizeof(int));
|
||||
}));
|
||||
mock_redirect(torrent::fd__setsockopt_int, std::function<int(int socket, int level, int option_name, int option_value)>([](int socket, int level, int option_name, int option_value) { return ::setsockopt(socket, level, option_name, &option_value, sizeof(int)); }));
|
||||
mock_redirect(torrent::fd__socket, std::function<int(int domain, int type, int protocol)>([](int domain, int type, int protocol) { return ::socket(domain, type, protocol); }));
|
||||
}
|
||||
|
||||
@@ -114,6 +112,69 @@ int fd__socket(int domain, int type, int protocol) {
|
||||
return mock_call<int>(__func__, &torrent::fd__socket, domain, type, protocol);
|
||||
}
|
||||
|
||||
//
|
||||
// Mock functions for 'torrent/common.h':
|
||||
//
|
||||
|
||||
namespace this_thread {
|
||||
|
||||
void event_open(Event* event) {
|
||||
MOCK_LOG("fd:%i type_name:%s", event->file_descriptor(), event->type_name());
|
||||
return mock_call<void>(__func__, &torrent::this_thread::event_open, event);
|
||||
}
|
||||
|
||||
void event_open_and_count(Event* event) {
|
||||
MOCK_LOG("fd:%i type_name:%s", event->file_descriptor(), event->type_name());
|
||||
return mock_call<void>(__func__, &torrent::this_thread::event_open_and_count, event);
|
||||
}
|
||||
|
||||
void event_close_and_count(Event* event) {
|
||||
MOCK_LOG("fd:%i type_name:%s", event->file_descriptor(), event->type_name());
|
||||
return mock_call<void>(__func__, &torrent::this_thread::event_close_and_count, event);
|
||||
}
|
||||
|
||||
void event_closed_and_count(Event* event) {
|
||||
MOCK_LOG("fd:%i type_name:%s", event->file_descriptor(), event->type_name());
|
||||
return mock_call<void>(__func__, &torrent::this_thread::event_closed_and_count, event);
|
||||
}
|
||||
|
||||
void event_insert_read(Event* event) {
|
||||
MOCK_LOG("fd:%i type_name:%s", event->file_descriptor(), event->type_name());
|
||||
return mock_call<void>(__func__, &torrent::this_thread::event_insert_read, event);
|
||||
}
|
||||
|
||||
void event_insert_write(Event* event) {
|
||||
MOCK_LOG("fd:%i type_name:%s", event->file_descriptor(), event->type_name());
|
||||
return mock_call<void>(__func__, &torrent::this_thread::event_insert_write, event);
|
||||
}
|
||||
|
||||
void event_insert_error(Event* event) {
|
||||
MOCK_LOG("fd:%i type_name:%s", event->file_descriptor(), event->type_name());
|
||||
return mock_call<void>(__func__, &torrent::this_thread::event_insert_error, event);
|
||||
}
|
||||
|
||||
void event_remove_read(Event* event) {
|
||||
MOCK_LOG("fd:%i type_name:%s", event->file_descriptor(), event->type_name());
|
||||
return mock_call<void>(__func__, &torrent::this_thread::event_remove_read, event);
|
||||
}
|
||||
|
||||
void event_remove_write(Event* event) {
|
||||
MOCK_LOG("fd:%i type_name:%s", event->file_descriptor(), event->type_name());
|
||||
return mock_call<void>(__func__, &torrent::this_thread::event_remove_write, event);
|
||||
}
|
||||
|
||||
void event_remove_error(Event* event) {
|
||||
MOCK_LOG("fd:%i type_name:%s", event->file_descriptor(), event->type_name());
|
||||
return mock_call<void>(__func__, &torrent::this_thread::event_remove_error, event);
|
||||
}
|
||||
|
||||
void event_remove_and_close(Event* event) {
|
||||
MOCK_LOG("fd:%i type_name:%s", event->file_descriptor(), event->type_name());
|
||||
return mock_call<void>(__func__, &torrent::this_thread::event_remove_and_close, event);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// Mock functions for 'torrent/utils/random.h':
|
||||
//
|
||||
|
||||
@@ -169,3 +169,19 @@ TestParseOptions::test_flag_libtorrent() {
|
||||
|
||||
FLAG_LT_LOG_ASSERT_ERROR("resume_data|rpc_dump");
|
||||
}
|
||||
|
||||
#define FLAGS_LT_IP_TOS_ASSERT(flags, result) \
|
||||
CPPUNIT_ASSERT(rpc::parse_option_flags(flags, std::bind(&torrent::option_find_string_str, torrent::OPTION_IP_TOS, std::placeholders::_1)) == (result))
|
||||
|
||||
#define FLAGS_LT_IP_TOS_ASSERT_ERROR(flags) \
|
||||
ASSERT_CATCH_INPUT_ERROR(rpc::parse_option_flags(flags, std::bind(&torrent::option_find_string_str, torrent::OPTION_IP_TOS, std::placeholders::_1)))
|
||||
|
||||
void
|
||||
TestParseOptions::test_flags_libtorrent() {
|
||||
FLAGS_LT_IP_TOS_ASSERT("throughput", torrent::option_find_string(torrent::OPTION_IP_TOS, "throughput"));
|
||||
FLAGS_LT_IP_TOS_ASSERT("lowdelay | throughput",
|
||||
torrent::option_find_string(torrent::OPTION_IP_TOS, "lowdelay")
|
||||
| torrent::option_find_string(torrent::OPTION_IP_TOS, "throughput"));
|
||||
|
||||
FLAGS_LT_IP_TOS_ASSERT_ERROR("throughput_");
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ class TestParseOptions : public test_fixture {
|
||||
CPPUNIT_TEST(test_flags_print_flags);
|
||||
|
||||
CPPUNIT_TEST(test_flag_libtorrent);
|
||||
CPPUNIT_TEST(test_flags_libtorrent);
|
||||
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
@@ -29,4 +30,5 @@ public:
|
||||
void test_flags_print_flags();
|
||||
|
||||
void test_flag_libtorrent();
|
||||
void test_flags_libtorrent();
|
||||
};
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "test/src/test_command_local.h"
|
||||
|
||||
#include <torrent/torrent.h>
|
||||
#include <torrent/runtime/socket_manager.h>
|
||||
#include <torrent/utils/option_strings.h>
|
||||
|
||||
#include "control.h"
|
||||
#include "globals.h"
|
||||
#include "rpc/parse_commands.h"
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(TestCommandLocal);
|
||||
|
||||
void initialize_command_local();
|
||||
|
||||
void
|
||||
TestCommandLocal::setUp() {
|
||||
torrent::initialize_main_thread();
|
||||
torrent::initialize();
|
||||
|
||||
if (control == nullptr)
|
||||
control = new Control;
|
||||
|
||||
if (!rpc::commands.has("system.sockets.size"))
|
||||
initialize_command_local();
|
||||
}
|
||||
|
||||
void
|
||||
TestCommandLocal::tearDown() {
|
||||
torrent::cleanup();
|
||||
}
|
||||
|
||||
void
|
||||
TestCommandLocal::test_socket_category_commands() {
|
||||
for (uint32_t i = 0; i < torrent::runtime::SocketManager::category_count; ++i) {
|
||||
auto category = static_cast<torrent::runtime::socket_manager_category_t>(i);
|
||||
auto name = "system.sockets." + torrent::option_to_str_or_throw(torrent::OPTION_SOCKET_CATEGORY, i);
|
||||
|
||||
for (const auto suffix : {".size", ".max_size", ".min_alloc", ".max_alloc"})
|
||||
if (rpc::commands.has(name + suffix))
|
||||
CPPUNIT_ASSERT_NO_THROW(rpc::commands.call(name + suffix));
|
||||
|
||||
const bool has_allocation = category != torrent::runtime::category_generic;
|
||||
|
||||
CPPUNIT_ASSERT(rpc::commands.has(name + ".size"));
|
||||
CPPUNIT_ASSERT(rpc::commands.has(name + ".max_size"));
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(has_allocation, rpc::commands.has(name + ".min_alloc"));
|
||||
CPPUNIT_ASSERT_EQUAL(has_allocation, rpc::commands.has(name + ".max_alloc"));
|
||||
CPPUNIT_ASSERT_EQUAL(has_allocation, rpc::commands.has(name + ".min_alloc.set"));
|
||||
CPPUNIT_ASSERT_EQUAL(has_allocation, rpc::commands.has(name + ".max_alloc.set"));
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
#include "test/helpers/test_fixture.h"
|
||||
|
||||
class TestCommandLocal : public test_fixture {
|
||||
CPPUNIT_TEST_SUITE(TestCommandLocal);
|
||||
|
||||
CPPUNIT_TEST(test_socket_category_commands);
|
||||
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
public:
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
||||
void test_socket_category_commands();
|
||||
};
|
||||
@@ -0,0 +1,45 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "test/src/test_encryption_config.h"
|
||||
|
||||
#include <torrent/runtime/encryption_policy.h>
|
||||
|
||||
#include "encryption_config.h"
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(TestEncryptionConfig);
|
||||
|
||||
void
|
||||
TestEncryptionConfig::test_default_policy() {
|
||||
const auto policy = encryption_config::default_policy();
|
||||
|
||||
CPPUNIT_ASSERT(policy.handshake == encryption_config::Policy::Mode::allow);
|
||||
CPPUNIT_ASSERT(policy.stream == encryption_config::Policy::Mode::allow);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("handshake=allow stream=allow"),
|
||||
encryption_config::summary_string(policy));
|
||||
}
|
||||
|
||||
void
|
||||
TestEncryptionConfig::test_granular_round_trip() {
|
||||
auto round_trip_handshake = [](const std::string& value) {
|
||||
encryption_config::Policy policy;
|
||||
encryption_config::apply_mode_value(policy, &encryption_config::Policy::handshake, value);
|
||||
return encryption_config::mode_to_string(policy.handshake);
|
||||
};
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("deny"), round_trip_handshake("deny"));
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("allow"), round_trip_handshake("allow"));
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("prefer"), round_trip_handshake("prefer"));
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("require"), round_trip_handshake("require"));
|
||||
|
||||
auto round_trip_stream = [](const std::string& value) {
|
||||
encryption_config::Policy policy;
|
||||
encryption_config::apply_mode_value(policy, &encryption_config::Policy::stream, value);
|
||||
return encryption_config::mode_to_string(policy.stream);
|
||||
};
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("deny"), round_trip_stream("deny"));
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("allow"), round_trip_stream("allow"));
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("prefer"), round_trip_stream("prefer"));
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("require"), round_trip_stream("require"));
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#include "test/helpers/test_fixture.h"
|
||||
|
||||
class TestEncryptionConfig : public test_fixture {
|
||||
CPPUNIT_TEST_SUITE(TestEncryptionConfig);
|
||||
CPPUNIT_TEST(test_default_policy);
|
||||
CPPUNIT_TEST(test_granular_round_trip);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
public:
|
||||
void test_default_policy();
|
||||
void test_granular_round_trip();
|
||||
};
|
||||
Reference in New Issue
Block a user