mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-10-11 08:39:21 +00:00
* Improved error handling for settings. LibTorrent now consistently
throws torrent::input_error and rtorrent catches those and prints good
error messages.
* torrent::set_{bind,local}_address now accepts dns addresses.
* Fixed bug that caused multiple instances of the setting
up/download_rate to change the relative rate, rather than constant.
* Minor change to the way PCB decides to not request more pieces.
git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@601 e378c898-3ddf-0310-93e7-cc216c733640
This commit is contained in:
@@ -40,6 +40,7 @@
|
|||||||
#include <sigc++/bind.h>
|
#include <sigc++/bind.h>
|
||||||
#include <sigc++/hide.h>
|
#include <sigc++/hide.h>
|
||||||
#include <sigc++/signal.h>
|
#include <sigc++/signal.h>
|
||||||
|
#include <torrent/exceptions.h>
|
||||||
|
|
||||||
#include "download.h"
|
#include "download.h"
|
||||||
|
|
||||||
@@ -128,7 +129,7 @@ Download::string_to_connection_type(const std::string& name) {
|
|||||||
else if (name == "seed")
|
else if (name == "seed")
|
||||||
return torrent::Download::CONNECTION_SEED;
|
return torrent::Download::CONNECTION_SEED;
|
||||||
else
|
else
|
||||||
throw std::runtime_error("Invalid connection type selected: \"" + name + "\"");
|
throw torrent::input_error("Unknown peer connection type selected: \"" + name + "\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
|
|||||||
+3
-3
@@ -82,11 +82,11 @@ Manager::Manager() :
|
|||||||
void
|
void
|
||||||
Manager::initialize_first() {
|
Manager::initialize_first() {
|
||||||
if ((m_pollManager = PollManagerEPoll::create(sysconf(_SC_OPEN_MAX))) != NULL)
|
if ((m_pollManager = PollManagerEPoll::create(sysconf(_SC_OPEN_MAX))) != NULL)
|
||||||
m_logImportant.push_front("Using 'epoll' based polling");
|
m_logImportant.push_front("Using 'epoll' based polling.");
|
||||||
else if ((m_pollManager = PollManagerSelect::create(sysconf(_SC_OPEN_MAX))) != NULL)
|
else if ((m_pollManager = PollManagerSelect::create(sysconf(_SC_OPEN_MAX))) != NULL)
|
||||||
m_logImportant.push_front("Using 'select' based polling");
|
m_logImportant.push_front("Using 'select' based polling.");
|
||||||
else
|
else
|
||||||
throw std::runtime_error("Could not create any PollManager");
|
throw std::runtime_error("Could not create any PollManager.");
|
||||||
|
|
||||||
// Need to initialize this before parseing options.
|
// Need to initialize this before parseing options.
|
||||||
torrent::initialize(m_pollManager->get_torrent_poll());
|
torrent::initialize(m_pollManager->get_torrent_poll());
|
||||||
|
|||||||
+45
-54
@@ -100,67 +100,57 @@ is_resized() {
|
|||||||
|
|
||||||
int
|
int
|
||||||
parse_options(Control* c, OptionHandler* optionHandler, int argc, char** argv) {
|
parse_options(Control* c, OptionHandler* optionHandler, int argc, char** argv) {
|
||||||
OptionParser optionParser;
|
try {
|
||||||
|
OptionParser optionParser;
|
||||||
|
|
||||||
// Converted.
|
// Converted.
|
||||||
optionParser.insert_flag('h', sigc::ptr_fun(&print_help));
|
optionParser.insert_flag('h', sigc::ptr_fun(&print_help));
|
||||||
|
|
||||||
optionParser.insert_option('b', sigc::bind<0>(sigc::mem_fun(*optionHandler, &OptionHandler::process), "bind"));
|
optionParser.insert_option('b', sigc::bind<0>(sigc::mem_fun(*optionHandler, &OptionHandler::process), "bind"));
|
||||||
optionParser.insert_option('d', sigc::bind<0>(sigc::mem_fun(*optionHandler, &OptionHandler::process), "directory"));
|
optionParser.insert_option('d', sigc::bind<0>(sigc::mem_fun(*optionHandler, &OptionHandler::process), "directory"));
|
||||||
optionParser.insert_option('i', sigc::bind<0>(sigc::mem_fun(*optionHandler, &OptionHandler::process), "ip"));
|
optionParser.insert_option('i', sigc::bind<0>(sigc::mem_fun(*optionHandler, &OptionHandler::process), "ip"));
|
||||||
optionParser.insert_option('p', sigc::bind<0>(sigc::mem_fun(*optionHandler, &OptionHandler::process), "port_range"));
|
optionParser.insert_option('p', sigc::bind<0>(sigc::mem_fun(*optionHandler, &OptionHandler::process), "port_range"));
|
||||||
optionParser.insert_option('s', sigc::bind<0>(sigc::mem_fun(*optionHandler, &OptionHandler::process), "session"));
|
optionParser.insert_option('s', sigc::bind<0>(sigc::mem_fun(*optionHandler, &OptionHandler::process), "session"));
|
||||||
|
|
||||||
optionParser.insert_option_list('o', sigc::mem_fun(*optionHandler, &OptionHandler::process));
|
optionParser.insert_option_list('o', sigc::mem_fun(*optionHandler, &OptionHandler::process));
|
||||||
|
|
||||||
return optionParser.process(argc, argv);
|
return optionParser.process(argc, argv);
|
||||||
|
|
||||||
|
} catch (torrent::input_error& e) {
|
||||||
|
throw std::runtime_error("Failed to parse command line option: " + std::string(e.what()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
initialize_option_handler(Control* c, OptionHandler* optionHandler) {
|
initialize_option_handler(Control* c, OptionHandler* optionHandler) {
|
||||||
optionHandler->insert("max_peers", new OptionHandlerInt(c, &apply_download_max_peers, &validate_download_peers));
|
optionHandler->insert("max_peers", new OptionHandlerInt(c, &apply_download_max_peers));
|
||||||
optionHandler->insert("min_peers", new OptionHandlerInt(c, &apply_download_min_peers, &validate_download_peers));
|
optionHandler->insert("min_peers", new OptionHandlerInt(c, &apply_download_min_peers));
|
||||||
optionHandler->insert("max_uploads", new OptionHandlerInt(c, &apply_download_max_uploads, &validate_download_peers));
|
optionHandler->insert("max_uploads", new OptionHandlerInt(c, &apply_download_max_uploads));
|
||||||
|
|
||||||
optionHandler->insert("download_rate", new OptionHandlerInt(c, &apply_global_download_rate, &validate_rate));
|
optionHandler->insert("download_rate", new OptionHandlerInt(c, &apply_global_download_rate));
|
||||||
optionHandler->insert("upload_rate", new OptionHandlerInt(c, &apply_global_upload_rate, &validate_rate));
|
optionHandler->insert("upload_rate", new OptionHandlerInt(c, &apply_global_upload_rate));
|
||||||
|
|
||||||
optionHandler->insert("bind", new OptionHandlerString(c, &apply_bind, &validate_ip));
|
optionHandler->insert("bind", new OptionHandlerString(c, &apply_bind));
|
||||||
optionHandler->insert("ip", new OptionHandlerString(c, &apply_ip, &validate_ip));
|
optionHandler->insert("ip", new OptionHandlerString(c, &apply_ip));
|
||||||
optionHandler->insert("port_range", new OptionHandlerString(c, &apply_port_range, &validate_port_range));
|
optionHandler->insert("port_range", new OptionHandlerString(c, &apply_port_range));
|
||||||
optionHandler->insert("port_random", new OptionHandlerString(c, &apply_port_random, &validate_yes_no));
|
optionHandler->insert("port_random", new OptionHandlerString(c, &apply_port_random));
|
||||||
|
|
||||||
optionHandler->insert("check_hash", new OptionHandlerString(c, &apply_check_hash, &validate_yes_no));
|
optionHandler->insert("check_hash", new OptionHandlerString(c, &apply_check_hash));
|
||||||
optionHandler->insert("directory", new OptionHandlerString(c, &apply_download_directory, &validate_directory));
|
optionHandler->insert("directory", new OptionHandlerString(c, &apply_download_directory));
|
||||||
|
|
||||||
optionHandler->insert("hash_read_ahead", new OptionHandlerInt(c, &apply_hash_read_ahead, &validate_hash_read_ahead));
|
optionHandler->insert("hash_read_ahead", new OptionHandlerInt(c, &apply_hash_read_ahead));
|
||||||
optionHandler->insert("hash_interval", new OptionHandlerInt(c, &apply_hash_interval, &validate_hash_interval));
|
optionHandler->insert("hash_interval", new OptionHandlerInt(c, &apply_hash_interval));
|
||||||
optionHandler->insert("hash_max_tries", new OptionHandlerInt(c, &apply_hash_max_tries, &validate_hash_max_tries));
|
optionHandler->insert("hash_max_tries", new OptionHandlerInt(c, &apply_hash_max_tries));
|
||||||
optionHandler->insert("max_open_files", new OptionHandlerInt(c, &apply_max_open_files, &validate_fd));
|
optionHandler->insert("max_open_files", new OptionHandlerInt(c, &apply_max_open_files));
|
||||||
optionHandler->insert("max_open_sockets", new OptionHandlerInt(c, &apply_max_open_sockets, &validate_fd));
|
optionHandler->insert("max_open_sockets", new OptionHandlerInt(c, &apply_max_open_sockets));
|
||||||
|
|
||||||
optionHandler->insert("connection_leech", new OptionHandlerString(c, &apply_connection_leech, &validate_non_empty));
|
optionHandler->insert("connection_leech", new OptionHandlerString(c, &apply_connection_leech));
|
||||||
optionHandler->insert("connection_seed", new OptionHandlerString(c, &apply_connection_seed, &validate_non_empty));
|
optionHandler->insert("connection_seed", new OptionHandlerString(c, &apply_connection_seed));
|
||||||
|
|
||||||
optionHandler->insert("session", new OptionHandlerString(c, &apply_session_directory, &validate_directory));
|
optionHandler->insert("session", new OptionHandlerString(c, &apply_session_directory));
|
||||||
optionHandler->insert("encoding_list", new OptionHandlerString(c, &apply_encoding_list, &validate_non_empty));
|
optionHandler->insert("encoding_list", new OptionHandlerString(c, &apply_encoding_list));
|
||||||
optionHandler->insert("tracker_dump", new OptionHandlerString(c, &apply_tracker_dump, &validate_yes_no));
|
optionHandler->insert("tracker_dump", new OptionHandlerString(c, &apply_tracker_dump));
|
||||||
optionHandler->insert("use_udp_trackers", new OptionHandlerString(c, &apply_use_udp_trackers, &validate_yes_no));
|
optionHandler->insert("use_udp_trackers", new OptionHandlerString(c, &apply_use_udp_trackers));
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
load_option_file(const std::string& filename, OptionHandler* optionHandler, bool require = false) {
|
|
||||||
std::fstream f(filename.c_str(), std::ios::in);
|
|
||||||
|
|
||||||
if (!f.is_open()) {
|
|
||||||
std::cout << "Could not open option file \"" << filename << "\"" << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
OptionFile optionFile;
|
|
||||||
|
|
||||||
optionFile.slot_option(sigc::mem_fun(*optionHandler, &OptionHandler::process));
|
|
||||||
optionFile.process(&f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -198,13 +188,16 @@ main(int argc, char** argv) {
|
|||||||
utils::Timer::update();
|
utils::Timer::update();
|
||||||
|
|
||||||
OptionHandler optionHandler;
|
OptionHandler optionHandler;
|
||||||
Control uiControl;
|
Control uiControl;
|
||||||
|
|
||||||
srandom(utils::Timer::cache().usec());
|
srandom(utils::Timer::cache().usec());
|
||||||
srand48(utils::Timer::cache().usec());
|
srand48(utils::Timer::cache().usec());
|
||||||
|
|
||||||
initialize_option_handler(&uiControl, &optionHandler);
|
initialize_option_handler(&uiControl, &optionHandler);
|
||||||
|
|
||||||
|
OptionFile optionFile;
|
||||||
|
optionFile.slot_option(sigc::mem_fun(optionHandler, &OptionHandler::process));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
SignalHandler::set_ignore(SIGPIPE);
|
SignalHandler::set_ignore(SIGPIPE);
|
||||||
@@ -215,8 +208,8 @@ main(int argc, char** argv) {
|
|||||||
|
|
||||||
uiControl.core()->initialize_first();
|
uiControl.core()->initialize_first();
|
||||||
|
|
||||||
if (getenv("HOME"))
|
if (getenv("HOME") && !optionFile.process_file(getenv("HOME") + std::string("/.rtorrent.rc")))
|
||||||
load_option_file(getenv("HOME") + std::string("/.rtorrent.rc"), &optionHandler);
|
uiControl.core()->get_log_important().push_front("Could not load \"~/.rtorrent.rc\".");
|
||||||
|
|
||||||
int firstArg = parse_options(&uiControl, &optionHandler, argc, argv);
|
int firstArg = parse_options(&uiControl, &optionHandler, argc, argv);
|
||||||
|
|
||||||
@@ -250,13 +243,13 @@ main(int argc, char** argv) {
|
|||||||
} catch (torrent::base_error& e) {
|
} catch (torrent::base_error& e) {
|
||||||
display::Canvas::cleanup();
|
display::Canvas::cleanup();
|
||||||
|
|
||||||
std::cout << "Caught exception from libtorrent: \"" << e.what() << '"' << std::endl;
|
std::cout << "Caught exception from libtorrent: " << e.what() << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
} catch (std::exception& e) {
|
} catch (std::exception& e) {
|
||||||
display::Canvas::cleanup();
|
display::Canvas::cleanup();
|
||||||
|
|
||||||
std::cout << "Caught exception: \"" << e.what() << '"' << std::endl;
|
std::cout << e.what() << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,8 +281,6 @@ do_panic(int signum) {
|
|||||||
|
|
||||||
if (signum == SIGBUS)
|
if (signum == SIGBUS)
|
||||||
std::cout << "A bus error propably means you ran out of diskspace." << std::endl;
|
std::cout << "A bus error propably means you ran out of diskspace." << std::endl;
|
||||||
|
|
||||||
std::cout << "TO AVOID CORRUPT DOWNLOADS, RUN \"touch\" ON ALL DOWNLOADED FILES OR INITATE HASH RECHECK WITH ^R ON ALL TORRENTS." << std::endl;
|
|
||||||
|
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-7
@@ -38,18 +38,35 @@
|
|||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <torrent/exceptions.h>
|
||||||
|
|
||||||
#include "option_file.h"
|
#include "option_file.h"
|
||||||
|
|
||||||
void
|
bool
|
||||||
OptionFile::process(std::istream* stream) {
|
OptionFile::process_file(const std::string& filename) {
|
||||||
char buf[max_size_line];
|
std::fstream file(filename.c_str(), std::ios::in);
|
||||||
|
|
||||||
while (stream->good()) {
|
if (!file.good())
|
||||||
stream->getline(buf, max_size_line);
|
return false;
|
||||||
|
|
||||||
parse_line(buf);
|
int lineNumber = 0;
|
||||||
|
char buffer[max_size_line];
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
while (file.getline(buffer, max_size_line).good()) {
|
||||||
|
lineNumber++;
|
||||||
|
parse_line(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (torrent::input_error& e) {
|
||||||
|
snprintf(buffer, max_size_line, "Error in option file: %s:%i: %s", filename.c_str(), lineNumber, e.what());
|
||||||
|
|
||||||
|
throw std::runtime_error(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -69,7 +86,7 @@ OptionFile::parse_line(const char* line) {
|
|||||||
if ((result = std::sscanf(line, "%63s = \"%511[^\"]s", key, opt)) != 2 &&
|
if ((result = std::sscanf(line, "%63s = \"%511[^\"]s", key, opt)) != 2 &&
|
||||||
(result = std::sscanf(line, "%63s = %511s", key, opt)) != 2 &&
|
(result = std::sscanf(line, "%63s = %511s", key, opt)) != 2 &&
|
||||||
result == 1)
|
result == 1)
|
||||||
throw std::runtime_error("Error parseing option file.");
|
throw torrent::input_error("Error parseing option file.");
|
||||||
|
|
||||||
if (opt[0] == '"' && opt[1] == '"')
|
if (opt[0] == '"' && opt[1] == '"')
|
||||||
opt[0] = '\0';
|
opt[0] = '\0';
|
||||||
|
|||||||
+7
-5
@@ -37,25 +37,27 @@
|
|||||||
#ifndef RTORRENT_OPTION_FILE_H
|
#ifndef RTORRENT_OPTION_FILE_H
|
||||||
#define RTORRENT_OPTION_FILE_H
|
#define RTORRENT_OPTION_FILE_H
|
||||||
|
|
||||||
#include <iosfwd>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sigc++/slot.h>
|
#include <sigc++/slot.h>
|
||||||
|
|
||||||
class OptionFile {
|
class OptionFile {
|
||||||
public:
|
public:
|
||||||
static const int max_size_key = 64;
|
static const int max_size_key = 128;
|
||||||
static const int max_size_opt = 512;
|
static const int max_size_opt = 1024;
|
||||||
static const int max_size_line = max_size_key + max_size_opt + 64;
|
static const int max_size_line = max_size_key + max_size_opt + 64;
|
||||||
|
|
||||||
typedef sigc::slot2<void, const std::string&, const std::string&> SlotStringPair;
|
typedef sigc::slot2<void, const std::string&, const std::string&> SlotStringPair;
|
||||||
|
|
||||||
void slot_option(const SlotStringPair& s) { m_slotOption = s; }
|
// Returns false when the file doesn't exist or cannot be opened.
|
||||||
|
bool process_file(const std::string& filename);
|
||||||
|
|
||||||
void process(std::istream* stream);
|
void slot_option(const SlotStringPair& s) { m_slotOption = s; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void parse_line(const char* line);
|
void parse_line(const char* line);
|
||||||
|
|
||||||
|
static char* fill_buffer(int fd, char* buffer, char* first, char* last);
|
||||||
|
|
||||||
SlotStringPair m_slotOption;
|
SlotStringPair m_slotOption;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <sigc++/bind.h>
|
#include <sigc++/bind.h>
|
||||||
#include <sigc++/hide.h>
|
#include <sigc++/hide.h>
|
||||||
|
#include <torrent/exceptions.h>
|
||||||
|
|
||||||
#include "option_handler.h"
|
#include "option_handler.h"
|
||||||
|
|
||||||
@@ -78,7 +79,7 @@ OptionHandler::process(const std::string& key, const std::string& arg) const {
|
|||||||
const_iterator itr = find(key);
|
const_iterator itr = find(key);
|
||||||
|
|
||||||
if (itr == end())
|
if (itr == end())
|
||||||
throw std::runtime_error("Could not find option key matching \"" + key + "\"");
|
throw torrent::input_error("Could not find option key \"" + key + "\".");
|
||||||
|
|
||||||
itr->second->process(key, arg);
|
itr->second->process(key, arg);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ public:
|
|||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
|
// The caller must catch torrent::input_error in case of bad input.
|
||||||
void process(const std::string& key, const std::string& arg) const;
|
void process(const std::string& key, const std::string& arg) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+16
-61
@@ -37,6 +37,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <torrent/exceptions.h>
|
||||||
#include <torrent/torrent.h>
|
#include <torrent/torrent.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
|
||||||
@@ -49,67 +50,19 @@
|
|||||||
|
|
||||||
void receive_tracker_dump(std::istream* s);
|
void receive_tracker_dump(std::istream* s);
|
||||||
|
|
||||||
bool
|
void
|
||||||
validate_ip(const std::string& arg) {
|
OptionHandlerInt::process(const std::string& key, const std::string& arg) {
|
||||||
struct in_addr addr;
|
int a;
|
||||||
|
|
||||||
return inet_aton(arg.c_str(), &addr);
|
if (std::sscanf(arg.c_str(), "%i", &a) != 1)
|
||||||
|
throw torrent::input_error("Invalid argument for \"" + key + "\": \"" + arg + "\"");
|
||||||
|
|
||||||
|
m_apply(m_control, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We consider an empty string to be valid as this allows us to
|
void
|
||||||
// disable options.
|
OptionHandlerString::process(const std::string& key, const std::string& arg) {
|
||||||
bool
|
m_apply(m_control, arg);
|
||||||
validate_directory(const std::string& arg) {
|
|
||||||
//return arg.empty() || utils::Directory(arg).is_valid();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
validate_port_range(const std::string& arg) {
|
|
||||||
int a, b;
|
|
||||||
|
|
||||||
return std::sscanf(arg.c_str(), "%i-%i", &a, &b) == 2 &&
|
|
||||||
a <= b && a > 0 && b < (1 << 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
validate_yes_no(const std::string& arg) {
|
|
||||||
return arg == "yes" || arg == "no";
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
validate_non_empty(const std::string& arg) {
|
|
||||||
return !arg.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
validate_download_peers(int arg) {
|
|
||||||
return arg > 0 && arg < (1 << 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
validate_rate(int arg) {
|
|
||||||
return arg >= 0 && arg < (1 << 20);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
validate_hash_read_ahead(int arg) {
|
|
||||||
return arg >= 1 && arg < 64;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
validate_hash_interval(int arg) {
|
|
||||||
return arg >= 1 && arg < 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
validate_hash_max_tries(int arg) {
|
|
||||||
return arg >= 1 && arg < 20;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
validate_fd(int arg) {
|
|
||||||
return arg >= 1 && arg < (1 << 16);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -137,22 +90,24 @@ apply_download_directory(Control* m, const std::string& arg) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
apply_connection_leech(Control* m, const std::string& arg) {
|
apply_connection_leech(Control* m, const std::string& arg) {
|
||||||
|
core::Download::string_to_connection_type(arg);
|
||||||
m->core()->get_download_list().slot_map_insert()["1_connection_leech"] = sigc::bind(sigc::mem_fun(&core::Download::set_connection_leech), arg);
|
m->core()->get_download_list().slot_map_insert()["1_connection_leech"] = sigc::bind(sigc::mem_fun(&core::Download::set_connection_leech), arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
apply_connection_seed(Control* m, const std::string& arg) {
|
apply_connection_seed(Control* m, const std::string& arg) {
|
||||||
|
core::Download::string_to_connection_type(arg);
|
||||||
m->core()->get_download_list().slot_map_insert()["1_connection_seed"] = sigc::bind(sigc::mem_fun(&core::Download::set_connection_seed), arg);
|
m->core()->get_download_list().slot_map_insert()["1_connection_seed"] = sigc::bind(sigc::mem_fun(&core::Download::set_connection_seed), arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
apply_global_download_rate(Control* m, int arg) {
|
apply_global_download_rate(Control* m, int arg) {
|
||||||
m->ui()->receive_down_throttle(arg);
|
m->ui()->set_down_throttle(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
apply_global_upload_rate(Control* m, int arg) {
|
apply_global_upload_rate(Control* m, int arg) {
|
||||||
m->ui()->receive_up_throttle(arg);
|
m->ui()->set_up_throttle(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -48,19 +48,6 @@ class Control;
|
|||||||
|
|
||||||
// Not pretty, but it is simple and easy to modify.
|
// Not pretty, but it is simple and easy to modify.
|
||||||
|
|
||||||
bool validate_ip(const std::string& arg);
|
|
||||||
bool validate_directory(const std::string& arg);
|
|
||||||
bool validate_port_range(const std::string& arg);
|
|
||||||
bool validate_yes_no(const std::string& arg);
|
|
||||||
bool validate_non_empty(const std::string& arg);
|
|
||||||
|
|
||||||
bool validate_download_peers(int arg);
|
|
||||||
bool validate_rate(int arg);
|
|
||||||
bool validate_hash_read_ahead(int arg);
|
|
||||||
bool validate_hash_interval(int arg);
|
|
||||||
bool validate_hash_max_tries(int arg);
|
|
||||||
bool validate_fd(int arg);
|
|
||||||
|
|
||||||
void apply_download_min_peers(Control* m, int arg);
|
void apply_download_min_peers(Control* m, int arg);
|
||||||
void apply_download_max_peers(Control* m, int arg);
|
void apply_download_max_peers(Control* m, int arg);
|
||||||
void apply_download_max_uploads(Control* m, int arg);
|
void apply_download_max_uploads(Control* m, int arg);
|
||||||
@@ -91,47 +78,30 @@ void apply_encoding_list(Control* m, const std::string& arg);
|
|||||||
|
|
||||||
class OptionHandlerInt : public OptionHandlerBase {
|
class OptionHandlerInt : public OptionHandlerBase {
|
||||||
public:
|
public:
|
||||||
typedef bool (*Validate)(int);
|
|
||||||
typedef void (*Apply)(Control*, int);
|
typedef void (*Apply)(Control*, int);
|
||||||
|
|
||||||
OptionHandlerInt(Control* c, Apply a, Validate v) :
|
OptionHandlerInt(Control* c, Apply a) :
|
||||||
m_control(c), m_apply(a), m_validate(v) {}
|
m_control(c), m_apply(a) {}
|
||||||
|
|
||||||
virtual void process(const std::string& key, const std::string& arg) {
|
virtual void process(const std::string& key, const std::string& arg);
|
||||||
int a;
|
|
||||||
|
|
||||||
if (std::sscanf(arg.c_str(), "%i", &a) != 1 ||
|
|
||||||
!m_validate(a))
|
|
||||||
throw std::runtime_error("Invalid argument for \"" + key + "\": \"" + arg + "\"");
|
|
||||||
|
|
||||||
m_apply(m_control, a);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Control* m_control;
|
Control* m_control;
|
||||||
Apply m_apply;
|
Apply m_apply;
|
||||||
Validate m_validate;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class OptionHandlerString : public OptionHandlerBase {
|
class OptionHandlerString : public OptionHandlerBase {
|
||||||
public:
|
public:
|
||||||
typedef bool (*Validate)(const std::string&);
|
|
||||||
typedef void (*Apply)(Control*, const std::string&);
|
typedef void (*Apply)(Control*, const std::string&);
|
||||||
|
|
||||||
OptionHandlerString(Control* c, Apply a, Validate v) :
|
OptionHandlerString(Control* c, Apply a) :
|
||||||
m_control(c), m_apply(a), m_validate(v) {}
|
m_control(c), m_apply(a) {}
|
||||||
|
|
||||||
virtual void process(const std::string& key, const std::string& arg) {
|
virtual void process(const std::string& key, const std::string& arg);
|
||||||
if (!m_validate(arg))
|
|
||||||
throw std::runtime_error("Invalid argument for \"" + key + "\": \"" + arg + "\"");
|
|
||||||
|
|
||||||
m_apply(m_control, arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Control* m_control;
|
Control* m_control;
|
||||||
Apply m_apply;
|
Apply m_apply;
|
||||||
Validate m_validate;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+29
-21
@@ -94,49 +94,57 @@ void
|
|||||||
Root::setup_keys() {
|
Root::setup_keys() {
|
||||||
m_control->input()->push_back(&m_bindings);
|
m_control->input()->push_back(&m_bindings);
|
||||||
|
|
||||||
m_bindings['a'] = sigc::bind(sigc::mem_fun(*this, &Root::receive_up_throttle), 1);
|
m_bindings['a'] = sigc::bind(sigc::mem_fun(*this, &Root::adjust_up_throttle), 1);
|
||||||
m_bindings['z'] = sigc::bind(sigc::mem_fun(*this, &Root::receive_up_throttle), -1);
|
m_bindings['z'] = sigc::bind(sigc::mem_fun(*this, &Root::adjust_up_throttle), -1);
|
||||||
m_bindings['s'] = sigc::bind(sigc::mem_fun(*this, &Root::receive_up_throttle), 5);
|
m_bindings['s'] = sigc::bind(sigc::mem_fun(*this, &Root::adjust_up_throttle), 5);
|
||||||
m_bindings['x'] = sigc::bind(sigc::mem_fun(*this, &Root::receive_up_throttle), -5);
|
m_bindings['x'] = sigc::bind(sigc::mem_fun(*this, &Root::adjust_up_throttle), -5);
|
||||||
m_bindings['d'] = sigc::bind(sigc::mem_fun(*this, &Root::receive_up_throttle), 50);
|
m_bindings['d'] = sigc::bind(sigc::mem_fun(*this, &Root::adjust_up_throttle), 50);
|
||||||
m_bindings['c'] = sigc::bind(sigc::mem_fun(*this, &Root::receive_up_throttle), -50);
|
m_bindings['c'] = sigc::bind(sigc::mem_fun(*this, &Root::adjust_up_throttle), -50);
|
||||||
|
|
||||||
m_bindings['A'] = sigc::bind(sigc::mem_fun(*this, &Root::receive_down_throttle), 1);
|
m_bindings['A'] = sigc::bind(sigc::mem_fun(*this, &Root::adjust_down_throttle), 1);
|
||||||
m_bindings['Z'] = sigc::bind(sigc::mem_fun(*this, &Root::receive_down_throttle), -1);
|
m_bindings['Z'] = sigc::bind(sigc::mem_fun(*this, &Root::adjust_down_throttle), -1);
|
||||||
m_bindings['S'] = sigc::bind(sigc::mem_fun(*this, &Root::receive_down_throttle), 5);
|
m_bindings['S'] = sigc::bind(sigc::mem_fun(*this, &Root::adjust_down_throttle), 5);
|
||||||
m_bindings['X'] = sigc::bind(sigc::mem_fun(*this, &Root::receive_down_throttle), -5);
|
m_bindings['X'] = sigc::bind(sigc::mem_fun(*this, &Root::adjust_down_throttle), -5);
|
||||||
m_bindings['D'] = sigc::bind(sigc::mem_fun(*this, &Root::receive_down_throttle), 50);
|
m_bindings['D'] = sigc::bind(sigc::mem_fun(*this, &Root::adjust_down_throttle), 50);
|
||||||
m_bindings['C'] = sigc::bind(sigc::mem_fun(*this, &Root::receive_down_throttle), -50);
|
m_bindings['C'] = sigc::bind(sigc::mem_fun(*this, &Root::adjust_down_throttle), -50);
|
||||||
|
|
||||||
m_bindings[KEY_RESIZE] = sigc::mem_fun(*m_control->display(), &display::Manager::adjust_layout);
|
m_bindings[KEY_RESIZE] = sigc::mem_fun(*m_control->display(), &display::Manager::adjust_layout);
|
||||||
m_bindings['\x11'] = sigc::mem_fun(*m_control, &Control::receive_shutdown);
|
m_bindings['\x11'] = sigc::mem_fun(*m_control, &Control::receive_shutdown);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Root::receive_down_throttle(int t) {
|
Root::set_down_throttle(unsigned int throttle) {
|
||||||
if (m_windowStatusbar != NULL)
|
if (m_windowStatusbar != NULL)
|
||||||
m_windowStatusbar->mark_dirty();
|
m_windowStatusbar->mark_dirty();
|
||||||
|
|
||||||
torrent::set_down_throttle(std::max<int>(torrent::down_throttle() + t * 1024, 0));
|
torrent::set_down_throttle(throttle * 1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Root::receive_up_throttle(int t) {
|
Root::set_up_throttle(unsigned int throttle) {
|
||||||
if (m_windowStatusbar != NULL)
|
if (m_windowStatusbar != NULL)
|
||||||
m_windowStatusbar->mark_dirty();
|
m_windowStatusbar->mark_dirty();
|
||||||
|
|
||||||
uint32_t throttle = std::max<int>(torrent::up_throttle() + t * 1024, 0);
|
torrent::set_up_throttle(throttle * 1024);
|
||||||
|
|
||||||
torrent::set_up_throttle(throttle);
|
|
||||||
|
|
||||||
if (throttle == 0)
|
if (throttle == 0)
|
||||||
torrent::set_max_unchoked(0);
|
torrent::set_max_unchoked(0);
|
||||||
|
|
||||||
else if (throttle <= 10 << 10)
|
else if (throttle <= 10)
|
||||||
torrent::set_max_unchoked(1 + throttle / (1 << 10));
|
torrent::set_max_unchoked(1 + throttle / 1);
|
||||||
|
|
||||||
else
|
else
|
||||||
torrent::set_max_unchoked(10 + throttle / (5 << 10));
|
torrent::set_max_unchoked(10 + throttle / 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Root::adjust_down_throttle(int throttle) {
|
||||||
|
set_down_throttle(std::max<int>(torrent::down_throttle() / 1024 + throttle, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Root::adjust_up_throttle(int throttle) {
|
||||||
|
set_up_throttle(std::max<int>(torrent::up_throttle() / 1024 + throttle, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-2
@@ -60,8 +60,11 @@ public:
|
|||||||
|
|
||||||
WStatusbar* window_statusbar() { return m_windowStatusbar; }
|
WStatusbar* window_statusbar() { return m_windowStatusbar; }
|
||||||
|
|
||||||
void receive_down_throttle(int t);
|
void set_down_throttle(unsigned int throttle);
|
||||||
void receive_up_throttle(int t);
|
void set_up_throttle(unsigned int throttle);
|
||||||
|
|
||||||
|
void adjust_down_throttle(int throttle);
|
||||||
|
void adjust_up_throttle(int throttle);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setup_keys();
|
void setup_keys();
|
||||||
|
|||||||
Reference in New Issue
Block a user