Compare commits

...

9 Commits

Author SHA1 Message Date
rakshasa efd9507149 Release 0.16.3. 2025-11-21 14:39:27 +01:00
Jari Sundell 3d91dfdb33 Valgrind suppressions file for macos. 2025-11-20 15:57:30 +09:00
Jari Sundell 30cec98799 Moved Poll to net namespace. 2025-11-20 03:05:16 +09:00
rakshasa b825906034 Store copies of command names added to xmlrpc-c. 2025-11-17 20:30:13 +01:00
rakshasa b05ecb5c5a Push back views explicitly takes a string. 2025-11-17 09:36:32 +01:00
Jari Sundell 900be334dc Cleaned up xmlrpc-c string sanitization. 2025-11-17 02:48:32 +09:00
rakshasa 3a1da2fe34 Check if AF_INET6 is supported, or block IPv6 traffic. 2025-11-15 09:17:56 +01:00
Jari Sundell 70750a2bd3 Cleanup of DHT controller. 2025-11-13 00:01:22 +09:00
Jari Sundell 1d2c424a70 Remove throttle from DHT. 2025-11-08 17:51:00 +09:00
28 changed files with 628 additions and 423 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
m4_pattern_allow([PKG_CHECK_EXISTS])
AC_INIT([rtorrent],[0.16.2],[sundell.software@gmail.com])
AC_INIT([rtorrent],[0.16.3],[sundell.software@gmail.com])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIRS([scripts])
@@ -48,7 +48,7 @@ if test "x$ax_cv_ncursesw" != xyes && test "x$ax_cv_ncurses" != xyes; then
fi
PKG_CHECK_MODULES([CPPUNIT], [cppunit],, [no_cppunit="yes"])
PKG_CHECK_MODULES([DEPENDENCIES], [libtorrent >= 0.16.2])
PKG_CHECK_MODULES([DEPENDENCIES], [libtorrent >= 0.16.3])
AC_LANG_PUSH(C++)
TORRENT_WITH_XMLRPC_C
+343
View File
@@ -0,0 +1,343 @@
{
<insert_a_suppression_name_here>
Memcheck:Cond
...
fun:__76-*
}
{
<insert_a_suppression_name_here>
Memcheck:Value8
...
fun:__76-*
}
{
<insert_a_suppression_name_here>
Memcheck:Value8
...
fun:__80-*
}
{
<insert_a_suppression_name_here>
Memcheck:Cond
...
fun:__93-*
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:__93-*
}
{
<insert_a_suppression_name_here>
Memcheck:Cond
...
fun:__108-*
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:__108-*
}
{
<insert_a_suppression_name_here>
Memcheck:Value8
...
fun:__108-*
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:-[CFPrefsPlistSource setDomainIdentifier:]
}
{
<insert_a_suppression_name_here>
Memcheck:Cond
...
fun:-[CFPrefsSearchListSource alreadylocked_copyValueForKey:]
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:-[CFPrefsSearchListSource alreadylocked_copyValueForKey:]
}
{
<insert_a_suppression_name_here>
Memcheck:Value8
...
fun:-[CFPrefsSearchListSource alreadylocked_copyValueForKey:]
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:-[CFPrefsSearchListSource addNamedVolatileSourceForIdentifier:]
}
{
<insert_a_suppression_name_here>
Memcheck:Cond
...
fun:-[CFPrefsSearchListSource handleReply:toRequestNewDataMessage:onConnection:retryCount:error:]
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:-[CFPrefsSearchListSource addSourceForIdentifier:user:byHost:container:]
}
{
<insert_a_suppression_name_here>
Memcheck:Value8
...
fun:-[CFPrefsSearchListSource handleReply:toRequestNewDataMessage:onConnection:retryCount:error:]
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:-[CFPrefsSearchListSource handleReply:toRequestNewDataMessage:onConnection:retryCount:error:]
}
{
<insert_a_suppression_name_here>
Memcheck:Value8
...
fun:-[CFPrefsSearchListSource handleReply:toRequestNewDataMessage:onConnection:retryCount:error:]
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:-[_CFXPreferences copyAppValueForKey:identifier:container:configurationURL:]
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:-[_CFXPreferences withSearchListForIdentifier:container:cloudConfigurationURL:perform:]
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:-[_CFXPreferences withSearchLists:]
}
{
<insert_a_suppression_name_here>
Memcheck:Value8
...
fun:-[CFPrefsSource copyValueForKey:]
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:-[OS_xpc_object dealloc]
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:_CF*
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:__CF*
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:_NS*
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:getSuperclassMetadata
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:_ZN5dyld*
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:_ZNK5dyld*
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:___ZNK5dyld*
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:_dyld_*
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:*_dyld_*
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:___SC_getApplicationBundleID_block_invoke
}
{
<insert_a_suppression_name_here>
Memcheck:Cond
...
fun:xpc_*
}
{
<insert_a_suppression_name_here>
Memcheck:Value8
...
fun:xpc_*
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:_xpc_*
}
{
<insert_a_suppression_name_here>
Memcheck:Cond
...
fun:_xpc_*
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:_libxpc_*
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:si_module_with_name
}
{
<insert_a_suppression_name_here>
Memcheck:Cond
...
fun:_dispatch_*
}
{
<insert_a_suppression_name_here>
Memcheck:Value8
...
fun:_dispatch_*
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:_dispatch_*
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:*_swift_*
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:libdispatch_init
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:_os_*
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:_od_*
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:_objc_init
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:_notify_*
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:bootstrap_*
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:$ss*
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:loadlocale
fun:setlocale
fun:main
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:initscr
fun:_ZN7display6Canvas10initializeEv
fun:_ZN7Control10initializeEv
fun:main
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:assume_default_colors_sp
fun:_ZN7display6Canvas10initializeEv
fun:_ZN7Control10initializeEv
fun:main
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:start_color_sp
fun:_ZN7display6Canvas10initializeEv
fun:_ZN7Control10initializeEv
fun:main
}
{
<insert_a_suppression_name_here>
Memcheck:Leak
...
fun:_ZN7display6Canvas10initializeEv
}
+4 -7
View File
@@ -539,16 +539,13 @@ download_set_variable_string(core::Download* download, const torrent::Object::st
//
torrent::Object
d_list_push_back_string(core::Download* download, const torrent::Object& rawArgs, const char* first_key, const char* second_key) {
auto& arg = rawArgs.as_string();
d_list_push_back_string(core::Download* download, const std::string& arg, const char* first_key, const char* second_key) {
download_get_variable(download, first_key, second_key).as_list().push_back(arg);
return torrent::Object();
}
torrent::Object
d_list_push_back_unique_string(core::Download* download, const torrent::Object& rawArgs, const char* first_key, const char* second_key) {
auto& arg = rawArgs.as_string();
d_list_push_back_unique_string(core::Download* download, const std::string& arg, const char* first_key, const char* second_key) {
torrent::Object::list_type& list = download_get_variable(download, first_key, second_key).as_list();
if (std::none_of(list.begin(), list.end(), [arg](const torrent::Object& obj) { return torrent::object_equal(obj, arg); }))
@@ -769,8 +766,8 @@ initialize_command_download() {
CMD2_DL ("d.views", std::bind(&download_get_variable, std::placeholders::_1, "rtorrent", "views"));
CMD2_DL ("d.views.has", std::bind(&d_list_has, std::placeholders::_1, std::placeholders::_2, "rtorrent", "views"));
CMD2_DL ("d.views.remove", std::bind(&d_list_remove, std::placeholders::_1, std::placeholders::_2, "rtorrent", "views"));
CMD2_DL ("d.views.push_back", std::bind(&d_list_push_back_string, std::placeholders::_1, std::placeholders::_2, "rtorrent", "views"));
CMD2_DL ("d.views.push_back_unique", std::bind(&d_list_push_back_unique_string, std::placeholders::_1, std::placeholders::_2, "rtorrent", "views"));
CMD2_DL_STRING ("d.views.push_back", std::bind(&d_list_push_back_string, std::placeholders::_1, std::placeholders::_2, "rtorrent", "views"));
CMD2_DL_STRING ("d.views.push_back_unique", std::bind(&d_list_push_back_unique_string, std::placeholders::_1, std::placeholders::_2, "rtorrent", "views"));
// This command really needs to be improved, so we have proper
// logging support.
+4 -5
View File
@@ -4,6 +4,7 @@
#include <cstdio>
#include <netdb.h>
#include <torrent/net/network_config.h>
#include <torrent/net/network_manager.h>
#include <torrent/net/resolver.h>
#include <torrent/tracker/dht_controller.h>
#include <torrent/tracker/tracker.h>
@@ -27,7 +28,7 @@ tracker_set_enabled(torrent::tracker::Tracker* tracker, bool state) {
torrent::Object
apply_dht_add_node(const std::string& arg) {
if (!torrent::dht_controller()->is_valid())
if (!torrent::runtime::network_manager()->is_dht_valid())
throw torrent::input_error("DHT not enabled.");
int port;
@@ -58,7 +59,7 @@ apply_dht_add_node(const std::string& arg) {
}
lt_log_print(torrent::LOG_DHT_CONTROLLER, "dht.add_node : %s", host_str.c_str());
torrent::dht_controller()->add_node(sa.get(), port);
torrent::runtime::network_manager()->dht_add_peer_node(sa.get(), port);
});
return torrent::Object();
@@ -144,7 +145,7 @@ initialize_command_tracker() {
auto dht_manager = control->dht_manager();
CMD2_ANY_STRING_V ("dht.mode.set", std::bind(&core::DhtManager::set_mode, control->dht_manager(), std::placeholders::_2));
CMD2_ANY ("dht.port", std::bind(&torrent::tracker::DhtController::port, torrent::dht_controller()));
CMD2_ANY ("dht.port", [](auto, auto) { return torrent::runtime::network_manager()->dht_controller()->port(); });
CMD2_ANY_VALUE_V ("dht.port.set", [](auto, auto) {
lt_log_print(torrent::LOG_DHT_ERROR, "dht.port.set is no longer supported, use dht.override_port.set", 0);
});
@@ -153,6 +154,4 @@ initialize_command_tracker() {
CMD2_ANY_STRING ("dht.add_node", std::bind(&apply_dht_add_node, std::placeholders::_2));
CMD2_ANY ("dht.statistics", std::bind(&core::DhtManager::dht_statistics, dht_manager));
CMD2_ANY ("dht.throttle.name", std::bind(&core::DhtManager::throttle_name, dht_manager));
CMD2_ANY_STRING_V ("dht.throttle.name.set", std::bind(&core::DhtManager::set_throttle_name, dht_manager, std::placeholders::_2));
}
+3 -2
View File
@@ -58,6 +58,8 @@ Control::~Control() {
void
Control::initialize() {
worker_thread->start_thread();
display::Canvas::initialize();
display::Window::slot_schedule([this](display::Window* w, std::chrono::microseconds t) { m_display->schedule(w, t); });
display::Window::slot_unschedule([this](display::Window* w) { m_display->unschedule(w); });
@@ -81,9 +83,8 @@ Control::cleanup() {
torrent::this_thread::scheduler()->erase(&m_task_shutdown);
if(!display::Canvas::daemon()) {
if(!display::Canvas::daemon())
m_inputStdin->remove(torrent::this_thread::poll());
}
m_core->download_store()->disable();
+28 -42
View File
@@ -1,22 +1,22 @@
#include "config.h"
#include "dht_manager.h"
#include <fstream>
#include <sstream>
#include <torrent/object.h>
#include <torrent/object_stream.h>
#include <torrent/net/network_manager.h>
#include <torrent/rate.h>
#include <torrent/tracker/dht_controller.h>
#include <torrent/utils/log.h>
#include "rpc/parse_commands.h"
#include "globals.h"
#include "control.h"
#include "dht_manager.h"
#include "download.h"
#include "download_store.h"
#include "globals.h"
#include "manager.h"
#include "rpc/parse_commands.h"
#define LT_LOG(log_fmt, ...) \
lt_log_print_subsystem(torrent::LOG_DHT_CONTROLLER, "dht_manager", log_fmt, __VA_ARGS__);
@@ -61,7 +61,7 @@ DhtManager::load_dht_cache() {
LT_LOG("could not open cache file (path:%s)", cache_filename.c_str());
}
torrent::dht_controller()->initialize(cache);
torrent::runtime::network_manager()->dht_controller()->initialize(cache);
if (m_start == dht_on)
start_dht();
@@ -71,26 +71,22 @@ void
DhtManager::start_dht() {
torrent::this_thread::scheduler()->erase(&m_stop_timeout);
if (!torrent::dht_controller()->is_valid()) {
if (!torrent::runtime::network_manager()->is_dht_valid()) {
LT_LOG("server start skipped, manager is uninitialized", 0);
return;
}
if (torrent::dht_controller()->is_active()) {
if (torrent::runtime::network_manager()->is_dht_active()) {
LT_LOG("server start skipped, already active", 0);
return;
}
torrent::ThrottlePair throttles = control->core()->get_throttle(m_throttleName);
torrent::dht_controller()->set_upload_throttle(throttles.first);
torrent::dht_controller()->set_download_throttle(throttles.second);
if (!torrent::dht_controller()->start()) {
if (!torrent::runtime::network_manager()->dht_controller()->start()) {
m_start = dht_off;
return;
}
torrent::dht_controller()->reset_statistics();
torrent::runtime::network_manager()->dht_controller()->reset_statistics();
m_update_timeout.slot() = std::bind(&DhtManager::update, this);
@@ -109,17 +105,19 @@ DhtManager::stop_dht() {
torrent::this_thread::scheduler()->erase(&m_update_timeout);
torrent::this_thread::scheduler()->erase(&m_stop_timeout);
if (torrent::dht_controller()->is_active()) {
if (torrent::runtime::network_manager()->is_dht_active()) {
LT_LOG("stopping server", 0);
log_statistics(true);
torrent::dht_controller()->stop();
torrent::runtime::network_manager()->dht_controller()->stop();
}
}
void
DhtManager::save_dht_cache() {
if (!control->core()->download_store()->is_enabled() || !torrent::dht_controller()->is_valid())
if (!control->core()->download_store()->is_enabled())
return;
if (!torrent::runtime::network_manager()->is_dht_valid())
return;
std::string filename = control->core()->download_store()->path() + "rtorrent.dht_cache";
@@ -130,7 +128,7 @@ DhtManager::save_dht_cache() {
return;
torrent::Object cache = torrent::Object::create_map();
cache_file << *torrent::dht_controller()->store_cache(&cache);
cache_file << *torrent::runtime::network_manager()->dht_controller()->store_cache(&cache);
if (!cache_file.good())
return;
@@ -161,7 +159,7 @@ DhtManager::set_mode(const std::string& arg) {
void
DhtManager::update() {
if (!torrent::dht_controller()->is_active())
if (!torrent::runtime::network_manager()->is_dht_active())
throw torrent::internal_error("DhtManager::update called with DHT inactive.");
if (m_start == dht_auto && !m_stop_timeout.is_scheduled()) {
@@ -186,17 +184,17 @@ DhtManager::update() {
bool
DhtManager::log_statistics(bool force) {
auto stats = torrent::dht_controller()->get_statistics();
auto stats = torrent::runtime::network_manager()->dht_controller()->get_statistics();
// Check for firewall problems.
if (stats.cycle > 2 && stats.queries_sent - m_dhtPrevQueriesSent > 100 && stats.queries_received == m_dhtPrevQueriesReceived) {
// We should have had clients ping us at least but have received
// nothing, that means the UDP port is probably unreachable.
if (torrent::dht_controller()->is_receiving_requests())
if (torrent::runtime::network_manager()->is_dht_active_and_receiving_requests())
LT_LOG("listening port appears to be unreachable, no queries received", 0);
torrent::dht_controller()->set_receive_requests(false);
torrent::runtime::network_manager()->dht_controller()->set_receive_requests(false);
}
if (stats.queries_sent - m_dhtPrevQueriesSent > stats.num_nodes * 2 + 20 && stats.replies_received == m_dhtPrevRepliesReceived) {
@@ -211,7 +209,7 @@ DhtManager::log_statistics(bool force) {
m_warned = false;
if (stats.queries_received > m_dhtPrevQueriesReceived)
torrent::dht_controller()->set_receive_requests(true);
torrent::runtime::network_manager()->dht_controller()->set_receive_requests(true);
// Nothing to log while bootstrapping, but check again every minute.
if (stats.cycle <= 1) {
@@ -233,13 +231,11 @@ DhtManager::log_statistics(bool force) {
if ((force && stats.cycle != m_dhtPrevCycle) || stats.cycle == 3 || stats.cycle > m_dhtPrevCycle + 7) {
char buffer[256];
snprintf(buffer, sizeof(buffer),
"DHT statistics: %d queries in, %d queries out, %d replies received, %lld bytes read, %lld bytes sent, "
"DHT statistics: %d queries in, %d queries out, %d replies received, "
"%d known nodes in %d buckets, %d peers (highest: %d) tracked in %d torrents.",
stats.queries_received - m_dhtPrevQueriesReceived,
stats.queries_sent - m_dhtPrevQueriesSent,
stats.replies_received - m_dhtPrevRepliesReceived,
(long long unsigned int)(stats.down_rate.total() - m_dhtPrevBytesDown),
(long long unsigned int)(stats.up_rate.total() - m_dhtPrevBytesUp),
stats.num_nodes,
stats.num_buckets,
stats.num_peers,
@@ -252,8 +248,6 @@ DhtManager::log_statistics(bool force) {
m_dhtPrevQueriesSent = stats.queries_sent;
m_dhtPrevRepliesReceived = stats.replies_received;
m_dhtPrevQueriesReceived = stats.queries_received;
m_dhtPrevBytesUp = stats.up_rate.total();
m_dhtPrevBytesDown = stats.down_rate.total();
}
return false;
@@ -264,11 +258,11 @@ DhtManager::dht_statistics() {
torrent::Object dhtStats = torrent::Object::create_map();
dhtStats.insert_key("dht", dht_settings[m_start]);
dhtStats.insert_key("active", torrent::dht_controller()->is_active());
dhtStats.insert_key("throttle", m_throttleName);
dhtStats.insert_key("active", torrent::runtime::network_manager()->is_dht_active());
dhtStats.insert_key("throttle", "");
if (torrent::dht_controller()->is_active()) {
auto stats = torrent::dht_controller()->get_statistics();
if (torrent::runtime::network_manager()->is_dht_active()) {
auto stats = torrent::runtime::network_manager()->dht_controller()->get_statistics();
dhtStats.insert_key("cycle", stats.cycle);
dhtStats.insert_key("queries_received", stats.queries_received);
@@ -276,8 +270,8 @@ DhtManager::dht_statistics() {
dhtStats.insert_key("replies_received", stats.replies_received);
dhtStats.insert_key("errors_received", stats.errors_received);
dhtStats.insert_key("errors_caught", stats.errors_caught);
dhtStats.insert_key("bytes_read", stats.down_rate.total());
dhtStats.insert_key("bytes_written", stats.up_rate.total());
dhtStats.insert_key("bytes_read", int64_t());
dhtStats.insert_key("bytes_written", int64_t());
dhtStats.insert_key("nodes", stats.num_nodes);
dhtStats.insert_key("buckets", stats.num_buckets);
dhtStats.insert_key("peers", stats.num_peers);
@@ -288,12 +282,4 @@ DhtManager::dht_statistics() {
return dhtStats;
}
void
DhtManager::set_throttle_name(const std::string& throttleName) {
if (torrent::dht_controller()->is_active())
throw torrent::input_error("Cannot set DHT throttle while active.");
m_throttleName = throttleName;
}
}
-5
View File
@@ -20,9 +20,6 @@ public:
void set_mode(const std::string& arg);
void set_throttle_name(const std::string& throttleName);
const std::string& throttle_name() const { return m_throttleName; }
private:
static const int dht_disable = 0;
static const int dht_off = 1;
@@ -47,8 +44,6 @@ private:
bool m_warned{};
int m_start{dht_off};
std::string m_throttleName;
};
}
+38 -30
View File
@@ -11,23 +11,31 @@
namespace display {
bool Canvas::m_isInitialized = false;
bool Canvas::m_isDaemon = false;
bool Canvas::m_initialized{};
bool Canvas::m_daemon{};
// Maps ncurses color IDs to a ncurses attribute int
std::unordered_map<int, int> Canvas::m_attr_map = {};
Canvas::Canvas(int x, int y, int width, int height) {
if (!m_isDaemon) {
if (!m_daemon) {
m_window = newwin(height, width, y, x);
if (m_window == NULL)
if (m_window == nullptr)
throw torrent::internal_error("Could not allocate ncurses canvas.");
}
}
Canvas::~Canvas() {
if (!m_daemon && m_window != nullptr) {
delwin(m_window);
m_window = nullptr;
}
}
void
Canvas::resize(int x, int y, int w, int h) {
if (!m_isDaemon) {
if (!m_daemon) {
wresize(m_window, h, w);
mvwin(m_window, y, x);
}
@@ -35,7 +43,7 @@ Canvas::resize(int x, int y, int w, int h) {
void
Canvas::print_attributes(unsigned int x, unsigned int y, const char* first, const char* last, const attributes_list* attributes) {
if (!m_isDaemon) {
if (!m_daemon) {
move(x, y);
attr_t org_attr;
@@ -68,14 +76,13 @@ Canvas::print_attributes(unsigned int x, unsigned int y, const char* first, cons
void
Canvas::initialize() {
if (m_isInitialized)
return;
if (m_initialized)
throw torrent::internal_error("Canvas::initialize() called more than once.");
m_isDaemon = rpc::call_command_value("system.daemon");
m_daemon = rpc::call_command_value("system.daemon");
m_initialized = true;
m_isInitialized = true;
if (!m_isDaemon) {
if (!m_daemon) {
initscr();
start_color();
use_default_colors();
@@ -88,6 +95,19 @@ Canvas::initialize() {
}
}
void
Canvas::cleanup() {
if (!m_initialized)
return;
m_initialized = false;
if (!m_daemon) {
noraw();
endwin();
}
}
// Function wrapper for what possibly is a macro
int
get_colors() {
@@ -102,7 +122,7 @@ Canvas::build_colors() {
// This may get called early in the start process by the config
// file, so we need to delay building until initscr() has a chance
// to run
if (!m_isInitialized || m_isDaemon)
if (!m_initialized || m_daemon)
return;
// basic color names, index maps to ncurses COLOR_*
@@ -115,7 +135,9 @@ Canvas::build_colors() {
for (int k = 1; k < RCOLOR_MAX; k++) {
init_pair(k, -1, -1);
std::string color_def = rpc::call_command_string(color_vars[k]);
if (color_def.empty())
continue; // Use terminal default if definition is empty
@@ -126,6 +148,7 @@ Canvas::build_colors() {
// Process string as space-separated words
size_t start = 0, end = 0;
while (true) {
end = color_def.find(' ', start);
std::string word = color_def.substr(start, end - start);
@@ -169,10 +192,8 @@ Canvas::build_colors() {
// Check that fg & bg color index is valid
if ((color[0] != -1 && color[0] >= get_colors()) || (color[1] != -1 && color[1] >= get_colors())) {
char buf[33];
snprintf(buf, 33, "%d", get_colors());
Canvas::cleanup();
throw torrent::input_error(color_def + ": your terminal only supports " + buf + " colors.");
throw torrent::input_error(color_def + ": your terminal only supports " + std::to_string(get_colors()) + " colors.");
}
m_attr_map[k] = attr; // overwrite or insert the value
@@ -196,24 +217,11 @@ Canvas::build_colors() {
}
}
void
Canvas::cleanup() {
if (!m_isInitialized)
return;
m_isInitialized = false;
if (!m_isDaemon) {
noraw();
endwin();
}
}
std::pair<int, int>
Canvas::term_size() {
struct winsize ws;
if (!m_isDaemon) {
if (!m_daemon) {
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == 0)
return std::pair<int, int>(ws.ws_col, ws.ws_row);
}
+29 -34
View File
@@ -54,9 +54,10 @@ public:
// Initialize stdscr.
static void initialize();
static void build_colors();
static void cleanup();
static void build_colors();
static int get_screen_width();
static int get_screen_height();
@@ -64,15 +65,15 @@ public:
static void do_update();
static bool daemon() { return m_isDaemon; }
static bool daemon() { return m_daemon; }
static const attributes_map& attr_map() { return m_attr_map; }
private:
Canvas(const Canvas&);
void operator=(const Canvas&);
static bool m_isInitialized;
static bool m_isDaemon;
static bool m_initialized;
static bool m_daemon;
// Maps ncurses color IDs to a ncurses attribute int
static std::unordered_map<int, int> m_attr_map;
@@ -80,57 +81,51 @@ private:
WINDOW* m_window;
};
inline Canvas::~Canvas() {
if (!m_isDaemon) {
delwin(m_window);
}
}
inline void
Canvas::refresh() {
if (!m_isDaemon) {
if (!m_daemon) {
wnoutrefresh(m_window);
}
}
inline void
Canvas::refresh_std() {
if (!m_isDaemon) {
if (!m_daemon) {
wnoutrefresh(stdscr);
}
}
inline void
Canvas::redraw() {
if (!m_isDaemon) {
if (!m_daemon) {
redrawwin(m_window);
}
}
inline void
Canvas::redraw_std() {
if (!m_isDaemon) {
if (!m_daemon) {
redrawwin(stdscr);
}
}
inline void
Canvas::resize(int w, int h) {
if (!m_isDaemon) {
if (!m_daemon) {
wresize(m_window, h, w);
}
}
inline void
Canvas::resize_term(int x, int y) {
if (!m_isDaemon) {
if (!m_daemon) {
resizeterm(y, x);
}
}
inline void
Canvas::resize_term(std::pair<int, int> dim) {
if (!m_isDaemon) {
if (!m_daemon) {
resizeterm(dim.second, dim.first);
}
}
@@ -139,7 +134,7 @@ inline unsigned int
Canvas::get_x() {
int x;
[[maybe_unused]] int y;
if (!m_isDaemon) {
if (!m_daemon) {
getyx(m_window, y, x);
} else {
x = 1;
@@ -150,7 +145,7 @@ Canvas::get_x() {
inline unsigned int
Canvas::get_y() {
int x, y;
if (!m_isDaemon) {
if (!m_daemon) {
getyx(m_window, y, x);
} else {
y = 1;
@@ -162,7 +157,7 @@ inline unsigned int
Canvas::width() {
int x;
[[maybe_unused]] int y;
if (!m_isDaemon) {
if (!m_daemon) {
getmaxyx(m_window, y, x);
} else {
x = 80;
@@ -173,7 +168,7 @@ Canvas::width() {
inline unsigned int
Canvas::height() {
int x, y;
if (!m_isDaemon) {
if (!m_daemon) {
getmaxyx(m_window, y, x);
} else {
y = 24;
@@ -183,21 +178,21 @@ Canvas::height() {
inline void
Canvas::move(unsigned int x, unsigned int y) {
if (!m_isDaemon) {
if (!m_daemon) {
wmove(m_window, y, x);
}
}
inline void
Canvas::erase() {
if (!m_isDaemon) {
if (!m_daemon) {
werase(m_window);
}
}
inline void
Canvas::erase_std() {
if (!m_isDaemon) {
if (!m_daemon) {
werase(stdscr);
}
}
@@ -206,7 +201,7 @@ inline void
Canvas::print(const char* str, ...) {
va_list arglist;
if (!m_isDaemon) {
if (!m_daemon) {
va_start(arglist, str);
vw_printw(m_window, const_cast<char*>(str), arglist);
va_end(arglist);
@@ -217,7 +212,7 @@ inline void
Canvas::print(unsigned int x, unsigned int y, const char* str, ...) {
va_list arglist;
if (!m_isDaemon) {
if (!m_daemon) {
va_start(arglist, str);
wmove(m_window, y, x);
vw_printw(m_window, const_cast<char*>(str), arglist);
@@ -227,35 +222,35 @@ Canvas::print(unsigned int x, unsigned int y, const char* str, ...) {
inline void
Canvas::print_char(const chtype ch) {
if (!m_isDaemon) {
if (!m_daemon) {
waddch(m_window, ch);
}
}
inline void
Canvas::print_char(unsigned int x, unsigned int y, const chtype ch) {
if (!m_isDaemon) {
if (!m_daemon) {
mvwaddch(m_window, y, x, ch);
}
}
inline void
Canvas::set_attr(unsigned int x, unsigned int y, unsigned int n, int attr, int color) {
if (!m_isDaemon) {
if (!m_daemon) {
mvwchgat(m_window, y, x, n, attr, color, NULL);
}
}
inline void
Canvas::set_attr(unsigned int x, unsigned int y, unsigned int n, ColorKind k) {
if (!m_isDaemon) {
if (!m_daemon) {
mvwchgat(m_window, y, x, n, m_attr_map[k], k, NULL);
}
}
inline void
Canvas::set_default_attributes(int attr) {
if (!m_isDaemon) {
if (!m_daemon) {
(void)wattrset(m_window, attr);
}
}
@@ -264,7 +259,7 @@ inline int
Canvas::get_screen_width() {
int x;
[[maybe_unused]] int y;
if (!m_isDaemon) {
if (!m_daemon) {
getmaxyx(stdscr, y, x);
} else {
x = 80;
@@ -275,7 +270,7 @@ Canvas::get_screen_width() {
inline int
Canvas::get_screen_height() {
int x, y;
if (!m_isDaemon) {
if (!m_daemon) {
getmaxyx(stdscr, y, x);
} else {
y = 24;
@@ -285,7 +280,7 @@ Canvas::get_screen_height() {
inline void
Canvas::do_update() {
if (!m_isDaemon) {
if (!m_daemon) {
doupdate();
}
}
+14 -49
View File
@@ -1,47 +1,12 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <sundell.software@gmail.com>
#include "config.h"
#include "display/frame.h"
#include <algorithm>
#include <functional>
#include <rak/algorithm.h>
#include <torrent/exceptions.h>
#include "frame.h"
#include "window.h"
#include "display/window.h"
namespace display {
@@ -137,7 +102,7 @@ Frame::preferred_size() const {
for (size_type i = 0; i < m_containerSize; ++i) {
bounds_type p = m_container[i]->preferred_size();
accum.minWidth += p.minWidth;
accum.minHeight += p.minHeight;
@@ -221,7 +186,7 @@ Frame::clear() {
m_window->set_offscreen(true);
break;
case TYPE_ROW:
case TYPE_COLUMN:
for (size_type i = 0; i < m_containerSize; ++i) {
@@ -335,10 +300,10 @@ Frame::balance_row(uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
dynamic_type dynamicFrames[max_size];
int remaining = height;
for (Frame **itr = m_container, **last = m_container + m_containerSize; itr != last; ++itr) {
bounds_type bounds = (*itr)->preferred_size();
if ((*itr)->is_height_dynamic()) {
(*itr)->m_height = 0;
dynamicFrames[dynamicSize++] = std::make_pair(*itr, bounds);
@@ -367,11 +332,11 @@ Frame::balance_row(uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
for (dynamic_type *itr = dynamicFrames, *last = dynamicFrames + dynamicSize; itr != last; ++itr) {
uint32_t adjust = (std::max(remaining, 0) + std::distance(itr, last) - 1) / std::distance(itr, last);
adjust += itr->first->m_height;
adjust = std::max(adjust, itr->second.minHeight);
adjust = std::min(adjust, itr->second.maxHeight);
remaining -= adjust - itr->first->m_height;
retry = retry || itr->first->m_height != adjust;
@@ -410,10 +375,10 @@ Frame::balance_column(uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
dynamic_type dynamicFrames[max_size];
int remaining = width;
for (Frame **itr = m_container, **last = m_container + m_containerSize; itr != last; ++itr) {
bounds_type bounds = (*itr)->preferred_size();
if ((*itr)->is_width_dynamic()) {
(*itr)->m_width = 0;
dynamicFrames[dynamicSize++] = std::make_pair(*itr, bounds);
@@ -423,7 +388,7 @@ Frame::balance_column(uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
remaining -= bounds.minWidth;
}
}
// Sort the dynamic frames by the min size in the direction we are
// interested in. Then try to satisfy the largest first, and if we
// have any remaining space we can use that to extend it and any
@@ -442,11 +407,11 @@ Frame::balance_column(uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
for (dynamic_type *itr = dynamicFrames, *last = dynamicFrames + dynamicSize; itr != last; ++itr) {
uint32_t adjust = (std::max(remaining, 0) + std::distance(itr, last) - 1) / std::distance(itr, last);
adjust += itr->first->m_width;
adjust = std::max(adjust, itr->second.minWidth);
adjust = std::min(adjust, itr->second.maxWidth);
remaining -= adjust - itr->first->m_width;
retry = retry || itr->first->m_width != adjust;
+2 -35
View File
@@ -1,41 +1,8 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <sundell.software@gmail.com>
#ifndef RTORRENT_DISPLAY_FRAME_H
#define RTORRENT_DISPLAY_FRAME_H
#include <cinttypes>
#include <utility>
namespace display {
@@ -121,7 +88,7 @@ private:
union {
Window* m_window;
struct {
size_type m_containerSize;
Frame* m_container[max_size];
+1 -1
View File
@@ -3,7 +3,7 @@
#include <torrent/utils/scheduler.h>
#include "frame.h"
#include "display/frame.h"
namespace display {
-2
View File
@@ -31,8 +31,6 @@ Window::Window(Canvas* canvas, int flags, extent_type min_width, extent_type min
Window::~Window() {
if (is_active())
m_slot_unschedule(this);
delete m_canvas;
}
void
+1 -1
View File
@@ -89,7 +89,7 @@ protected:
static SlotWindow m_slot_unschedule;
static Slot m_slot_adjust;
Canvas* m_canvas;
std::unique_ptr<Canvas> m_canvas;
int m_flags;
-34
View File
@@ -1,37 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <sundell.software@gmail.com>
#include "config.h"
#include "canvas.h"
-34
View File
@@ -1,37 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <sundell.software@gmail.com>
#ifndef RTORRENT_DISPLAY_WINDOW_INPUT_H
#define RTORRENT_DISPLAY_WINDOW_INPUT_H
+2 -2
View File
@@ -7,13 +7,13 @@
namespace input {
void
InputEvent::insert(torrent::Poll* p) {
InputEvent::insert(torrent::net::Poll* p) {
p->open(this);
p->insert_read(this);
}
void
InputEvent::remove(torrent::Poll* p) {
InputEvent::remove(torrent::net::Poll* p) {
p->remove_read(this);
p->close(this);
}
+3 -3
View File
@@ -4,7 +4,7 @@
#include <functional>
#include <torrent/event.h>
#include <torrent/poll.h>
#include <torrent/net/poll.h>
namespace input {
@@ -14,8 +14,8 @@ public:
InputEvent(int fd) { m_fileDesc = fd; }
void insert(torrent::Poll* p);
void remove(torrent::Poll* p);
void insert(torrent::net::Poll* p);
void remove(torrent::net::Poll* p);
void event_read();
void event_write();
+69 -51
View File
@@ -10,6 +10,7 @@
#include <torrent/torrent.h>
#include <torrent/exceptions.h>
#include <torrent/data/chunk_utils.h>
#include <torrent/net/fd.h>
#include <torrent/utils/chrono.h>
#include <torrent/utils/log.h>
#include <rak/error_number.h>
@@ -214,6 +215,7 @@ main(int argc, char** argv) {
torrent::initialize();
torrent::set_main_thread_slots(std::bind(&client_perform));
// TODO: Move to controller.
worker_thread = new ThreadWorker();
worker_thread->init_thread();
@@ -350,74 +352,76 @@ main(int argc, char** argv) {
// Functions that might not get depracted as they are nice for
// configuration files, and thus might do with just some
// cleanup.
CMD2_REDIRECT("upload_rate", "throttle.global_up.max_rate.set_kb");
CMD2_REDIRECT("download_rate", "throttle.global_down.max_rate.set_kb");
CMD2_REDIRECT("upload_rate", "throttle.global_up.max_rate.set_kb");
CMD2_REDIRECT("download_rate", "throttle.global_down.max_rate.set_kb");
CMD2_REDIRECT("ratio.enable", "group.seeding.ratio.enable");
CMD2_REDIRECT("ratio.disable", "group.seeding.ratio.disable");
CMD2_REDIRECT("ratio.min", "group.seeding.ratio.min");
CMD2_REDIRECT("ratio.max", "group.seeding.ratio.max");
CMD2_REDIRECT("ratio.upload", "group.seeding.ratio.upload");
CMD2_REDIRECT("ratio.min.set", "group.seeding.ratio.min.set");
CMD2_REDIRECT("ratio.max.set", "group.seeding.ratio.max.set");
CMD2_REDIRECT("ratio.upload.set", "group.seeding.ratio.upload.set");
CMD2_REDIRECT("ratio.enable", "group.seeding.ratio.enable");
CMD2_REDIRECT("ratio.disable", "group.seeding.ratio.disable");
CMD2_REDIRECT("ratio.min", "group.seeding.ratio.min");
CMD2_REDIRECT("ratio.max", "group.seeding.ratio.max");
CMD2_REDIRECT("ratio.upload", "group.seeding.ratio.upload");
CMD2_REDIRECT("ratio.min.set", "group.seeding.ratio.min.set");
CMD2_REDIRECT("ratio.max.set", "group.seeding.ratio.max.set");
CMD2_REDIRECT("ratio.upload.set", "group.seeding.ratio.upload.set");
CMD2_REDIRECT("encryption", "protocol.encryption.set");
CMD2_REDIRECT("encoding_list", "encoding.add");
CMD2_REDIRECT("encryption", "protocol.encryption.set");
CMD2_REDIRECT("encoding_list", "encoding.add");
CMD2_REDIRECT("connection_leech", "protocol.connection.leech.set");
CMD2_REDIRECT("connection_seed", "protocol.connection.seed.set");
CMD2_REDIRECT("connection_leech", "protocol.connection.leech.set");
CMD2_REDIRECT("connection_seed", "protocol.connection.seed.set");
CMD2_REDIRECT("min_peers", "throttle.min_peers.normal.set");
CMD2_REDIRECT("max_peers", "throttle.max_peers.normal.set");
CMD2_REDIRECT("min_peers_seed", "throttle.min_peers.seed.set");
CMD2_REDIRECT("max_peers_seed", "throttle.max_peers.seed.set");
CMD2_REDIRECT("min_peers", "throttle.min_peers.normal.set");
CMD2_REDIRECT("max_peers", "throttle.max_peers.normal.set");
CMD2_REDIRECT("min_peers_seed", "throttle.min_peers.seed.set");
CMD2_REDIRECT("max_peers_seed", "throttle.max_peers.seed.set");
CMD2_REDIRECT("min_uploads", "throttle.min_uploads.set");
CMD2_REDIRECT("max_uploads", "throttle.max_uploads.set");
CMD2_REDIRECT("min_downloads", "throttle.min_downloads.set");
CMD2_REDIRECT("max_downloads", "throttle.max_downloads.set");
CMD2_REDIRECT("min_uploads", "throttle.min_uploads.set");
CMD2_REDIRECT("max_uploads", "throttle.max_uploads.set");
CMD2_REDIRECT("min_downloads", "throttle.min_downloads.set");
CMD2_REDIRECT("max_downloads", "throttle.max_downloads.set");
CMD2_REDIRECT("max_uploads_div", "throttle.max_uploads.div.set");
CMD2_REDIRECT("max_uploads_global", "throttle.max_uploads.global.set");
CMD2_REDIRECT("max_downloads_div", "throttle.max_downloads.div.set");
CMD2_REDIRECT("max_downloads_global", "throttle.max_downloads.global.set");
CMD2_REDIRECT("max_uploads_div", "throttle.max_uploads.div.set");
CMD2_REDIRECT("max_uploads_global", "throttle.max_uploads.global.set");
CMD2_REDIRECT("max_downloads_div", "throttle.max_downloads.div.set");
CMD2_REDIRECT("max_downloads_global", "throttle.max_downloads.global.set");
CMD2_REDIRECT("max_memory_usage", "pieces.memory.max.set");
CMD2_REDIRECT("max_memory_usage", "pieces.memory.max.set");
CMD2_REDIRECT("bind", "network.bind_address.set");
CMD2_REDIRECT("ip", "network.local_address.set");
CMD2_REDIRECT("port_range", "network.port_range.set");
CMD2_REDIRECT("bind", "network.bind_address.set");
CMD2_REDIRECT("ip", "network.local_address.set");
CMD2_REDIRECT("port_range", "network.port_range.set");
CMD2_REDIRECT("dht", "dht.mode.set");
CMD2_REDIRECT("dht", "dht.mode.set");
CMD2_REDIRECT("port_random", "network.port_random.set");
CMD2_REDIRECT("proxy_address", "network.proxy_address.set");
CMD2_REDIRECT("port_random", "network.port_random.set");
CMD2_REDIRECT("proxy_address", "network.proxy_address.set");
CMD2_REDIRECT("scgi_port", "network.scgi.open_port");
CMD2_REDIRECT("scgi_local", "network.scgi.open_local");
CMD2_REDIRECT("scgi_port", "network.scgi.open_port");
CMD2_REDIRECT("scgi_local", "network.scgi.open_local");
CMD2_REDIRECT("directory", "directory.default.set");
CMD2_REDIRECT("session", "session.path.set");
CMD2_REDIRECT("directory", "directory.default.set");
CMD2_REDIRECT("session", "session.path.set");
CMD2_REDIRECT("check_hash", "pieces.hash.on_completion.set");
CMD2_REDIRECT("check_hash", "pieces.hash.on_completion.set");
CMD2_REDIRECT("key_layout", "keys.layout.set");
CMD2_REDIRECT("key_layout", "keys.layout.set");
CMD2_REDIRECT("to_gm_time", "convert.gm_time");
CMD2_REDIRECT("to_gm_date", "convert.gm_date");
CMD2_REDIRECT("to_time", "convert.time");
CMD2_REDIRECT("to_date", "convert.date");
CMD2_REDIRECT("to_elapsed_time", "convert.elapsed_time");
CMD2_REDIRECT("to_kb", "convert.kb");
CMD2_REDIRECT("to_mb", "convert.mb");
CMD2_REDIRECT("to_xb", "convert.xb");
CMD2_REDIRECT("to_throttle", "convert.throttle");
CMD2_REDIRECT("to_gm_time", "convert.gm_time");
CMD2_REDIRECT("to_gm_date", "convert.gm_date");
CMD2_REDIRECT("to_time", "convert.time");
CMD2_REDIRECT("to_date", "convert.date");
CMD2_REDIRECT("to_elapsed_time", "convert.elapsed_time");
CMD2_REDIRECT("to_kb", "convert.kb");
CMD2_REDIRECT("to_mb", "convert.mb");
CMD2_REDIRECT("to_xb", "convert.xb");
CMD2_REDIRECT("to_throttle", "convert.throttle");
CMD2_REDIRECT("torrent_list_layout", "ui.torrent_list.layout.set");
CMD2_REDIRECT("torrent_list_layout", "ui.torrent_list.layout.set");
// Deprecate:
CMD2_VAR_STRING("dht.throttle.name", "deprecated");
CMD2_REDIRECT("network.http.max_open", "network.http.max_total_connections");
CMD2_REDIRECT("network.http.max_open.set", "network.http.max_total_connections.set");
@@ -443,6 +447,19 @@ main(int argc, char** argv) {
// if (rpc::call_command_value("method.use_deprecated") == 1) {
// }
{
auto fd = torrent::fd_open_family(torrent::fd_flag_stream, AF_INET6);
if (fd == -1) {
if (errno == EAFNOSUPPORT) {
lt_log_print(torrent::LOG_WARN, "disabling ipv6 support, not available on system");
rpc::call_command_set_value("network.block.ipv6.set", true);
}
} else {
torrent::fd_close(fd);
}
}
int firstArg = parse_options(argc, argv);
if (OptionParser::has_flag('n', argc, argv)) {
@@ -482,8 +499,6 @@ main(int argc, char** argv) {
control->display()->adjust_layout();
control->display()->receive_update();
worker_thread->start_thread();
rpc::commands.call_catch("event.system.startup_done", rpc::make_target(), "startup_done", "System startup_done event action failed: ");
torrent::utils::Thread::self()->event_loop();
@@ -518,7 +533,10 @@ main(int argc, char** argv) {
torrent::log_cleanup();
delete control;
control = nullptr;
delete worker_thread;
worker_thread = nullptr;
return 0;
}
+1 -1
View File
@@ -3,10 +3,10 @@
#include <cassert>
#include <sys/un.h>
#include <torrent/connection_manager.h>
#include <torrent/poll.h>
#include <torrent/torrent.h>
#include <torrent/exceptions.h>
#include <torrent/net/fd.h>
#include <torrent/net/poll.h>
#include <torrent/net/socket_address.h>
#include "control.h"
+1 -1
View File
@@ -8,8 +8,8 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <torrent/exceptions.h>
#include <torrent/poll.h>
#include <torrent/torrent.h>
#include <torrent/net/poll.h>
#include <torrent/utils/log.h>
#include <torrent/utils/thread.h>
+17
View File
@@ -4,10 +4,27 @@
#include "parse_commands.h"
#include <cstring>
#include <torrent/exceptions.h>
namespace rpc {
std::vector<std::unique_ptr<const char>> XmlRpc::m_command_names;
const char*
XmlRpc::store_command_name(const char* name) {
if (::strnlen(name, 8192) == 8192)
throw torrent::input_error("XMLRPC command name too long, limit is 8192 characters.");
for (const auto& itr : m_command_names) {
if (::strcmp(itr.get(), name) == 0)
return itr.get();
}
m_command_names.push_back(std::unique_ptr<const char>(::strdup(name)));
return m_command_names.back().get();
}
#ifndef HAVE_XMLRPC_C
#ifndef HAVE_XMLRPC_TINYXML2
+4 -1
View File
@@ -59,6 +59,10 @@ public:
void set_size_limit(uint64_t size);
private:
static const char* store_command_name(const char* name);
static std::vector<std::unique_ptr<const char>> m_command_names;
slot_download m_slotFindDownload;
slot_file m_slotFindFile;
slot_tracker m_slotFindTracker;
@@ -73,7 +77,6 @@ private:
// Only used by tinyxml2
bool m_isValid;
uint64_t m_sizeLimit{SCgiTask::max_content_size};
};
}
+42 -34
View File
@@ -8,9 +8,9 @@
#include <cctype>
#include <string>
#include <stdlib.h>
#include <rak/string_manip.h>
#include <torrent/object.h>
#include <torrent/exceptions.h>
#include <torrent/utils/string_manip.h>
#include <xmlrpc-c/server.h>
#include "rpc_manager.h"
@@ -282,24 +282,20 @@ object_to_xmlrpc(xmlrpc_env* env, const torrent::Object& object) {
// The versions that support I8 do implicit utf-8 validation.
xmlrpc_value* result = xmlrpc_string_new(env, object.as_string().c_str());
#else
xmlrpc_value* result{};
// In older versions, xmlrpc-c doesn't validate the utf-8 encoding itself.
xmlrpc_validate_utf8(env, object.as_string().c_str(), object.as_string().length());
xmlrpc_value* result = env->fault_occurred ? NULL : xmlrpc_string_new(env, object.as_string().c_str());
if (!env->fault_occurred)
result = xmlrpc_string_new(env, object.as_string().c_str());
#endif
if (env->fault_occurred) {
xmlrpc_env_clean(env);
xmlrpc_env_init(env);
const std::string& str = object.as_string();
char buffer[str.size() + 1];
char* dst = buffer;
for (char itr : str)
*dst++ = ((itr < 0x20 && itr != '\r' && itr != '\n' && itr != '\t') || (itr & 0x80)) ? '?' : itr;
*dst = 0;
result = xmlrpc_string_new(env, buffer);
return xmlrpc_string_new(env, torrent::utils::string_with_escape_codes(object.as_string()).c_str());
}
return result;
@@ -361,10 +357,12 @@ object_to_xmlrpc(xmlrpc_env* env, const torrent::Object& object) {
xmlrpc_value*
xmlrpc_call_command(xmlrpc_env* env, xmlrpc_value* args, void* voidServerInfo) {
CommandMap::iterator itr = commands.find((const char*)voidServerInfo);
auto server_info = static_cast<const char*>(voidServerInfo);
CommandMap::iterator itr = commands.find(server_info);
if (itr == commands.end()) {
xmlrpc_env_set_fault(env, XMLRPC_PARSE_ERROR, ("Command \"" + std::string((const char*)voidServerInfo) + "\" does not exist.").c_str());
xmlrpc_env_set_fault(env, XMLRPC_PARSE_ERROR, ("Command \"" + std::string(server_info) + "\" does not exist.").c_str());
return NULL;
}
@@ -397,6 +395,11 @@ xmlrpc_call_command(xmlrpc_env* env, xmlrpc_value* args, void* voidServerInfo) {
}
}
bool
XmlRpc::is_valid() const {
return m_env != NULL;
}
void
XmlRpc::initialize() {
#ifndef XMLRPC_HAVE_I8
@@ -421,34 +424,42 @@ XmlRpc::cleanup() {
bool
XmlRpc::process(const char* inBuffer, uint32_t length, slot_write slotWrite) {
xmlrpc_env localEnv;
xmlrpc_env_init(&localEnv);
xmlrpc_env local_env;
xmlrpc_env_init(&local_env);
xmlrpc_mem_block* memblock = xmlrpc_registry_process_call(&localEnv, (xmlrpc_registry*)m_registry, NULL, inBuffer, length);
xmlrpc_mem_block* memblock = xmlrpc_registry_process_call(&local_env, (xmlrpc_registry*)m_registry, NULL, inBuffer, length);
if (localEnv.fault_occurred && localEnv.fault_code == XMLRPC_INTERNAL_ERROR)
if (local_env.fault_occurred && local_env.fault_code == XMLRPC_INTERNAL_ERROR)
throw torrent::internal_error("Internal error in XMLRPC.");
bool result = slotWrite((const char*)xmlrpc_mem_block_contents(memblock),
xmlrpc_mem_block_size(memblock));
xmlrpc_mem_block_free(memblock);
xmlrpc_env_clean(&localEnv);
xmlrpc_env_clean(&local_env);
return result;
}
void
XmlRpc::insert_command(const char* name, const char* parm, const char* doc) {
xmlrpc_env localEnv;
xmlrpc_env_init(&localEnv);
xmlrpc_env local_env;
xmlrpc_env_init(&local_env);
xmlrpc_registry_add_method_w_doc(&localEnv, (xmlrpc_registry*)m_registry, NULL, name,
&xmlrpc_call_command, const_cast<char*>(name), parm, doc);
auto stored_name = store_command_name(name);
if (localEnv.fault_occurred)
xmlrpc_registry_add_method_w_doc(&local_env,
(xmlrpc_registry*)m_registry,
nullptr,
stored_name,
&xmlrpc_call_command,
(void*)stored_name,
parm,
doc);
if (local_env.fault_occurred)
throw torrent::internal_error("Fault occured while inserting xmlrpc call.");
xmlrpc_env_clean(&localEnv);
xmlrpc_env_clean(&local_env);
}
void
@@ -456,8 +467,8 @@ XmlRpc::set_dialect(int dialect) {
if (!is_valid())
throw torrent::input_error("Cannot select XMLRPC dialect before it is initialized.");
xmlrpc_env localEnv;
xmlrpc_env_init(&localEnv);
xmlrpc_env local_env;
xmlrpc_env_init(&local_env);
switch (dialect) {
case dialect_generic:
@@ -465,25 +476,25 @@ XmlRpc::set_dialect(int dialect) {
#ifdef XMLRPC_HAVE_I8
case dialect_i8:
xmlrpc_registry_set_dialect(&localEnv, (xmlrpc_registry*)m_registry, xmlrpc_dialect_i8);
xmlrpc_registry_set_dialect(&local_env, (xmlrpc_registry*)m_registry, xmlrpc_dialect_i8);
break;
case dialect_apache:
xmlrpc_registry_set_dialect(&localEnv, (xmlrpc_registry*)m_registry, xmlrpc_dialect_apache);
xmlrpc_registry_set_dialect(&local_env, (xmlrpc_registry*)m_registry, xmlrpc_dialect_apache);
break;
#endif
default:
xmlrpc_env_clean(&localEnv);
xmlrpc_env_clean(&local_env);
throw torrent::input_error("Unsupported XMLRPC dialect selected.");
}
if (localEnv.fault_occurred) {
xmlrpc_env_clean(&localEnv);
if (local_env.fault_occurred) {
xmlrpc_env_clean(&local_env);
throw torrent::input_error("Unsupported XMLRPC dialect selected.");
}
xmlrpc_env_clean(&localEnv);
xmlrpc_env_clean(&local_env);
m_dialect = dialect;
}
@@ -500,9 +511,6 @@ XmlRpc::set_size_limit(uint64_t size) {
xmlrpc_limit_set(XMLRPC_XML_SIZE_LIMIT_ID, size);
}
bool
XmlRpc::is_valid() const { return m_env != NULL; }
} // namespace rpc
#endif
+4 -4
View File
@@ -116,7 +116,7 @@ DownloadList::activate_display(Display displayType) {
m_uiArray[m_state] = NULL;
break;
case DISPLAY_DOWNLOAD_LIST:
m_uiArray[DISPLAY_DOWNLOAD_LIST]->disable();
@@ -130,7 +130,7 @@ DownloadList::activate_display(Display displayType) {
case DISPLAY_STRING_LIST:
m_uiArray[m_state]->disable();
break;
default:
break;
}
@@ -152,7 +152,7 @@ DownloadList::activate_display(Display displayType) {
download->activate(m_frame);
download->slot_exit(std::bind(&DownloadList::activate_display, this, DISPLAY_DOWNLOAD_LIST));
m_uiArray[DISPLAY_DOWNLOAD] = download;
break;
}
@@ -273,7 +273,7 @@ DownloadList::receive_exit_input(Input type) {
set_escdelay(1000);
input::TextInput* input = control->ui()->current_input();
// We should check that this object is the one holding the input.
if (input == NULL)
return;
-34
View File
@@ -1,37 +1,3 @@
// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <sundell.software@gmail.com>
#ifndef RTORRENT_UI_DOWNLOAD_LIST_H
#define RTORRENT_UI_DOWNLOAD_LIST_H
+15 -8
View File
@@ -83,13 +83,13 @@ Root::init(Control* c) {
m_downloadList = std::make_unique<DownloadList>();
display::Frame* rootFrame = m_control->display()->root_frame();
auto root_frame = m_control->display()->root_frame();
rootFrame->initialize_row(5);
rootFrame->frame(0)->initialize_window(m_windowTitle.get());
rootFrame->frame(2)->initialize_window(m_windowHttpQueue.get());
rootFrame->frame(3)->initialize_window(m_windowInput.get());
rootFrame->frame(4)->initialize_window(m_windowStatusbar.get());
root_frame->initialize_row(5);
root_frame->frame(0)->initialize_window(m_windowTitle.get());
root_frame->frame(2)->initialize_window(m_windowHttpQueue.get());
root_frame->frame(3)->initialize_window(m_windowInput.get());
root_frame->frame(4)->initialize_window(m_windowStatusbar.get());
m_windowTitle->set_active(true);
m_windowStatusbar->set_active(true);
@@ -97,7 +97,7 @@ Root::init(Control* c) {
setup_keys();
m_downloadList->activate(rootFrame->frame(1));
m_downloadList->activate(root_frame->frame(1));
}
void
@@ -111,7 +111,14 @@ Root::cleanup() {
m_control->display()->root_frame()->clear();
m_control->input()->erase(&m_bindings);
m_control = NULL;
// Destroy windows in reverse order of creation.
m_windowStatusbar = nullptr;
m_windowInput = nullptr;
m_windowHttpQueue = nullptr;
m_windowTitle = nullptr;
m_downloadList = nullptr;
m_control = nullptr;
}
const char*
+1 -1
View File
@@ -6,7 +6,7 @@
#include "test/helpers/mock_function.h"
#include "torrent/exceptions.h"
#include "torrent/poll.h"
#include "torrent/net/poll.h"
const int test_thread::test_flag_pre_stop;
const int test_thread::test_flag_long_timeout;