mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-10-10 16:19:23 +00:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8e5fb72867 | |||
| 880d381839 | |||
| b9782c71f5 | |||
| 2688f27f0a | |||
| 24ce818aaf | |||
| 12f3d6fe8f | |||
| 101ce5924c | |||
| 4bf094b6de | |||
| a84743b008 | |||
| eebfb5f5e5 | |||
| 991ebdabe0 | |||
| 2aaf1cbfd1 | |||
| b5b37a2e07 | |||
| 4831a44879 | |||
| 14c8d2b470 | |||
| 15756ddadc | |||
| e0c0d96aba | |||
| 7fbe54d4dd | |||
| 41209bc14d | |||
| 47eb1432b6 | |||
| d16263701a | |||
| d3f4d18164 | |||
| 6c6d2b9333 | |||
| f79cb257d7 |
+3
-3
@@ -1,6 +1,6 @@
|
|||||||
m4_pattern_allow([PKG_CHECK_EXISTS])
|
m4_pattern_allow([PKG_CHECK_EXISTS])
|
||||||
|
|
||||||
AC_INIT([rtorrent],[0.16.25],[sundell.software@gmail.com])
|
AC_INIT([rtorrent],[0.16.24],[sundell.software@gmail.com])
|
||||||
|
|
||||||
AC_CONFIG_HEADERS([config.h])
|
AC_CONFIG_HEADERS([config.h])
|
||||||
AC_CONFIG_MACRO_DIRS([scripts])
|
AC_CONFIG_MACRO_DIRS([scripts])
|
||||||
@@ -14,7 +14,7 @@ AX_CXX_COMPILE_STDCXX(20, noext, mandatory)
|
|||||||
|
|
||||||
PKG_PROG_PKG_CONFIG
|
PKG_PROG_PKG_CONFIG
|
||||||
|
|
||||||
AC_DEFINE([API_VERSION], [29], [api version])
|
AC_DEFINE([API_VERSION], [28], [api version])
|
||||||
|
|
||||||
RAK_CHECK_CFLAGS
|
RAK_CHECK_CFLAGS
|
||||||
RAK_CHECK_CXXFLAGS
|
RAK_CHECK_CXXFLAGS
|
||||||
@@ -49,7 +49,7 @@ fi
|
|||||||
|
|
||||||
PKG_CHECK_MODULES([CPPUNIT], [cppunit],, [no_cppunit="yes"])
|
PKG_CHECK_MODULES([CPPUNIT], [cppunit],, [no_cppunit="yes"])
|
||||||
PKG_CHECK_MODULES([ZLIB], [zlib])
|
PKG_CHECK_MODULES([ZLIB], [zlib])
|
||||||
PKG_CHECK_MODULES([DEPENDENCIES], [libtorrent >= 0.16.25])
|
PKG_CHECK_MODULES([DEPENDENCIES], [libtorrent >= 0.16.24])
|
||||||
|
|
||||||
AC_LANG_PUSH(C++)
|
AC_LANG_PUSH(C++)
|
||||||
TORRENT_WITH_XMLRPC_C
|
TORRENT_WITH_XMLRPC_C
|
||||||
|
|||||||
+13
-9
@@ -18,8 +18,7 @@ Some control over formatting will be provided at a later date.
|
|||||||
\begin{verbatim}
|
\begin{verbatim}
|
||||||
# log.add_output = "logging event", "log name"
|
# log.add_output = "logging event", "log name"
|
||||||
|
|
||||||
log.add_output = "errors", "rtorrent.log"
|
log.add_output = "info", "rtorrent.log"
|
||||||
log.add_output = "events", "rtorrent.log"
|
|
||||||
|
|
||||||
log.add_output = "dht_all", "tracker.log"
|
log.add_output = "dht_all", "tracker.log"
|
||||||
log.add_output = "tracker_events", "tracker.log"
|
log.add_output = "tracker_events", "tracker.log"
|
||||||
@@ -32,16 +31,21 @@ Each log handle can be added to multiple different logging events.
|
|||||||
\subsection{Logging events}
|
\subsection{Logging events}
|
||||||
|
|
||||||
\begin{verbatim}
|
\begin{verbatim}
|
||||||
"errors"
|
"critical"
|
||||||
"events"
|
"error"
|
||||||
"debug_trace"
|
"warn"
|
||||||
|
"notice"
|
||||||
|
"info"
|
||||||
|
"debug"
|
||||||
\end{verbatim}
|
\end{verbatim}
|
||||||
|
|
||||||
The above events are not cascading, so add both ``errors'' and
|
The above events receive logging events from all the sub-groups
|
||||||
``events'' to an output to receive both.
|
displayed below, and each event also reciving events from the event
|
||||||
|
above in importance.
|
||||||
|
|
||||||
High-volume sub-group events such as ``tracker\_debug'' are not part
|
Thus some high-volume sub-group events such as ``tracker\_debug'' are
|
||||||
of ``debug\_trace''.
|
not part of ``debug'' and every ``warn'' event will receive events
|
||||||
|
from ``error'', ``critical''.
|
||||||
|
|
||||||
\begin{verbatim}
|
\begin{verbatim}
|
||||||
"connection_*"
|
"connection_*"
|
||||||
|
|||||||
@@ -104,8 +104,7 @@ print = (cat, "Logging to ", (cfg.logfile))
|
|||||||
|
|
||||||
log.open_file = "log", (cfg.logfile)
|
log.open_file = "log", (cfg.logfile)
|
||||||
|
|
||||||
log.add_output = "errors", "log"
|
log.add_output = "info", "log"
|
||||||
log.add_output = "events", "log"
|
|
||||||
#log.add_output = "tracker_events", "log"
|
#log.add_output = "tracker_events", "log"
|
||||||
#log.add_output = "tracker_requests", "log"
|
#log.add_output = "tracker_requests", "log"
|
||||||
|
|
||||||
|
|||||||
@@ -135,8 +135,7 @@ rc.schedule2('watch_load', '11', '10', 'load.verbose=(cat, (cfg.watch), "load/*.
|
|||||||
-- Groups = connection_* dht_* peer_* rpc_* storage_* thread_* tracker_* torrent_*
|
-- Groups = connection_* dht_* peer_* rpc_* storage_* thread_* tracker_* torrent_*
|
||||||
rc.print('Logging to '..rc.cfg.logfile())
|
rc.print('Logging to '..rc.cfg.logfile())
|
||||||
rc.log.open_file('log', rc.cfg.logfile())
|
rc.log.open_file('log', rc.cfg.logfile())
|
||||||
rc.log.add_output('errors', 'log')
|
rc.log.add_output('info', 'log')
|
||||||
rc.log.add_output('events', 'log')
|
|
||||||
--rc.log.add_output('tracker_events', 'log')
|
--rc.log.add_output('tracker_events', 'log')
|
||||||
--rc.log.add_output('tracker_requests', 'log')
|
--rc.log.add_output('tracker_requests', 'log')
|
||||||
|
|
||||||
|
|||||||
+17
-31
@@ -107,7 +107,7 @@ apply_d_change_link(core::Download* download, const torrent::Object::list_type&
|
|||||||
switch (changeType) {
|
switch (changeType) {
|
||||||
case 0:
|
case 0:
|
||||||
if (symlink(target.c_str(), link.c_str()) == -1)
|
if (symlink(target.c_str(), link.c_str()) == -1)
|
||||||
lt_log_print(torrent::LOG_TORRENT_DEBUG, "create_link failed: %s", std::strerror(errno));
|
lt_log_print(torrent::LOG_TORRENT_WARN, "create_link failed: %s", std::strerror(errno));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -117,7 +117,7 @@ apply_d_change_link(core::Download* download, const torrent::Object::list_type&
|
|||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
||||||
if (!fileStat.update_link(link) || !fileStat.is_link() || unlink(link.c_str()) == -1)
|
if (!fileStat.update_link(link) || !fileStat.is_link() || unlink(link.c_str()) == -1)
|
||||||
lt_log_print(torrent::LOG_TORRENT_DEBUG, "delete_link failed: %s", std::strerror(errno));
|
lt_log_print(torrent::LOG_TORRENT_WARN, "delete_link failed: %s", std::strerror(errno));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -135,7 +135,7 @@ apply_d_delete_tied(core::Download* download) {
|
|||||||
if (tie.empty())
|
if (tie.empty())
|
||||||
return torrent::Object();
|
return torrent::Object();
|
||||||
|
|
||||||
if (unlink(expand_path(tie).c_str()) == -1)
|
if (::unlink(expand_path(tie).c_str()) == -1)
|
||||||
control->core()->push_log_std("Could not unlink tied file: " + std::string(std::strerror(errno)));
|
control->core()->push_log_std("Could not unlink tied file: " + std::string(std::strerror(errno)));
|
||||||
|
|
||||||
rpc::call_command("d.tied_to_file.set", std::string(), rpc::make_target(download));
|
rpc::call_command("d.tied_to_file.set", std::string(), rpc::make_target(download));
|
||||||
@@ -293,7 +293,7 @@ apply_d_add_peer(core::Download* download, const std::string& arg) {
|
|||||||
// Currently discarding SOCK_STREAM.
|
// Currently discarding SOCK_STREAM.
|
||||||
torrent::this_thread::resolver()->resolve_preferred(callback_id, host, AF_UNSPEC, AF_INET, [download, port](torrent::c_sa_shared_ptr sa, int err) {
|
torrent::this_thread::resolver()->resolve_preferred(callback_id, host, AF_UNSPEC, AF_INET, [download, port](torrent::c_sa_shared_ptr sa, int err) {
|
||||||
if (sa == nullptr) {
|
if (sa == nullptr) {
|
||||||
lt_log_print(torrent::LOG_TORRENT_DEBUG, "could not resolve hostname for added peer: %s", gai_strerror(err));
|
lt_log_print(torrent::LOG_TORRENT_WARN, "could not resolve hostname for added peer: %s", gai_strerror(err));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -334,11 +334,6 @@ f_multicall(core::Download* download, const torrent::Object::list_type& args) {
|
|||||||
|
|
||||||
bool use_regex = true;
|
bool use_regex = true;
|
||||||
|
|
||||||
rpc::preparsed_commands commands([&args](auto& cmds) {
|
|
||||||
for (auto cItr = ++args.begin(); cItr != args.end(); ++cItr)
|
|
||||||
cmds.push_back(rpc::parse_command_object(cItr->as_string()));
|
|
||||||
});
|
|
||||||
|
|
||||||
if (args.front().is_list())
|
if (args.front().is_list())
|
||||||
for (const auto& o : args.front().as_list())
|
for (const auto& o : args.front().as_list())
|
||||||
regex_list.push_back(o.as_string_c());
|
regex_list.push_back(o.as_string_c());
|
||||||
@@ -354,10 +349,10 @@ f_multicall(core::Download* download, const torrent::Object::list_type& args) {
|
|||||||
|
|
||||||
torrent::Object::list_type& row = result.insert(result.end(), torrent::Object::create_list())->as_list();
|
torrent::Object::list_type& row = result.insert(result.end(), torrent::Object::create_list())->as_list();
|
||||||
|
|
||||||
// Defer parsing until a file actually matches the multicall selection.
|
for (torrent::Object::list_const_iterator cItr = ++args.begin(); cItr != args.end(); cItr++) {
|
||||||
commands.prepare_if_needed();
|
const std::string& cmd = cItr->as_string();
|
||||||
for (auto& itr : commands)
|
row.push_back(rpc::parse_command(rpc::make_target(file.get()), cmd.c_str(), cmd.c_str() + cmd.size()).first);
|
||||||
row.push_back(rpc::call_object(itr, rpc::make_target(file.get())));
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return resultRaw;
|
return resultRaw;
|
||||||
@@ -377,11 +372,6 @@ t_multicall(core::Download* download, const torrent::Object::list_type& args) {
|
|||||||
auto result_raw = torrent::Object::create_list();
|
auto result_raw = torrent::Object::create_list();
|
||||||
auto& result = result_raw.as_list();
|
auto& result = result_raw.as_list();
|
||||||
|
|
||||||
rpc::preparsed_commands commands([&args](auto& cmds) {
|
|
||||||
for (auto cItr = ++args.begin(); cItr != args.end(); ++cItr)
|
|
||||||
cmds.push_back(rpc::parse_command_object(cItr->as_string()));
|
|
||||||
});
|
|
||||||
|
|
||||||
for (uint32_t idx = 0, last = download->tracker_list_size(); idx < last; idx++) {
|
for (uint32_t idx = 0, last = download->tracker_list_size(); idx < last; idx++) {
|
||||||
auto& row = result.insert(result.end(), torrent::Object::create_list())->as_list();
|
auto& row = result.insert(result.end(), torrent::Object::create_list())->as_list();
|
||||||
auto tracker = download->tracker_controller().at(idx);
|
auto tracker = download->tracker_controller().at(idx);
|
||||||
@@ -389,10 +379,11 @@ t_multicall(core::Download* download, const torrent::Object::list_type& args) {
|
|||||||
if (!tracker.is_valid())
|
if (!tracker.is_valid())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Do not parse columns when there are no valid tracker targets.
|
for (auto cItr = ++args.begin(); cItr != args.end(); cItr++) {
|
||||||
commands.prepare_if_needed();
|
auto& cmd = cItr->as_string();
|
||||||
for (auto& itr : commands)
|
|
||||||
row.push_back(rpc::call_object(itr, rpc::make_target(&tracker)));
|
row.push_back(rpc::parse_command(rpc::make_target(&tracker), cmd.c_str(), cmd.c_str() + cmd.size()).first);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result_raw;
|
return result_raw;
|
||||||
@@ -414,18 +405,13 @@ p_multicall(core::Download* download, const torrent::Object::list_type& args) {
|
|||||||
auto* connection_list = download->connection_list();
|
auto* connection_list = download->connection_list();
|
||||||
const auto change_counter = connection_list->change_counter();
|
const auto change_counter = connection_list->change_counter();
|
||||||
|
|
||||||
rpc::preparsed_commands commands([&args](auto& cmds) {
|
|
||||||
for (auto cItr = ++args.begin(); cItr != args.end(); ++cItr)
|
|
||||||
cmds.push_back(rpc::parse_command_object(cItr->as_string()));
|
|
||||||
});
|
|
||||||
|
|
||||||
for (const auto& connection : *connection_list) {
|
for (const auto& connection : *connection_list) {
|
||||||
torrent::Object::list_type& row = result.insert(result.end(), torrent::Object::create_list())->as_list();
|
torrent::Object::list_type& row = result.insert(result.end(), torrent::Object::create_list())->as_list();
|
||||||
|
|
||||||
// Prepare only after a peer exists, preserving empty-list laziness.
|
for (auto cItr = ++args.begin(); cItr != args.end(); cItr++) {
|
||||||
commands.prepare_if_needed();
|
const std::string& cmd = cItr->as_string();
|
||||||
for (auto& itr : commands) {
|
|
||||||
row.push_back(rpc::call_object(itr, rpc::make_target(connection)));
|
row.push_back(rpc::parse_command(rpc::make_target(connection), cmd.c_str(), cmd.c_str() + cmd.size()).first);
|
||||||
|
|
||||||
// Erasing a peer frees it and swaps the last element into its place, so
|
// Erasing a peer frees it and swaps the last element into its place, so
|
||||||
// neither this peer nor the iteration survives a change to the list.
|
// neither this peer nor the iteration survives a change to the list.
|
||||||
|
|||||||
@@ -394,7 +394,7 @@ cmd_catch(rpc::target_type target, const torrent::Object& args) {
|
|||||||
try {
|
try {
|
||||||
return rpc::call_object(args, target);
|
return rpc::call_object(args, target);
|
||||||
} catch (torrent::input_error& e) {
|
} catch (torrent::input_error& e) {
|
||||||
lt_log_print(torrent::LOG_ERRORS, "Caught exception: '%s'.", e.what());
|
lt_log_print(torrent::LOG_WARN, "Caught exception: '%s'.", e.what());
|
||||||
return torrent::Object();
|
return torrent::Object();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-13
@@ -169,7 +169,7 @@ void apply_try_import(const std::string& path) { if (!rpc::parse_command_file(pa
|
|||||||
|
|
||||||
torrent::Object
|
torrent::Object
|
||||||
apply_close_low_diskspace(int64_t arg, uint32_t skip_priority) {
|
apply_close_low_diskspace(int64_t arg, uint32_t skip_priority) {
|
||||||
int closed{};
|
bool closed = false;
|
||||||
|
|
||||||
torrent::FileList::cache_list cache;
|
torrent::FileList::cache_list cache;
|
||||||
|
|
||||||
@@ -186,11 +186,11 @@ apply_close_low_diskspace(int64_t arg, uint32_t skip_priority) {
|
|||||||
download->set_hash_failed(true);
|
download->set_hash_failed(true);
|
||||||
download->set_message(std::string("Low diskspace."));
|
download->set_message(std::string("Low diskspace."));
|
||||||
|
|
||||||
closed++;
|
closed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (closed != 0)
|
if (closed)
|
||||||
lt_log_print(torrent::LOG_TORRENT_EVENTS, "closed torrents due to low diskspace : count:%i", closed);
|
lt_log_print(torrent::LOG_TORRENT_ERROR, "Closed torrents due to low diskspace.");
|
||||||
|
|
||||||
return torrent::Object();
|
return torrent::Object();
|
||||||
}
|
}
|
||||||
@@ -247,26 +247,20 @@ d_multicall(const torrent::Object::list_type& args) {
|
|||||||
torrent::Object resultRaw = torrent::Object::create_list();
|
torrent::Object resultRaw = torrent::Object::create_list();
|
||||||
torrent::Object::list_type& result = resultRaw.as_list();
|
torrent::Object::list_type& result = resultRaw.as_list();
|
||||||
|
|
||||||
rpc::preparsed_commands commands([&args](auto& cmds) {
|
|
||||||
for (auto cItr = ++args.begin(); cItr != args.end(); ++cItr)
|
|
||||||
cmds.push_back(rpc::parse_command_object(cItr->as_string()));
|
|
||||||
});
|
|
||||||
|
|
||||||
for (const auto& download : dlist) {
|
for (const auto& download : dlist) {
|
||||||
if (download.use_count() == 1)
|
if (download.use_count() == 1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
torrent::Object::list_type& row = result.insert(result.end(), torrent::Object::create_list())->as_list();
|
torrent::Object::list_type& row = result.insert(result.end(), torrent::Object::create_list())->as_list();
|
||||||
|
|
||||||
// Skip parsing if there are no usable download targets in the view.
|
for (torrent::Object::list_const_iterator cItr = ++args.begin(); cItr != args.end(); cItr++) {
|
||||||
commands.prepare_if_needed();
|
|
||||||
for (auto& itr : commands) {
|
|
||||||
// A command may erase this download, which destroys the torrent object it
|
// A command may erase this download, which destroys the torrent object it
|
||||||
// wraps; the list dropping its reference is what tells us.
|
// wraps; the list dropping its reference is what tells us.
|
||||||
if (download.use_count() == 1)
|
if (download.use_count() == 1)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
row.push_back(rpc::call_object(itr, rpc::make_target(download)));
|
auto& cmd = cItr->as_string();
|
||||||
|
row.push_back(rpc::parse_command(rpc::make_target(download), cmd.c_str(), cmd.c_str() + cmd.size()).first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,9 @@
|
|||||||
// For cg_d_group.
|
// For cg_d_group.
|
||||||
#include "core/download.h"
|
#include "core/download.h"
|
||||||
|
|
||||||
|
#define LT_LOG_SUBSYSTEM(log_fmt, ...) \
|
||||||
|
lt_log_print_subsystem(torrent::LOG_TORRENT_INFO, "choke_queue", log_fmt, __VA_ARGS__);
|
||||||
|
|
||||||
// A hack to allow testing of the new choke_group API without the
|
// A hack to allow testing of the new choke_group API without the
|
||||||
// working parts present.
|
// working parts present.
|
||||||
#define USE_CHOKE_GROUP 0
|
#define USE_CHOKE_GROUP 0
|
||||||
@@ -204,7 +207,7 @@ apply_cg_index_of(const std::string& arg) {
|
|||||||
|
|
||||||
torrent::Object
|
torrent::Object
|
||||||
apply_cg_all_update_balance(bool is_up) {
|
apply_cg_all_update_balance(bool is_up) {
|
||||||
lt_log_print(torrent::LOG_TORRENT_DEBUG, "choke_queue : applying update balance : is_up:%i", (int)is_up);
|
LT_LOG_SUBSYSTEM("apply update balance: hack is_up:%i", (int)is_up);
|
||||||
|
|
||||||
for (const auto& itr : cg_list_hack) {
|
for (const auto& itr : cg_list_hack) {
|
||||||
if (is_up)
|
if (is_up)
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ initialize_command_local() {
|
|||||||
CMD_ANY_VALUE_V ("pieces.sync.timeout.set", [](auto, auto& value) { return torrent::runtime::memory_manager()->set_timeout_sync(value); });
|
CMD_ANY_VALUE_V ("pieces.sync.timeout.set", [](auto, auto& value) { return torrent::runtime::memory_manager()->set_timeout_sync(value); });
|
||||||
CMD_ANY ("pieces.sync.timeout_safe", [](auto, auto) { return 0; });
|
CMD_ANY ("pieces.sync.timeout_safe", [](auto, auto) { return 0; });
|
||||||
CMD_ANY_VALUE_V ("pieces.sync.timeout_safe.set", [](auto, auto) {
|
CMD_ANY_VALUE_V ("pieces.sync.timeout_safe.set", [](auto, auto) {
|
||||||
lt_log_print(torrent::LOG_ERRORS, "pieces.sync.timeout_safe.set is no longer supported and does nothing.");
|
lt_log_print(torrent::LOG_WARN, "pieces.sync.timeout_safe.set is no longer supported and does nothing.");
|
||||||
});
|
});
|
||||||
CMD_ANY ("pieces.sync.queue_size", [](auto, auto) { return torrent::runtime::memory_manager()->sync_queue_block_count(); });
|
CMD_ANY ("pieces.sync.queue_size", [](auto, auto) { return torrent::runtime::memory_manager()->sync_queue_block_count(); });
|
||||||
|
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ apply_obsolete_encryption(const torrent::Object::list_type& args) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lt_log_print(torrent::LOG_ERRORS, "Obsolete encryption options used, use 'handshake_{deny,allow,prefer,require}, stream_{deny,allow,prefer,require}' instead.");
|
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);
|
torrent::runtime::network_config()->set_encryption_modes(handshake_mode, stream_mode);
|
||||||
return {};
|
return {};
|
||||||
|
|||||||
@@ -88,8 +88,6 @@ initialize_command_system() {
|
|||||||
|
|
||||||
CMD_ANY ("system.file_name.replace_slash", [](auto, auto) { return torrent::runtime::client_config()->file_name_replace_slash(); });
|
CMD_ANY ("system.file_name.replace_slash", [](auto, auto) { return torrent::runtime::client_config()->file_name_replace_slash(); });
|
||||||
CMD_ANY_STRING_V("system.file_name.replace_slash.set", [](auto, auto& str) { return torrent::runtime::client_config()->set_file_name_replace_slash(str); });
|
CMD_ANY_STRING_V("system.file_name.replace_slash.set", [](auto, auto& str) { return torrent::runtime::client_config()->set_file_name_replace_slash(str); });
|
||||||
CMD_ANY ("system.file_name.allow_legacy_utf8", [](auto, auto) { return torrent::runtime::client_config()->file_name_allow_legacy_utf8(); });
|
|
||||||
CMD_ANY_VALUE_V ("system.file_name.allow_legacy_utf8.set", [](auto, auto& value) { return torrent::runtime::client_config()->set_file_name_allow_legacy_utf8(value); });
|
|
||||||
|
|
||||||
CMD_ANY ("system.file_status_cache.size", [](auto, auto) { return control->core()->file_status_cache()->size(); });
|
CMD_ANY ("system.file_status_cache.size", [](auto, auto) { return control->core()->file_status_cache()->size(); });
|
||||||
CMD_ANY_V ("system.file_status_cache.prune", [](auto, auto) { return control->core()->file_status_cache()->prune(); });
|
CMD_ANY_V ("system.file_status_cache.prune", [](auto, auto) { return control->core()->file_status_cache()->prune(); });
|
||||||
@@ -169,13 +167,10 @@ initialize_command_system() {
|
|||||||
rpc::rpc.mark_safe("system.time");
|
rpc::rpc.mark_safe("system.time");
|
||||||
rpc::rpc.mark_safe("system.time_seconds");
|
rpc::rpc.mark_safe("system.time_seconds");
|
||||||
rpc::rpc.mark_safe("system.time_usec");
|
rpc::rpc.mark_safe("system.time_usec");
|
||||||
rpc::rpc.mark_safe("system.torrent_name.use_sanitized");
|
|
||||||
rpc::rpc.mark_safe("system.file.allocate");
|
rpc::rpc.mark_safe("system.file.allocate");
|
||||||
rpc::rpc.mark_safe("system.file.max_size");
|
rpc::rpc.mark_safe("system.file.max_size");
|
||||||
rpc::rpc.mark_safe("system.file.split_size");
|
rpc::rpc.mark_safe("system.file.split_size");
|
||||||
rpc::rpc.mark_safe("system.file.split_suffix");
|
rpc::rpc.mark_safe("system.file.split_suffix");
|
||||||
rpc::rpc.mark_safe("system.file_name.replace_slash");
|
|
||||||
rpc::rpc.mark_safe("system.file_name.allow_legacy_utf8");
|
|
||||||
|
|
||||||
rpc::rpc.mark_safe("system.sockets.size");
|
rpc::rpc.mark_safe("system.sockets.size");
|
||||||
rpc::rpc.mark_safe("system.sockets.max_size");
|
rpc::rpc.mark_safe("system.sockets.max_size");
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ initialize_command_tracker() {
|
|||||||
|
|
||||||
CMD2_ANY ("trackers.use_udp", [](auto, auto) { return true; });
|
CMD2_ANY ("trackers.use_udp", [](auto, auto) { return true; });
|
||||||
CMD2_ANY_VALUE_V ("trackers.use_udp.set", [](auto, auto) {
|
CMD2_ANY_VALUE_V ("trackers.use_udp.set", [](auto, auto) {
|
||||||
lt_log_print(torrent::LOG_ERRORS, "trackers.use_udp.set is no longer supported", 0);
|
lt_log_print(torrent::LOG_ERROR, "trackers.use_udp.set is no longer supported", 0);
|
||||||
})
|
})
|
||||||
|
|
||||||
CMD2_ANY_STRING_V ("dht.mode.set", [](auto, auto& str) { return control->dht_manager()->set_mode_by_user(str); });
|
CMD2_ANY_STRING_V ("dht.mode.set", [](auto, auto& str) { return control->dht_manager()->set_mode_by_user(str); });
|
||||||
|
|||||||
@@ -21,10 +21,10 @@
|
|||||||
#include "session/session_manager.h"
|
#include "session/session_manager.h"
|
||||||
|
|
||||||
#define LT_LOG(log_fmt, ...) \
|
#define LT_LOG(log_fmt, ...) \
|
||||||
lt_log_print(torrent::LOG_DHT_CONTROLLER, "dht_manager : " log_fmt, __VA_ARGS__);
|
lt_log_print_subsystem(torrent::LOG_DHT_CONTROLLER, "dht_manager", log_fmt, __VA_ARGS__);
|
||||||
|
|
||||||
#define LT_LOG_ERROR(log_fmt, ...) \
|
#define LT_LOG_ERROR(log_fmt, ...) \
|
||||||
lt_log_print(torrent::LOG_DHT_ERROR, "dht_manager : " log_fmt, __VA_ARGS__);
|
lt_log_print_subsystem(torrent::LOG_DHT_ERROR, "dht_manager", log_fmt, __VA_ARGS__);
|
||||||
|
|
||||||
namespace core {
|
namespace core {
|
||||||
|
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ DownloadFactory::receive_success() {
|
|||||||
libtorrent_resume_object = download_factory_load_stream((expand_path(m_uri) + ".libtorrent_resume").c_str(), &session_invalid);
|
libtorrent_resume_object = download_factory_load_stream((expand_path(m_uri) + ".libtorrent_resume").c_str(), &session_invalid);
|
||||||
|
|
||||||
if (session_invalid)
|
if (session_invalid)
|
||||||
lt_log_print(torrent::LOG_ERRORS, "%s: %s", session_invalid_message, m_uri.c_str());
|
lt_log_print(torrent::LOG_ERROR, "%s: %s", session_invalid_message, m_uri.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t tracker_key;
|
uint32_t tracker_key;
|
||||||
@@ -313,7 +313,7 @@ DownloadFactory::receive_success() {
|
|||||||
} catch (const torrent::input_error& e) {
|
} catch (const torrent::input_error& e) {
|
||||||
std::string msg = std::string(session_invalid_message) + ": " + e.what();
|
std::string msg = std::string(session_invalid_message) + ": " + e.what();
|
||||||
|
|
||||||
lt_log_print(torrent::LOG_ERRORS, "%s: %s", msg.c_str(), m_uri.c_str());
|
lt_log_print(torrent::LOG_ERROR, "%s: %s", msg.c_str(), m_uri.c_str());
|
||||||
|
|
||||||
if (m_printLog)
|
if (m_printLog)
|
||||||
m_manager->push_log_std(msg + ": \"" + m_uri + "\"");
|
m_manager->push_log_std(msg + ": \"" + m_uri + "\"");
|
||||||
|
|||||||
+27
-37
@@ -29,11 +29,6 @@
|
|||||||
#include "session/session_manager.h"
|
#include "session/session_manager.h"
|
||||||
#include "ui/root.h"
|
#include "ui/root.h"
|
||||||
|
|
||||||
#define LT_LOG_DOWNLOAD_DEBUG(log_fmt, ...) \
|
|
||||||
lt_log_print_hash(torrent::LOG_TORRENT_DEBUG, download->info()->hash(), "download_list : " log_fmt, __VA_ARGS__);
|
|
||||||
#define LT_LOG_DOWNLOAD_EVENTS(log_fmt, ...) \
|
|
||||||
lt_log_print_info(torrent::LOG_TORRENT_EVENTS, download->info(), "download_list : " log_fmt, __VA_ARGS__);
|
|
||||||
|
|
||||||
#define DL_TRIGGER_EVENT(download, event_name) \
|
#define DL_TRIGGER_EVENT(download, event_name) \
|
||||||
rpc::commands.call_catch(event_name, rpc::make_target(download), torrent::Object(), "Event '" event_name "' failed: ");
|
rpc::commands.call_catch(event_name, rpc::make_target(download), torrent::Object(), "Event '" event_name "' failed: ");
|
||||||
|
|
||||||
@@ -61,7 +56,7 @@ DownloadList::clear() {
|
|||||||
torrent::download_remove(*download->download());
|
torrent::download_remove(*download->download());
|
||||||
|
|
||||||
} catch (torrent::internal_error& e) {
|
} catch (torrent::internal_error& e) {
|
||||||
lt_log_print(torrent::LOG_ERRORS, "DownloadList::clear() failed to close or remove download: %s", e.what());
|
lt_log_print(torrent::LOG_ERROR, "DownloadList::clear() failed to close or remove download: %s", e.what());
|
||||||
error_count++;
|
error_count++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -114,7 +109,7 @@ DownloadList::create(torrent::Object* obj, uint32_t tracker_key, bool printLog)
|
|||||||
|
|
||||||
} catch (torrent::local_error& e) {
|
} catch (torrent::local_error& e) {
|
||||||
if (printLog)
|
if (printLog)
|
||||||
lt_log_print(torrent::LOG_TORRENT_EVENTS, "download_list : could not create download : %s", e.what());
|
lt_log_print(torrent::LOG_TORRENT_ERROR, "Could not create download: %s", e.what());
|
||||||
|
|
||||||
delete obj;
|
delete obj;
|
||||||
|
|
||||||
@@ -140,7 +135,7 @@ DownloadList::create(std::istream* str, uint32_t tracker_key, bool printLog) {
|
|||||||
delete object;
|
delete object;
|
||||||
|
|
||||||
if (printLog)
|
if (printLog)
|
||||||
lt_log_print(torrent::LOG_TORRENT_EVENTS, "download_list : could not create download : invalid or incomplete bencode data");
|
lt_log_print(torrent::LOG_TORRENT_ERROR, "Could not create download, the input is not a valid torrent.");
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -151,7 +146,7 @@ DownloadList::create(std::istream* str, uint32_t tracker_key, bool printLog) {
|
|||||||
delete object;
|
delete object;
|
||||||
|
|
||||||
if (printLog)
|
if (printLog)
|
||||||
lt_log_print(torrent::LOG_TORRENT_EVENTS, "download_list : could not create download : %s", e.what());
|
lt_log_print(torrent::LOG_TORRENT_ERROR, "Could not create download: %s", e.what());
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -165,7 +160,7 @@ DownloadList::iterator
|
|||||||
DownloadList::insert(Download* download) {
|
DownloadList::insert(Download* download) {
|
||||||
iterator itr = base_type::insert(end(), std::shared_ptr<Download>(download));
|
iterator itr = base_type::insert(end(), std::shared_ptr<Download>(download));
|
||||||
|
|
||||||
LT_LOG_DOWNLOAD_DEBUG("inserting download", 0);
|
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Inserting download.");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
(*itr)->data()->slot_initial_hash() = std::bind(&DownloadList::hash_done, this, download);
|
(*itr)->data()->slot_initial_hash() = std::bind(&DownloadList::hash_done, this, download);
|
||||||
@@ -205,7 +200,7 @@ DownloadList::erase(iterator itr) {
|
|||||||
|
|
||||||
(*itr)->set_erasing();
|
(*itr)->set_erasing();
|
||||||
|
|
||||||
lt_log_print_hash(torrent::LOG_TORRENT_DEBUG, (*itr)->info()->hash(), "download_list : removing download");
|
lt_log_print_info(torrent::LOG_TORRENT_INFO, (*itr)->info(), "download_list", "Erasing download.");
|
||||||
|
|
||||||
// Makes sure close doesn't restart hashing of this download.
|
// Makes sure close doesn't restart hashing of this download.
|
||||||
(*itr)->set_hash_failed(true);
|
(*itr)->set_hash_failed(true);
|
||||||
@@ -233,7 +228,7 @@ DownloadList::open(Download* download) {
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
} catch (torrent::local_error& e) {
|
} catch (torrent::local_error& e) {
|
||||||
lt_log_print(torrent::LOG_TORRENT_EVENTS, "download_list : could not open download : %s", e.what());
|
lt_log_print(torrent::LOG_TORRENT_ERROR, "Could not open download: %s", e.what());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -242,7 +237,7 @@ void
|
|||||||
DownloadList::open_throw(Download* download) {
|
DownloadList::open_throw(Download* download) {
|
||||||
check_contains(download);
|
check_contains(download);
|
||||||
|
|
||||||
lt_log_print_hash(torrent::LOG_TORRENT_DEBUG, download->info()->hash(), "download_list : opening download");
|
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Opening download.");
|
||||||
|
|
||||||
if (download->download()->info()->is_open())
|
if (download->download()->info()->is_open())
|
||||||
return;
|
return;
|
||||||
@@ -253,7 +248,6 @@ DownloadList::open_throw(Download* download) {
|
|||||||
openFlags |= torrent::Download::open_enable_fallocate;
|
openFlags |= torrent::Download::open_enable_fallocate;
|
||||||
|
|
||||||
download->download()->open(openFlags);
|
download->download()->open(openFlags);
|
||||||
|
|
||||||
DL_TRIGGER_EVENT(download, "event.download.opened");
|
DL_TRIGGER_EVENT(download, "event.download.opened");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,7 +257,7 @@ DownloadList::close(Download* download) {
|
|||||||
close_throw(download);
|
close_throw(download);
|
||||||
|
|
||||||
} catch (torrent::local_error& e) {
|
} catch (torrent::local_error& e) {
|
||||||
lt_log_print(torrent::LOG_TORRENT_EVENTS, "download_list : could not close download : %s", e.what());
|
lt_log_print(torrent::LOG_TORRENT_ERROR, "Could not close download: %s", e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,7 +265,7 @@ DownloadList::close(Download* download) {
|
|||||||
// need the files closed and will keep using the download.
|
// need the files closed and will keep using the download.
|
||||||
void
|
void
|
||||||
DownloadList::close_files(Download* download) {
|
DownloadList::close_files(Download* download) {
|
||||||
lt_log_print_hash(torrent::LOG_TORRENT_DEBUG, download->info()->hash(), "download_list : closing download files");
|
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Closing download files.");
|
||||||
|
|
||||||
if (download->download()->info()->is_active()) {
|
if (download->download()->info()->is_active()) {
|
||||||
download->download()->stop(torrent::Download::stop_skip_tracker);
|
download->download()->stop(torrent::Download::stop_skip_tracker);
|
||||||
@@ -286,7 +280,7 @@ DownloadList::close_files(Download* download) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
DownloadList::close_directly(Download* download) {
|
DownloadList::close_directly(Download* download) {
|
||||||
lt_log_print_hash(torrent::LOG_TORRENT_DEBUG, download->info()->hash(), "download_list : closing download directly");
|
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Closing download directly.");
|
||||||
|
|
||||||
auto lifetime = download->lifetime();
|
auto lifetime = download->lifetime();
|
||||||
bool was_active = download->download()->info()->is_active();
|
bool was_active = download->download()->info()->is_active();
|
||||||
@@ -333,8 +327,7 @@ DownloadList::update_paused_state(Download* download) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
DownloadList::close_quick(Download* download) {
|
DownloadList::close_quick(Download* download) {
|
||||||
lt_log_print_hash(torrent::LOG_TORRENT_DEBUG, download->info()->hash(), "download_list : closing download quickly.");
|
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Closing download quickly.");
|
||||||
|
|
||||||
close(download);
|
close(download);
|
||||||
|
|
||||||
// Make sure we cancel any tracker requests. This should rather be
|
// Make sure we cancel any tracker requests. This should rather be
|
||||||
@@ -348,7 +341,7 @@ void
|
|||||||
DownloadList::close_throw(Download* download) {
|
DownloadList::close_throw(Download* download) {
|
||||||
check_contains(download);
|
check_contains(download);
|
||||||
|
|
||||||
LT_LOG_DOWNLOAD_DEBUG("closing download with throw", 0);
|
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Closing download with throw.");
|
||||||
|
|
||||||
// When pause gets called it will clear the initial hash check state
|
// When pause gets called it will clear the initial hash check state
|
||||||
// and set hash failed. This should ensure hashing doesn't restart
|
// and set hash failed. This should ensure hashing doesn't restart
|
||||||
@@ -390,7 +383,7 @@ void
|
|||||||
DownloadList::resume(Download* download, int flags) {
|
DownloadList::resume(Download* download, int flags) {
|
||||||
check_contains(download);
|
check_contains(download);
|
||||||
|
|
||||||
LT_LOG_DOWNLOAD_DEBUG("resuming download : flags:%0x.", flags);
|
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Resuming download: flags:%0x.", flags);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
@@ -479,7 +472,7 @@ DownloadList::resume(Download* download, int flags) {
|
|||||||
DL_TRIGGER_EVENT(download, "event.download.resumed");
|
DL_TRIGGER_EVENT(download, "event.download.resumed");
|
||||||
|
|
||||||
} catch (torrent::local_error& e) {
|
} catch (torrent::local_error& e) {
|
||||||
LT_LOG_DOWNLOAD_EVENTS("could not resume download : %s", e.what());
|
lt_log_print(torrent::LOG_TORRENT_ERROR, "Could not resume download: %s", e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -487,7 +480,7 @@ void
|
|||||||
DownloadList::pause(Download* download, int flags) {
|
DownloadList::pause(Download* download, int flags) {
|
||||||
check_contains(download);
|
check_contains(download);
|
||||||
|
|
||||||
LT_LOG_DOWNLOAD_DEBUG("pausing download : flags:%0x.", flags);
|
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Pausing download: flags:%0x.", flags);
|
||||||
|
|
||||||
auto lifetime = download->lifetime();
|
auto lifetime = download->lifetime();
|
||||||
|
|
||||||
@@ -530,7 +523,7 @@ DownloadList::pause(Download* download, int flags) {
|
|||||||
//control->core()->download_store()->save(download);
|
//control->core()->download_store()->save(download);
|
||||||
|
|
||||||
} catch (torrent::local_error& e) {
|
} catch (torrent::local_error& e) {
|
||||||
LT_LOG_DOWNLOAD_EVENTS("could not pause download : %s", e.what());
|
lt_log_print(torrent::LOG_TORRENT_ERROR, "Could not pause download: %s", e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -538,7 +531,7 @@ void
|
|||||||
DownloadList::check_hash(Download* download) {
|
DownloadList::check_hash(Download* download) {
|
||||||
check_contains(download);
|
check_contains(download);
|
||||||
|
|
||||||
LT_LOG_DOWNLOAD_DEBUG("checking hash", 0);
|
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Checking hash.");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (rpc::call_command_value("d.hashing", rpc::make_target(download)) != Download::variable_hashing_stopped)
|
if (rpc::call_command_value("d.hashing", rpc::make_target(download)) != Download::variable_hashing_stopped)
|
||||||
@@ -547,7 +540,7 @@ DownloadList::check_hash(Download* download) {
|
|||||||
hash_queue(download, Download::variable_hashing_rehash);
|
hash_queue(download, Download::variable_hashing_rehash);
|
||||||
|
|
||||||
} catch (torrent::local_error& e) {
|
} catch (torrent::local_error& e) {
|
||||||
LT_LOG_DOWNLOAD_EVENTS("could not check hash : %s", e.what());
|
lt_log_print(torrent::LOG_TORRENT_ERROR, "Could not check hash: %s", e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -555,7 +548,7 @@ void
|
|||||||
DownloadList::hash_done(Download* download) {
|
DownloadList::hash_done(Download* download) {
|
||||||
check_contains(download);
|
check_contains(download);
|
||||||
|
|
||||||
LT_LOG_DOWNLOAD_DEBUG("hash done", 0);
|
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Hash done.");
|
||||||
|
|
||||||
if (download->is_hash_checking() || download->is_active())
|
if (download->is_hash_checking() || download->is_active())
|
||||||
throw torrent::internal_error("DownloadList::hash_done(...) download in invalid state.");
|
throw torrent::internal_error("DownloadList::hash_done(...) download in invalid state.");
|
||||||
@@ -620,8 +613,7 @@ DownloadList::hash_done(Download* download) {
|
|||||||
confirm_finished(download);
|
confirm_finished(download);
|
||||||
} else {
|
} else {
|
||||||
download->set_message("Hash check on download completion found bad chunks.");
|
download->set_message("Hash check on download completion found bad chunks.");
|
||||||
LT_LOG_DOWNLOAD_EVENTS("hash check on download completion found bad chunks", 0);
|
lt_log_print(torrent::LOG_TORRENT_ERROR, "Hash check on download completion found bad chunks.");
|
||||||
|
|
||||||
DL_TRIGGER_EVENT(download, "event.download.hash_final_failed");
|
DL_TRIGGER_EVENT(download, "event.download.hash_final_failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -642,7 +634,7 @@ void
|
|||||||
DownloadList::hash_queue(Download* download, int type) {
|
DownloadList::hash_queue(Download* download, int type) {
|
||||||
check_contains(download);
|
check_contains(download);
|
||||||
|
|
||||||
LT_LOG_DOWNLOAD_DEBUG("hash queue : type:%d", type);
|
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Hash queue.");
|
||||||
|
|
||||||
if (rpc::call_command_value("d.hashing", rpc::make_target(download)) != Download::variable_hashing_stopped)
|
if (rpc::call_command_value("d.hashing", rpc::make_target(download)) != Download::variable_hashing_stopped)
|
||||||
throw torrent::internal_error("DownloadList::hash_queue(...) hashing already queued.");
|
throw torrent::internal_error("DownloadList::hash_queue(...) hashing already queued.");
|
||||||
@@ -686,7 +678,7 @@ void
|
|||||||
DownloadList::received_finished(Download* download) {
|
DownloadList::received_finished(Download* download) {
|
||||||
check_contains(download);
|
check_contains(download);
|
||||||
|
|
||||||
LT_LOG_DOWNLOAD_DEBUG("received finished", 0);
|
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Received finished.");
|
||||||
|
|
||||||
if (rpc::call_command_value("pieces.hash.on_completion"))
|
if (rpc::call_command_value("pieces.hash.on_completion"))
|
||||||
// Set some 'checking_finished_thingie' variable to make hash_done
|
// Set some 'checking_finished_thingie' variable to make hash_done
|
||||||
@@ -701,7 +693,7 @@ void
|
|||||||
DownloadList::confirm_finished(Download* download) {
|
DownloadList::confirm_finished(Download* download) {
|
||||||
check_contains(download);
|
check_contains(download);
|
||||||
|
|
||||||
LT_LOG_DOWNLOAD_DEBUG("confirming finished", 0);
|
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Confirming finished.");
|
||||||
|
|
||||||
if (download->download()->info()->is_meta_download())
|
if (download->download()->info()->is_meta_download())
|
||||||
return process_meta_download(download);
|
return process_meta_download(download);
|
||||||
@@ -776,7 +768,7 @@ DownloadList::confirm_finished(Download* download) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
DownloadList::process_meta_download(Download* download) {
|
DownloadList::process_meta_download(Download* download) {
|
||||||
LT_LOG_DOWNLOAD_DEBUG("processing meta download", 0);
|
lt_log_print_info(torrent::LOG_TORRENT_INFO, download->info(), "download_list", "Processing meta download.");
|
||||||
|
|
||||||
rpc::call_command("d.stop", torrent::Object(), rpc::make_target(download));
|
rpc::call_command("d.stop", torrent::Object(), rpc::make_target(download));
|
||||||
rpc::call_command("d.close", torrent::Object(), rpc::make_target(download));
|
rpc::call_command("d.close", torrent::Object(), rpc::make_target(download));
|
||||||
@@ -786,7 +778,7 @@ DownloadList::process_meta_download(Download* download) {
|
|||||||
std::fstream file(metafile.c_str(), std::ios::in | std::ios::binary);
|
std::fstream file(metafile.c_str(), std::ios::in | std::ios::binary);
|
||||||
|
|
||||||
if (!file.is_open()) {
|
if (!file.is_open()) {
|
||||||
LT_LOG_DOWNLOAD_EVENTS("could not read download metadata : %s", metafile.c_str());
|
lt_log_print(torrent::LOG_TORRENT_ERROR, "Could not read download metadata.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -794,7 +786,7 @@ DownloadList::process_meta_download(Download* download) {
|
|||||||
file >> bencode->insert_key("info", torrent::Object());
|
file >> bencode->insert_key("info", torrent::Object());
|
||||||
|
|
||||||
if (file.fail()) {
|
if (file.fail()) {
|
||||||
LT_LOG_DOWNLOAD_EVENTS("could not create download, the input is not a valid torrent : %s", metafile.c_str());
|
lt_log_print(torrent::LOG_TORRENT_ERROR, "Could not create download, the input is not a valid torrent.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -802,10 +794,8 @@ DownloadList::process_meta_download(Download* download) {
|
|||||||
|
|
||||||
// Steal the keys we still need. The old download has no use for them.
|
// Steal the keys we still need. The old download has no use for them.
|
||||||
bencode->insert_key("rtorrent_meta_download", torrent::Object()).swap(download->bencode()->get_key("rtorrent_meta_download"));
|
bencode->insert_key("rtorrent_meta_download", torrent::Object()).swap(download->bencode()->get_key("rtorrent_meta_download"));
|
||||||
|
|
||||||
if (download->bencode()->has_key("announce"))
|
if (download->bencode()->has_key("announce"))
|
||||||
bencode->insert_key("announce", torrent::Object()).swap(download->bencode()->get_key("announce"));
|
bencode->insert_key("announce", torrent::Object()).swap(download->bencode()->get_key("announce"));
|
||||||
|
|
||||||
if (download->bencode()->has_key("announce-list"))
|
if (download->bencode()->has_key("announce-list"))
|
||||||
bencode->insert_key("announce-list", torrent::Object()).swap(download->bencode()->get_key("announce-list"));
|
bencode->insert_key("announce-list", torrent::Object()).swap(download->bencode()->get_key("announce-list"));
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#ifndef RTORRENT_CORE_DOWNLOAD_LIST_H
|
#ifndef RTORRENT_CORE_DOWNLOAD_LIST_H
|
||||||
#define RTORRENT_CORE_DOWNLOAD_LIST_H
|
#define RTORRENT_CORE_DOWNLOAD_LIST_H
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|||||||
+1
-2
@@ -440,8 +440,7 @@ Manager::receive_hashing_changed() {
|
|||||||
} else {
|
} else {
|
||||||
(*itr)->set_hash_failed(true);
|
(*itr)->set_hash_failed(true);
|
||||||
(*itr)->set_message("Hashing failed: " + std::string(e.what()));
|
(*itr)->set_message("Hashing failed: " + std::string(e.what()));
|
||||||
|
lt_log_print(torrent::LOG_TORRENT_ERROR, "Hashing failed: %s", e.what());
|
||||||
lt_log_print_hash(torrent::LOG_TORRENT_EVENTS, (*itr)->info()->hash(), "hashing failed : %s", e.what());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-19
@@ -152,11 +152,10 @@ main(int argc, char** argv) {
|
|||||||
|
|
||||||
SignalHandler::set_sigaction_handler(SIGBUS, &handle_sigbus);
|
SignalHandler::set_sigaction_handler(SIGBUS, &handle_sigbus);
|
||||||
|
|
||||||
torrent::log_add_group_output(torrent::LOG_ERRORS, "important");
|
torrent::log_add_group_output(torrent::LOG_NOTICE, "important");
|
||||||
torrent::log_add_group_output(torrent::LOG_DHT_ERROR, "important");
|
torrent::log_add_group_output(torrent::LOG_DHT_ERROR, "important");
|
||||||
|
|
||||||
torrent::log_add_group_output(torrent::LOG_ERRORS, "complete");
|
torrent::log_add_group_output(torrent::LOG_INFO, "complete");
|
||||||
torrent::log_add_group_output(torrent::LOG_EVENTS, "complete");
|
|
||||||
torrent::log_add_group_output(torrent::LOG_DHT_ERROR, "complete");
|
torrent::log_add_group_output(torrent::LOG_DHT_ERROR, "complete");
|
||||||
torrent::log_add_group_output(torrent::LOG_DHT_CONTROLLER, "complete");
|
torrent::log_add_group_output(torrent::LOG_DHT_CONTROLLER, "complete");
|
||||||
|
|
||||||
@@ -176,17 +175,17 @@ main(int argc, char** argv) {
|
|||||||
|
|
||||||
if (OptionParser::has_flag('D', argc, argv)) {
|
if (OptionParser::has_flag('D', argc, argv)) {
|
||||||
rpc::call_command_set_value("method.use_deprecated.set", true);
|
rpc::call_command_set_value("method.use_deprecated.set", true);
|
||||||
lt_log_print(torrent::LOG_ERRORS, "Enabled deprecated commands.");
|
lt_log_print(torrent::LOG_WARN, "Enabled deprecated commands.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OptionParser::has_flag('I', argc, argv)) {
|
if (OptionParser::has_flag('I', argc, argv)) {
|
||||||
rpc::call_command_set_value("method.use_intermediate.set", 0);
|
rpc::call_command_set_value("method.use_intermediate.set", 0);
|
||||||
lt_log_print(torrent::LOG_ERRORS, "Disabled intermediate commands.");
|
lt_log_print(torrent::LOG_WARN, "Disabled intermediate commands.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OptionParser::has_flag('K', argc, argv)) {
|
if (OptionParser::has_flag('K', argc, argv)) {
|
||||||
rpc::call_command_set_value("method.use_intermediate.set", 2);
|
rpc::call_command_set_value("method.use_intermediate.set", 2);
|
||||||
lt_log_print(torrent::LOG_ERRORS, "Allowing intermediate commands without xmlrpc.");
|
lt_log_print(torrent::LOG_WARN, "Allowing intermediate commands without xmlrpc.");
|
||||||
}
|
}
|
||||||
|
|
||||||
rpc::parse_command_multiple
|
rpc::parse_command_multiple
|
||||||
@@ -373,11 +372,11 @@ main(int argc, char** argv) {
|
|||||||
rpc::rpc.mark_safe("network.http.proxy_address");
|
rpc::rpc.mark_safe("network.http.proxy_address");
|
||||||
|
|
||||||
CMD2_ANY_VALUE_V("network.http.max_total_connections.set", [](auto, auto) {
|
CMD2_ANY_VALUE_V("network.http.max_total_connections.set", [](auto, auto) {
|
||||||
lt_log_print(torrent::LOG_ERRORS, "network.http.max_total_connections.set is deprecated, use system.sockets.http.min_alloc.set instead.");
|
lt_log_print(torrent::LOG_WARN, "network.http.max_total_connections.set is deprecated, use system.sockets.http.min_alloc.set instead.");
|
||||||
});
|
});
|
||||||
|
|
||||||
CMD2_ANY_VALUE_V("network.max_open_files.set", [](auto, auto) {
|
CMD2_ANY_VALUE_V("network.max_open_files.set", [](auto, auto) {
|
||||||
lt_log_print(torrent::LOG_ERRORS, "network.max_open_files.set is deprecated, use system.sockets.files.min_alloc.set instead.");
|
lt_log_print(torrent::LOG_WARN, "network.max_open_files.set is deprecated, use system.sockets.files.min_alloc.set instead.");
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: Keep d.directory_base for a while as it is widely used.
|
// TODO: Keep d.directory_base for a while as it is widely used.
|
||||||
@@ -420,16 +419,16 @@ main(int argc, char** argv) {
|
|||||||
CMD_REDIRECT("max_memory_usage", "pieces.memory.max.set");
|
CMD_REDIRECT("max_memory_usage", "pieces.memory.max.set");
|
||||||
|
|
||||||
CMD_ANY_LIST("throttle.ip", []( auto, auto) {
|
CMD_ANY_LIST("throttle.ip", []( auto, auto) {
|
||||||
lt_log_print(torrent::LOG_ERRORS, "The 'throttle.ip' command is deprecated and does nothing.");
|
lt_log_print(torrent::LOG_WARN, "The 'throttle.ip' command is deprecated and does nothing.");
|
||||||
return torrent::Object();
|
return torrent::Object();
|
||||||
});
|
});
|
||||||
|
|
||||||
CMD_ANY("network.port_open", [](auto, auto) {
|
CMD_ANY("network.port_open", [](auto, auto) {
|
||||||
lt_log_print(torrent::LOG_ERRORS, "The 'network.port_open' command is deprecated and does nothing.");
|
lt_log_print(torrent::LOG_WARN, "The 'network.port_open' command is deprecated and does nothing.");
|
||||||
return torrent::Object();
|
return torrent::Object();
|
||||||
});
|
});
|
||||||
CMD_ANY("network.port_open.set", [](auto, auto) {
|
CMD_ANY("network.port_open.set", [](auto, auto) {
|
||||||
lt_log_print(torrent::LOG_ERRORS, "The 'network.port_open.set' command is deprecated and does nothing.");
|
lt_log_print(torrent::LOG_WARN, "The 'network.port_open.set' command is deprecated and does nothing.");
|
||||||
return torrent::Object();
|
return torrent::Object();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -444,7 +443,7 @@ main(int argc, char** argv) {
|
|||||||
|
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
if (errno == EAFNOSUPPORT) {
|
if (errno == EAFNOSUPPORT) {
|
||||||
lt_log_print(torrent::LOG_ERRORS, "disabling ipv6 support, not available on system");
|
lt_log_print(torrent::LOG_WARN, "disabling ipv6 support, not available on system");
|
||||||
rpc::call_command_set_value("network.block.ipv6.set", true);
|
rpc::call_command_set_value("network.block.ipv6.set", true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -456,7 +455,7 @@ main(int argc, char** argv) {
|
|||||||
|
|
||||||
parse_config_file(argc, argv, [](auto& path) {
|
parse_config_file(argc, argv, [](auto& path) {
|
||||||
if (path.empty()) {
|
if (path.empty()) {
|
||||||
lt_log_print(torrent::LOG_ERRORS, "Ignoring rtorrent.rc.");
|
lt_log_print(torrent::LOG_WARN, "Ignoring rtorrent.rc.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -500,7 +499,7 @@ main(int argc, char** argv) {
|
|||||||
<< e.what() << std::endl
|
<< e.what() << std::endl
|
||||||
<< e.backtrace();
|
<< e.backtrace();
|
||||||
|
|
||||||
lt_log_print_dump(torrent::LOG_ERRORS, e.backtrace().c_str(), e.backtrace().size(),
|
lt_log_print_dump(torrent::LOG_CRITICAL, e.backtrace().c_str(), e.backtrace().size(),
|
||||||
"Caught internal_error: '%s'.", e.what());
|
"Caught internal_error: '%s'.", e.what());
|
||||||
|
|
||||||
torrent::log_cleanup();
|
torrent::log_cleanup();
|
||||||
@@ -512,7 +511,7 @@ main(int argc, char** argv) {
|
|||||||
|
|
||||||
std::cout << "rtorrent: caught" << typeid(e).name() << " : " << e.what() << std::endl;
|
std::cout << "rtorrent: caught" << typeid(e).name() << " : " << e.what() << std::endl;
|
||||||
|
|
||||||
lt_log_print(torrent::LOG_ERRORS, "Caught exception: '%s'.", e.what());
|
lt_log_print(torrent::LOG_CRITICAL, "Caught exception: '%s'.", e.what());
|
||||||
|
|
||||||
torrent::log_cleanup();
|
torrent::log_cleanup();
|
||||||
return -1;
|
return -1;
|
||||||
@@ -589,9 +588,9 @@ handle_sigbus(int signum, siginfo_t* sa, [[maybe_unused]] void* ptr) {
|
|||||||
handle_sigbus_exit:
|
handle_sigbus_exit:
|
||||||
std::cout << output.rdbuf();
|
std::cout << output.rdbuf();
|
||||||
|
|
||||||
if (lt_log_is_valid(torrent::LOG_ERRORS)) {
|
if (lt_log_is_valid(torrent::LOG_CRITICAL)) {
|
||||||
std::string dump = output.str();
|
std::string dump = output.str();
|
||||||
lt_log_print_dump(torrent::LOG_ERRORS, dump.c_str(), dump.size(), "Caught signal: '%s'.", signal_reason);
|
lt_log_print_dump(torrent::LOG_CRITICAL, dump.c_str(), dump.size(), "Caught signal: '%s'.", signal_reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
torrent::log_cleanup();
|
torrent::log_cleanup();
|
||||||
@@ -630,9 +629,9 @@ do_panic(int signum) {
|
|||||||
|
|
||||||
std::cout << output.rdbuf();
|
std::cout << output.rdbuf();
|
||||||
|
|
||||||
if (lt_log_is_valid(torrent::LOG_ERRORS)) {
|
if (lt_log_is_valid(torrent::LOG_CRITICAL)) {
|
||||||
std::string dump = output.str();
|
std::string dump = output.str();
|
||||||
lt_log_print_dump(torrent::LOG_ERRORS, dump.c_str(), dump.size(), "Caught signal: '%s.", strsignal(signum));
|
lt_log_print_dump(torrent::LOG_CRITICAL, dump.c_str(), dump.size(), "Caught signal: '%s.", strsignal(signum));
|
||||||
}
|
}
|
||||||
|
|
||||||
torrent::log_cleanup();
|
torrent::log_cleanup();
|
||||||
|
|||||||
+1
-1
@@ -108,7 +108,7 @@ public:
|
|||||||
|
|
||||||
static stack_type* from_data(char* data) { return reinterpret_cast<stack_type*>(data); }
|
static stack_type* from_data(char* data) { return reinterpret_cast<stack_type*>(data); }
|
||||||
|
|
||||||
alignas(optimal_alignment) char buffer[sizeof(torrent::Object) * max_arguments];
|
char buffer[sizeof(torrent::Object) * max_arguments];
|
||||||
};
|
};
|
||||||
|
|
||||||
command_base() : m_copy_helper(nullptr), m_dest_helper(nullptr) {}
|
command_base() : m_copy_helper(nullptr), m_dest_helper(nullptr) {}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "rpc/exec_file.h"
|
#include "rpc/exec_file.h"
|
||||||
|
|
||||||
// #include <cassert>
|
// #include <cassert>
|
||||||
@@ -83,9 +81,8 @@ ExecFile::execute_object(const torrent::Object& rawArgs, int flags) {
|
|||||||
char* argsBuffer[max_args];
|
char* argsBuffer[max_args];
|
||||||
char** argsCurrent = argsBuffer;
|
char** argsCurrent = argsBuffer;
|
||||||
|
|
||||||
// On the heap: a buffer of buffer_size does not belong on the stack of whichever thread runs the command.
|
// Size of value strings are less than 24.
|
||||||
auto valueStorage = std::make_unique<char[]>(buffer_size + 1);
|
char valueBuffer[buffer_size+1];
|
||||||
char* valueBuffer = valueStorage.get();
|
|
||||||
char* valueCurrent = valueBuffer;
|
char* valueCurrent = valueBuffer;
|
||||||
|
|
||||||
if (rawArgs.is_list()) {
|
if (rawArgs.is_list()) {
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@ namespace rpc {
|
|||||||
class ExecFile {
|
class ExecFile {
|
||||||
public:
|
public:
|
||||||
static constexpr unsigned int max_args = 128;
|
static constexpr unsigned int max_args = 128;
|
||||||
static constexpr unsigned int buffer_size = 128 * 1024;
|
static constexpr unsigned int buffer_size = 4096;
|
||||||
|
|
||||||
static constexpr int flag_expand_tilde = 0x1;
|
static constexpr int flag_expand_tilde = 0x1;
|
||||||
static constexpr int flag_throw = 0x2;
|
static constexpr int flag_throw = 0x2;
|
||||||
|
|||||||
+9
-14
@@ -118,32 +118,27 @@ parse_value_nothrow(const char* src, int64_t* value, int base, int unit) {
|
|||||||
if (base != 0 && base != 8 && base != 10 && base != 16)
|
if (base != 0 && base != 8 && base != 10 && base != 16)
|
||||||
throw torrent::input_error("Command::string_to_value_unit(...) received invalid base.");
|
throw torrent::input_error("Command::string_to_value_unit(...) received invalid base.");
|
||||||
|
|
||||||
const char* first = src;
|
|
||||||
|
|
||||||
while (parse_is_space(*src))
|
while (parse_is_space(*src))
|
||||||
src++;
|
src++;
|
||||||
|
|
||||||
if (src[0] == '+')
|
if (src[0] == '+')
|
||||||
return first;
|
return src;
|
||||||
|
|
||||||
if (src[0] == '-') {
|
if (src[0] == '-') {
|
||||||
if (base == 8 || base == 16)
|
if (base == 8 || base == 16)
|
||||||
return first;
|
return src;
|
||||||
|
|
||||||
if (src[1] == '0')
|
if (src[1] == '0')
|
||||||
return first;
|
return src;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (base == 10 && src[0] == '0' && (src[1] >= '0' && src[1] <= '9'))
|
|
||||||
return first;
|
|
||||||
|
|
||||||
char* last{};
|
char* last{};
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
*value = strtoll(src, &last, base);
|
*value = strtoll(src, &last, base);
|
||||||
|
|
||||||
if (errno == ERANGE)
|
if (errno == ERANGE)
|
||||||
return first;
|
return src;
|
||||||
|
|
||||||
if (last == src) {
|
if (last == src) {
|
||||||
*value = 0;
|
*value = 0;
|
||||||
@@ -153,7 +148,7 @@ parse_value_nothrow(const char* src, int64_t* value, int base, int unit) {
|
|||||||
if (strcasecmp(src, "true") == 0) { *value = 1; return src + strlen("true"); }
|
if (strcasecmp(src, "true") == 0) { *value = 1; return src + strlen("true"); }
|
||||||
if (strcasecmp(src, "false") == 0) { *value = 0; return src + strlen("false"); }
|
if (strcasecmp(src, "false") == 0) { *value = 0; return src + strlen("false"); }
|
||||||
|
|
||||||
return first;
|
return src;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (*last) {
|
switch (*last) {
|
||||||
@@ -161,15 +156,15 @@ parse_value_nothrow(const char* src, int64_t* value, int base, int unit) {
|
|||||||
case 'B': ++last; break;
|
case 'B': ++last; break;
|
||||||
case 'k':
|
case 'k':
|
||||||
case 'K':
|
case 'K':
|
||||||
if (!value_fits_shifted(*value, 10)) return first; // overflow guard
|
if (!value_fits_shifted(*value, 10)) return src; // overflow guard
|
||||||
*value = *value << 10; ++last; break;
|
*value = *value << 10; ++last; break;
|
||||||
case 'm':
|
case 'm':
|
||||||
case 'M':
|
case 'M':
|
||||||
if (!value_fits_shifted(*value, 20)) return first; // overflow guard
|
if (!value_fits_shifted(*value, 20)) return src; // overflow guard
|
||||||
*value = *value << 20; ++last; break;
|
*value = *value << 20; ++last; break;
|
||||||
case 'g':
|
case 'g':
|
||||||
case 'G':
|
case 'G':
|
||||||
if (!value_fits_shifted(*value, 30)) return first; // overflow guard
|
if (!value_fits_shifted(*value, 30)) return src; // overflow guard
|
||||||
*value = *value << 30; ++last; break;
|
*value = *value << 30; ++last; break;
|
||||||
// case ' ':
|
// case ' ':
|
||||||
// case '\0': *value = *value * unit; break;
|
// case '\0': *value = *value * unit; break;
|
||||||
@@ -177,7 +172,7 @@ parse_value_nothrow(const char* src, int64_t* value, int base, int unit) {
|
|||||||
default:
|
default:
|
||||||
if (*value > std::numeric_limits<int64_t>::max() / unit ||
|
if (*value > std::numeric_limits<int64_t>::max() / unit ||
|
||||||
*value < std::numeric_limits<int64_t>::min() / unit)
|
*value < std::numeric_limits<int64_t>::min() / unit)
|
||||||
return first; // overflow guard
|
return src; // overflow guard
|
||||||
|
|
||||||
*value = *value * unit;
|
*value = *value * unit;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -123,39 +123,6 @@ parse_command(target_type target, const char* first, const char* last) {
|
|||||||
return std::make_pair(commands.call_command(key, args, target), first);
|
return std::make_pair(commands.call_command(key, args, target), first);
|
||||||
}
|
}
|
||||||
|
|
||||||
torrent::Object
|
|
||||||
parse_command_object(const char* first, const char* last) {
|
|
||||||
first = std::find_if(first, last, [&](char c) { return !command_map_is_space(c); });
|
|
||||||
|
|
||||||
if (first == last || *first == '#')
|
|
||||||
return torrent::Object();
|
|
||||||
|
|
||||||
char key[128];
|
|
||||||
|
|
||||||
first = parse_command_name(first, last, key, key + 128);
|
|
||||||
first = std::find_if(first, last, [&](char c) { return !command_map_is_space(c); });
|
|
||||||
|
|
||||||
if (first == last || *first != '=')
|
|
||||||
throw torrent::input_error("Could not find '=' in command '" + std::string(key) + "'.");
|
|
||||||
|
|
||||||
torrent::Object result = torrent::Object::create_dict_key();
|
|
||||||
|
|
||||||
result.as_dict_key() = key;
|
|
||||||
|
|
||||||
first = parse_whole_list(first + 1, last, &result.as_dict_obj(), &parse_is_delim_command);
|
|
||||||
|
|
||||||
// Find the last character that is part of this command, skipping
|
|
||||||
// the whitespace at the end.
|
|
||||||
first = std::find_if(first, last, [&](char c) { return !command_map_is_space(c); });
|
|
||||||
|
|
||||||
// This helper accepts exactly one command and cannot return where a next
|
|
||||||
// command begins, so reject every non-whitespace suffix, including ';'.
|
|
||||||
if (first != last && *first != '\0')
|
|
||||||
throw torrent::input_error("Junk at end of input.");
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
torrent::Object
|
torrent::Object
|
||||||
parse_command_multiple(target_type target, const char* first, const char* last) {
|
parse_command_multiple(target_type target, const char* first, const char* last) {
|
||||||
parse_command_type result;
|
parse_command_type result;
|
||||||
|
|||||||
@@ -37,9 +37,6 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <functional>
|
|
||||||
#include <utility>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "xmlrpc.h"
|
#include "xmlrpc.h"
|
||||||
#include "rpc_manager.h"
|
#include "rpc_manager.h"
|
||||||
@@ -70,34 +67,6 @@ parse_command_single(target_type target, const std::string& cmd) {
|
|||||||
return parse_command(target, cmd.c_str(), cmd.c_str() + cmd.size()).first;
|
return parse_command(target, cmd.c_str(), cmd.c_str() + cmd.size()).first;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse one RPC command without executing it. Repeated evaluations can use
|
|
||||||
// call_object on the result, which handles per-target argument expansion.
|
|
||||||
torrent::Object parse_command_object(const char* first, const char* last);
|
|
||||||
|
|
||||||
inline torrent::Object parse_command_object(const std::string& cmd) {
|
|
||||||
return parse_command_object(cmd.c_str(), cmd.c_str() + cmd.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare a multicall's commands once, on the first target that uses them. This
|
|
||||||
// keeps empty target lists from parsing commands that would never be evaluated.
|
|
||||||
struct preparsed_commands : public std::vector<torrent::Object> {
|
|
||||||
explicit preparsed_commands(std::function<void(preparsed_commands&)> prepare)
|
|
||||||
: m_prepare(std::move(prepare)) {}
|
|
||||||
|
|
||||||
void prepare_if_needed() {
|
|
||||||
if (m_prepare) {
|
|
||||||
// Clear before invoking: the callback may inspect this vector, and a
|
|
||||||
// throwing callback must not be run again against partially added items.
|
|
||||||
auto prepare = std::move(m_prepare);
|
|
||||||
m_prepare = {};
|
|
||||||
prepare(*this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::function<void(preparsed_commands&)> m_prepare;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline torrent::Object
|
inline torrent::Object
|
||||||
parse_command_multiple_std(const std::string& cmd, target_type target = rpc::make_target()) {
|
parse_command_multiple_std(const std::string& cmd, target_type target = rpc::make_target()) {
|
||||||
return parse_command_multiple(target, cmd.c_str(), cmd.c_str() + cmd.size());
|
return parse_command_multiple(target, cmd.c_str(), cmd.c_str() + cmd.size());
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ ThreadScgi::change_rpc_log() {
|
|||||||
::close(scgi()->log_fd());
|
::close(scgi()->log_fd());
|
||||||
scgi()->set_log_fd(-1);
|
scgi()->set_log_fd(-1);
|
||||||
|
|
||||||
lt_log_print(torrent::LOG_EVENTS, "Closed RPC log.", 0);
|
lt_log_print(torrent::LOG_NOTICE, "Closed RPC log.", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_rpc_log_filename.empty())
|
if (m_rpc_log_filename.empty())
|
||||||
@@ -91,11 +91,11 @@ ThreadScgi::change_rpc_log() {
|
|||||||
scgi()->set_log_fd(open(expand_path(m_rpc_log_filename).c_str(), O_WRONLY | O_APPEND | O_CREAT, 0644));
|
scgi()->set_log_fd(open(expand_path(m_rpc_log_filename).c_str(), O_WRONLY | O_APPEND | O_CREAT, 0644));
|
||||||
|
|
||||||
if (scgi()->log_fd() == -1) {
|
if (scgi()->log_fd() == -1) {
|
||||||
lt_log_print(torrent::LOG_EVENTS, "Could not open RPC log file '%s'.", m_rpc_log_filename.c_str());
|
lt_log_print(torrent::LOG_NOTICE, "Could not open RPC log file '%s'.", m_rpc_log_filename.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
lt_log_print(torrent::LOG_EVENTS, "Logging RPC events to '%s'.", m_rpc_log_filename.c_str());
|
lt_log_print(torrent::LOG_NOTICE, "Logging RPC events to '%s'.", m_rpc_log_filename.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -417,7 +417,7 @@ SessionManager::process_finished_saves() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
lt_log_print(torrent::LOG_ERRORS, "Storage errors saving session data for download: ignored:%u : %s", m_ignored_storage_error_count, e.what());
|
lt_log_print(torrent::LOG_ERROR, "Storage errors saving session data for download: ignored:%u : %s", m_ignored_storage_error_count, e.what());
|
||||||
|
|
||||||
m_last_storage_error_message = torrent::this_thread::cached_time();
|
m_last_storage_error_message = torrent::this_thread::cached_time();
|
||||||
m_ignored_storage_error_count = 0;
|
m_ignored_storage_error_count = 0;
|
||||||
|
|||||||
+1
-1
@@ -142,7 +142,7 @@ parse_config_file_comments(const std::string& path) {
|
|||||||
else
|
else
|
||||||
throw torrent::input_error("Unknown command in config file comment: " + line);
|
throw torrent::input_error("Unknown command in config file comment: " + line);
|
||||||
|
|
||||||
lt_log_print(torrent::LOG_EVENTS, "Pre-config command: %s=%s", command.c_str(), args.c_str());
|
lt_log_print(torrent::LOG_NOTICE, "Pre-config command: %s=%s", command.c_str(), args.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -366,7 +366,7 @@ DownloadList::receive_exit_input(Input type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} catch (torrent::input_error& e) {
|
} catch (torrent::input_error& e) {
|
||||||
lt_log_print(torrent::LOG_ERRORS, "Input failed: %s", e.what());
|
lt_log_print(torrent::LOG_WARN, "Input failed: %s", e.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
activate_display(DISPLAY_DOWNLOAD_LIST);
|
activate_display(DISPLAY_DOWNLOAD_LIST);
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ ElementDownloadList::receive_command(const char* cmd) {
|
|||||||
m_view->set_last_changed();
|
m_view->set_last_changed();
|
||||||
|
|
||||||
} catch (torrent::input_error& e) {
|
} catch (torrent::input_error& e) {
|
||||||
lt_log_print(torrent::LOG_ERRORS, "Command failed: %s", e.what());
|
lt_log_print(torrent::LOG_WARN, "Command failed: %s", e.what());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -197,9 +197,8 @@ ElementDownloadList::receive_cycle_throttle() {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
core::Download* download = m_view->focus()->get();
|
core::Download* download = m_view->focus()->get();
|
||||||
|
|
||||||
if (download->is_active()) {
|
if (download->is_active()) {
|
||||||
lt_log_print_hash(torrent::LOG_TORRENT_DEBUG, download->info()->hash(), "cannot change throttle on active download");
|
lt_log_print(torrent::LOG_TORRENT_WARN, "Cannot change throttle on active download.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-7
@@ -380,7 +380,7 @@ Root::set_input_history_size(int size) {
|
|||||||
void
|
void
|
||||||
Root::load_input_history() {
|
Root::load_input_history() {
|
||||||
if (m_control == nullptr || !session_thread::manager()->is_used()) {
|
if (m_control == nullptr || !session_thread::manager()->is_used()) {
|
||||||
lt_log_print(torrent::LOG_DEBUG_TRACE, "ignoring input history file");
|
lt_log_print(torrent::LOG_DEBUG, "ignoring input history file");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -415,10 +415,10 @@ Root::load_input_history() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (history_file.bad()) {
|
if (history_file.bad()) {
|
||||||
lt_log_print(torrent::LOG_DEBUG_TRACE, "input history file corrupted, discarding (path:%s)", history_filename.c_str());
|
lt_log_print(torrent::LOG_DEBUG, "input history file corrupted, discarding (path:%s)", history_filename.c_str());
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
lt_log_print(torrent::LOG_DEBUG_TRACE, "input history file read (path:%s)", history_filename.c_str());
|
lt_log_print(torrent::LOG_DEBUG, "input history file read (path:%s)", history_filename.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& [entry, category] : input_history_tmp) {
|
for (const auto& [entry, category] : input_history_tmp) {
|
||||||
@@ -441,7 +441,7 @@ Root::load_input_history() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
lt_log_print(torrent::LOG_DEBUG_TRACE, "could not open input history file (path:%s)", history_filename.c_str());
|
lt_log_print(torrent::LOG_DEBUG, "could not open input history file (path:%s)", history_filename.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -455,7 +455,7 @@ Root::save_input_history() {
|
|||||||
auto history_file = std::fstream(history_filename_tmp.c_str(), std::ios::out | std::ios::trunc);
|
auto history_file = std::fstream(history_filename_tmp.c_str(), std::ios::out | std::ios::trunc);
|
||||||
|
|
||||||
if (!history_file.is_open()) {
|
if (!history_file.is_open()) {
|
||||||
lt_log_print(torrent::LOG_DEBUG_TRACE, "could not open input history file for writing (path:%s)", history_filename.c_str());
|
lt_log_print(torrent::LOG_DEBUG, "could not open input history file for writing (path:%s)", history_filename.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -471,10 +471,10 @@ Root::save_input_history() {
|
|||||||
history_file.close();
|
history_file.close();
|
||||||
|
|
||||||
if (!history_file.good()) {
|
if (!history_file.good()) {
|
||||||
lt_log_print(torrent::LOG_DEBUG_TRACE, "input history file corrupted during writing, discarding (path:%s)", history_filename.c_str());
|
lt_log_print(torrent::LOG_DEBUG, "input history file corrupted during writing, discarding (path:%s)", history_filename.c_str());
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
lt_log_print(torrent::LOG_DEBUG_TRACE, "input history file written (path:%s)", history_filename.c_str());
|
lt_log_print(torrent::LOG_DEBUG, "input history file written (path:%s)", history_filename.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::rename(history_filename_tmp.c_str(), history_filename.c_str());
|
std::rename(history_filename_tmp.c_str(), history_filename.c_str());
|
||||||
|
|||||||
@@ -71,18 +71,10 @@ rtorrent_Test_Src_SOURCES = $(rtorrent_Test_Common) \
|
|||||||
src/test_command_path.h \
|
src/test_command_path.h \
|
||||||
src/test_command_string.cc \
|
src/test_command_string.cc \
|
||||||
src/test_command_string.h \
|
src/test_command_string.h \
|
||||||
src/test_command_throttle.cc \
|
|
||||||
src/test_command_throttle.h \
|
|
||||||
src/test_command_tracker.cc \
|
src/test_command_tracker.cc \
|
||||||
src/test_command_tracker.h \
|
src/test_command_tracker.h \
|
||||||
src/test_download_list.cc \
|
src/test_download_list.cc \
|
||||||
src/test_download_list.h \
|
src/test_download_list.h \
|
||||||
src/test_input_path_input.cc \
|
|
||||||
src/test_input_path_input.h \
|
|
||||||
src/test_session_commit.cc \
|
|
||||||
src/test_session_commit.h \
|
|
||||||
src/test_session_storer.cc \
|
|
||||||
src/test_session_storer.h \
|
|
||||||
src/test_setup.cc \
|
src/test_setup.cc \
|
||||||
src/test_setup.h \
|
src/test_setup.h \
|
||||||
src/test_ui_download_list.cc \
|
src/test_ui_download_list.cc \
|
||||||
|
|||||||
@@ -2,10 +2,7 @@
|
|||||||
|
|
||||||
#include "test/rpc/test_command.h"
|
#include "test/rpc/test_command.h"
|
||||||
|
|
||||||
#include <torrent/exceptions.h>
|
|
||||||
|
|
||||||
#include "rpc/command.h"
|
#include "rpc/command.h"
|
||||||
#include "rpc/parse_commands.h"
|
|
||||||
|
|
||||||
CPPUNIT_TEST_SUITE_REGISTRATION(TestCommand);
|
CPPUNIT_TEST_SUITE_REGISTRATION(TestCommand);
|
||||||
|
|
||||||
@@ -86,50 +83,3 @@ TestCommand::test_stack_double() {
|
|||||||
rpc::command_base::pop_stack(&stack_first, last_stack_first);
|
rpc::command_base::pop_stack(&stack_first, last_stack_first);
|
||||||
CPPUNIT_ASSERT(command_stack_all_empty());
|
CPPUNIT_ASSERT(command_stack_all_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
TestCommand::test_preparsed_commands() {
|
|
||||||
unsigned int prepare_count = 0;
|
|
||||||
rpc::preparsed_commands commands([&prepare_count](auto& prepared) {
|
|
||||||
++prepare_count;
|
|
||||||
// Reentrant access must not invoke the same callback recursively.
|
|
||||||
prepared.prepare_if_needed();
|
|
||||||
prepared.push_back(rpc::parse_command_object("string.length=abc"));
|
|
||||||
});
|
|
||||||
|
|
||||||
CPPUNIT_ASSERT_EQUAL(0u, prepare_count);
|
|
||||||
CPPUNIT_ASSERT(commands.empty());
|
|
||||||
|
|
||||||
commands.prepare_if_needed();
|
|
||||||
CPPUNIT_ASSERT_EQUAL(1u, prepare_count);
|
|
||||||
|
|
||||||
size_t count = 0;
|
|
||||||
for (auto& itr : commands) {
|
|
||||||
CPPUNIT_ASSERT(itr.is_dict_key());
|
|
||||||
++count;
|
|
||||||
}
|
|
||||||
|
|
||||||
CPPUNIT_ASSERT_EQUAL(size_t(1), count);
|
|
||||||
CPPUNIT_ASSERT_EQUAL(1u, prepare_count);
|
|
||||||
|
|
||||||
for (auto& itr : commands)
|
|
||||||
CPPUNIT_ASSERT(itr.is_dict_key());
|
|
||||||
|
|
||||||
CPPUNIT_ASSERT_EQUAL(1u, prepare_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TestCommand::test_parse_command_object() {
|
|
||||||
auto command = rpc::parse_command_object("\tstring.length=abc ");
|
|
||||||
CPPUNIT_ASSERT(command.is_dict_key());
|
|
||||||
CPPUNIT_ASSERT_EQUAL(std::string("string.length"), command.as_dict_key());
|
|
||||||
|
|
||||||
// This helper has no way to return the next-command pointer, so it must not
|
|
||||||
// silently accept a multipart command separated by ';'.
|
|
||||||
CPPUNIT_ASSERT_THROW(rpc::parse_command_object("string.length=abc;string.length=def"), torrent::input_error);
|
|
||||||
|
|
||||||
// Unlike parse_command (which parses command files), this helper handles one
|
|
||||||
// multicall command and must reject newline boundaries, including CRLF.
|
|
||||||
CPPUNIT_ASSERT_THROW(rpc::parse_command_object("string.length=abc\nstring.length=def"), torrent::input_error);
|
|
||||||
CPPUNIT_ASSERT_THROW(rpc::parse_command_object("string.length=abc\r\nstring.length=def"), torrent::input_error);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -5,14 +5,10 @@ class TestCommand : public test_fixture {
|
|||||||
|
|
||||||
CPPUNIT_TEST(test_stack);
|
CPPUNIT_TEST(test_stack);
|
||||||
CPPUNIT_TEST(test_stack_double);
|
CPPUNIT_TEST(test_stack_double);
|
||||||
CPPUNIT_TEST(test_preparsed_commands);
|
|
||||||
CPPUNIT_TEST(test_parse_command_object);
|
|
||||||
|
|
||||||
CPPUNIT_TEST_SUITE_END();
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void test_stack();
|
void test_stack();
|
||||||
void test_stack_double();
|
void test_stack_double();
|
||||||
void test_preparsed_commands();
|
|
||||||
void test_parse_command_object();
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ assert_arg_count_error(const std::string& line) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
TestSetup::test_config_comment_log_add_output() {
|
TestSetup::test_config_comment_log_add_output() {
|
||||||
temp_config_file file("# do:log.add_output=debug_trace,test_output");
|
temp_config_file file("# do:log.add_output=debug,test_output");
|
||||||
|
|
||||||
CPPUNIT_ASSERT_NO_THROW(parse_config_file_comments(file.path()));
|
CPPUNIT_ASSERT_NO_THROW(parse_config_file_comments(file.path()));
|
||||||
}
|
}
|
||||||
@@ -69,10 +69,10 @@ TestSetup::test_config_comment_log_add_output_no_args() {
|
|||||||
|
|
||||||
void
|
void
|
||||||
TestSetup::test_config_comment_log_add_output_one_arg() {
|
TestSetup::test_config_comment_log_add_output_one_arg() {
|
||||||
assert_arg_count_error("# do:log.add_output=debug_trace");
|
assert_arg_count_error("# do:log.add_output=debug");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TestSetup::test_config_comment_log_add_output_too_many_args() {
|
TestSetup::test_config_comment_log_add_output_too_many_args() {
|
||||||
assert_arg_count_error("# do:log.add_output=debug_trace,test_output,extra");
|
assert_arg_count_error("# do:log.add_output=debug,test_output,extra");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user