* Set SO_REUSEADDR for the listening socket.

* Moved several settings to use the new variables and made the parser
better.

* Use "-O2" rather than "-O3".


git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@623 e378c898-3ddf-0310-93e7-cc216c733640
This commit is contained in:
rakshasa
2006-01-17 17:23:32 +00:00
parent 4028ab2295
commit e8cd37ea3a
15 changed files with 207 additions and 129 deletions
+1 -1
View File
@@ -5,7 +5,7 @@ AC_DEFUN([TORRENT_CHECK_CXXFLAGS], [
if test -n "$CXXFLAGS"; then if test -n "$CXXFLAGS"; then
AC_MSG_RESULT([user-defined "$CXXFLAGS"]) AC_MSG_RESULT([user-defined "$CXXFLAGS"])
else else
CXXFLAGS="-O3 -Wall" CXXFLAGS="-O2 -Wall"
AC_MSG_RESULT([default "$CXXFLAGS"]) AC_MSG_RESULT([default "$CXXFLAGS"])
fi fi
]) ])
+2 -2
View File
@@ -38,10 +38,10 @@
#define RTORRENT_CONTROL_H #define RTORRENT_CONTROL_H
#include <inttypes.h> #include <inttypes.h>
#include <rak/timer.h>
#include <rak/priority_queue_default.h>
#include <torrent/torrent.h> #include <torrent/torrent.h>
#include "globals.h"
namespace ui { namespace ui {
class Root; class Root;
} }
+7 -5
View File
@@ -50,6 +50,9 @@
#include <torrent/bencode.h> #include <torrent/bencode.h>
#include <torrent/exceptions.h> #include <torrent/exceptions.h>
#include "utils/variable_map.h"
#include "globals.h"
#include "curl_get.h" #include "curl_get.h"
#include "download.h" #include "download.h"
#include "download_factory.h" #include "download_factory.h"
@@ -85,10 +88,8 @@ delete_tied(Download* d) {
Manager::Manager() : Manager::Manager() :
m_pollManager(NULL), m_pollManager(NULL),
m_portRandom(false),
m_portFirst(6890), m_portFirst(6890),
m_portLast(6999), m_portLast(6999) {
m_checkHash(true) {
} }
void void
@@ -245,7 +246,7 @@ Manager::check_hash(Download* d) {
void void
Manager::receive_download_done(Download* d) { Manager::receive_download_done(Download* d) {
if (m_checkHash) { if (control->variables()->get("check_hash").as_string() == "yes") {
// Start the hash checking, send completed to tracker after // Start the hash checking, send completed to tracker after
// finishing. // finishing.
prepare_hash_check(d); prepare_hash_check(d);
@@ -263,7 +264,7 @@ Manager::listen_open() {
if (m_portFirst > m_portLast) if (m_portFirst > m_portLast)
throw torrent::input_error("Invalid port range for listening"); throw torrent::input_error("Invalid port range for listening");
if (m_portRandom) { if (control->variables()->get("port_random").as_string() == "yes") {
int boundary = m_portFirst + random() % (m_portLast - m_portFirst + 1); int boundary = m_portFirst + random() % (m_portLast - m_portFirst + 1);
if (!torrent::listen_open(boundary, m_portLast) && if (!torrent::listen_open(boundary, m_portLast) &&
@@ -273,6 +274,7 @@ Manager::listen_open() {
} else { } else {
if (!torrent::listen_open(m_portFirst, m_portLast)) if (!torrent::listen_open(m_portFirst, m_portLast))
throw torrent::input_error("Could not open/bind a port for listening."); throw torrent::input_error("Could not open/bind a port for listening.");
} }
} }
-6
View File
@@ -69,11 +69,8 @@ public:
Log& get_log_important() { return m_logImportant; } Log& get_log_important() { return m_logImportant; }
Log& get_log_complete() { return m_logComplete; } Log& get_log_complete() { return m_logComplete; }
void set_port_random(bool v) { m_portRandom = v; }
void set_port_range(int a, int b) { m_portFirst = a; m_portLast = b; } void set_port_range(int a, int b) { m_portFirst = a; m_portLast = b; }
void set_check_hash(bool state) { m_checkHash = state; }
// Really should find a more descriptive name. // Really should find a more descriptive name.
void initialize_first(); void initialize_first();
void initialize_second(); void initialize_second();
@@ -121,11 +118,8 @@ private:
Log m_logImportant; Log m_logImportant;
Log m_logComplete; Log m_logComplete;
bool m_portRandom;
int m_portFirst; int m_portFirst;
int m_portLast; int m_portLast;
bool m_checkHash;
}; };
} }
+7 -6
View File
@@ -121,30 +121,31 @@ print_download_info(char* buf, unsigned int length, core::Download* d) {
(double)d->get_download().down_rate()->rate() / (1 << 10), (double)d->get_download().down_rate()->rate() / (1 << 10),
(double)d->get_download().up_rate()->total() / (1 << 20)), 0); (double)d->get_download().up_rate()->total() / (1 << 20)), 0);
//buf += std::max(0, snprintf(buf, length, " Left: ")); buf = print_download_time_left(buf, last - buf, d);
buf = print_download_time_left(buf, length, d);
return buf; return buf;
} }
char* char*
print_download_status(char* buf, unsigned int length, core::Download* d) { print_download_status(char* buf, unsigned int length, core::Download* d) {
char* last = buf + length;
if (!d->get_download().is_active()) if (!d->get_download().is_active())
buf += std::max(snprintf(buf, length, "Inactive: "), 0); buf += std::max(snprintf(buf, last - buf, "Inactive: "), 0);
if (d->get_download().is_hash_checking()) if (d->get_download().is_hash_checking())
buf += std::max(snprintf(buf, length, "Checking hash [%2i%%]", buf += std::max(snprintf(buf, last - buf, "Checking hash [%2i%%]",
(d->get_download().chunks_hashed() * 100) / d->get_download().chunks_total()), 0); (d->get_download().chunks_hashed() * 100) / d->get_download().chunks_total()), 0);
else if (d->get_download().is_tracker_busy() && else if (d->get_download().is_tracker_busy() &&
d->get_download().tracker_focus() < d->get_download().size_trackers()) d->get_download().tracker_focus() < d->get_download().size_trackers())
buf += std::max(snprintf(buf, length, "Tracker[%i:%i]: Connecting to %s", buf += std::max(snprintf(buf, last - buf, "Tracker[%i:%i]: Connecting to %s",
d->get_download().tracker(d->get_download().tracker_focus()).group(), d->get_download().tracker(d->get_download().tracker_focus()).group(),
d->get_download().tracker_focus(), d->get_download().tracker_focus(),
d->get_download().tracker(d->get_download().tracker_focus()).url().c_str()), 0); d->get_download().tracker(d->get_download().tracker_focus()).url().c_str()), 0);
else if (!d->get_message().empty()) else if (!d->get_message().empty())
buf += std::max(snprintf(buf, length, "%s", d->get_message().c_str()), 0); buf += std::max(snprintf(buf, last - buf, "%s", d->get_message().c_str()), 0);
else else
buf[0] = '\0'; buf[0] = '\0';
+1 -1
View File
@@ -120,7 +120,7 @@ WindowFileList::redraw() {
m_canvas->print(84, pos, "%i - %i", m_canvas->print(84, pos, "%i - %i",
e.chunk_begin(), e.chunk_begin(),
e.chunk_end()); e.chunk_begin() != e.chunk_end() ? (e.chunk_end() - 1) : e.chunk_end());
++range.first; ++range.first;
++pos; ++pos;
+2
View File
@@ -40,3 +40,5 @@
rak::priority_queue_default taskScheduler; rak::priority_queue_default taskScheduler;
rak::timer cachedTime; rak::timer cachedTime;
Control* control = NULL;
+4
View File
@@ -40,7 +40,11 @@
#include <rak/timer.h> #include <rak/timer.h>
#include <rak/priority_queue_default.h> #include <rak/priority_queue_default.h>
#include "control.h"
extern rak::priority_queue_default taskScheduler; extern rak::priority_queue_default taskScheduler;
extern rak::timer cachedTime; extern rak::timer cachedTime;
extern Control* control;
#endif #endif
+18 -14
View File
@@ -159,12 +159,12 @@ main(int argc, char** argv) {
cachedTime = rak::timer::current(); cachedTime = rak::timer::current();
Control control; control = new Control;
srandom(cachedTime.usec()); srandom(cachedTime.usec());
srand48(cachedTime.usec()); srand48(cachedTime.usec());
initialize_option_handler(&control); initialize_option_handler(control);
SignalHandler::set_ignore(SIGPIPE); SignalHandler::set_ignore(SIGPIPE);
SignalHandler::set_handler(SIGINT, sigc::mem_fun(control, &Control::receive_shutdown)); SignalHandler::set_handler(SIGINT, sigc::mem_fun(control, &Control::receive_shutdown));
@@ -172,17 +172,17 @@ main(int argc, char** argv) {
SignalHandler::set_handler(SIGBUS, sigc::bind(sigc::ptr_fun(&do_panic), SIGBUS)); SignalHandler::set_handler(SIGBUS, sigc::bind(sigc::ptr_fun(&do_panic), SIGBUS));
SignalHandler::set_handler(SIGFPE, sigc::bind(sigc::ptr_fun(&do_panic), SIGFPE)); SignalHandler::set_handler(SIGFPE, sigc::bind(sigc::ptr_fun(&do_panic), SIGFPE));
control.core()->initialize_first(); control->core()->initialize_first();
OptionFile optionFile; OptionFile optionFile;
optionFile.slot_option(sigc::mem_fun(control.variables(), &utils::VariableMap::set)); optionFile.slot_option(sigc::mem_fun(control->variables(), &utils::VariableMap::process_command));
if (getenv("HOME") && !optionFile.process_file(getenv("HOME") + std::string("/.rtorrent.rc"))) if (getenv("HOME") && !optionFile.process_file(getenv("HOME") + std::string("/.rtorrent.rc")))
control.core()->get_log_important().push_front("Could not load \"~/.rtorrent.rc\"."); control->core()->get_log_important().push_front("Could not load \"~/.rtorrent.rc\".");
int firstArg = parse_options(&control, control.variables(), argc, argv); int firstArg = parse_options(control, control->variables(), argc, argv);
control.initialize(); control->initialize();
// Just to make sure we did all the stuff on the queue before // Just to make sure we did all the stuff on the queue before
// loading any torrents. // loading any torrents.
@@ -192,38 +192,42 @@ main(int argc, char** argv) {
// Load session torrents and perform scheduled tasks to ensure // Load session torrents and perform scheduled tasks to ensure
// session torrents are loaded before arg torrents. // session torrents are loaded before arg torrents.
load_session_torrents(&control); load_session_torrents(control);
rak::priority_queue_perform(&taskScheduler, cachedTime); rak::priority_queue_perform(&taskScheduler, cachedTime);
load_arg_torrents(&control, argv + firstArg, argv + argc); load_arg_torrents(control, argv + firstArg, argv + argc);
control.display()->adjust_layout(); control->display()->adjust_layout();
while (!control.is_shutdown_completed()) { while (!control->is_shutdown_completed()) {
control.inc_tick(); control->inc_tick();
cachedTime = rak::timer::current(); cachedTime = rak::timer::current();
rak::priority_queue_perform(&taskScheduler, cachedTime); rak::priority_queue_perform(&taskScheduler, cachedTime);
// Do shutdown check before poll, not after. // Do shutdown check before poll, not after.
control.core()->get_poll_manager()->poll(client_next_timeout()); control->core()->get_poll_manager()->poll(client_next_timeout());
} }
control.cleanup(); control->cleanup();
} catch (torrent::base_error& e) { } catch (torrent::base_error& e) {
display::Canvas::cleanup(); display::Canvas::cleanup();
delete control;
std::cout << "Caught exception: " << e.what() << std::endl; std::cout << "Caught exception: " << e.what() << std::endl;
return -1; return -1;
} catch (std::exception& e) { } catch (std::exception& e) {
display::Canvas::cleanup(); display::Canvas::cleanup();
delete control;
std::cout << e.what() << std::endl; std::cout << e.what() << std::endl;
return -1; return -1;
} }
delete control;
return 0; return 0;
} }
+19 -19
View File
@@ -57,7 +57,7 @@ OptionFile::process_file(const std::string& filename) {
while (file.getline(buffer, max_size_line).good()) { while (file.getline(buffer, max_size_line).good()) {
lineNumber++; lineNumber++;
parse_line(buffer); m_slotOption(buffer);
} }
} catch (torrent::input_error& e) { } catch (torrent::input_error& e) {
@@ -69,28 +69,28 @@ OptionFile::process_file(const std::string& filename) {
return true; return true;
} }
void // void
OptionFile::parse_line(const char* line) { // OptionFile::parse_line(const char* line) {
//const char* last = std::find(line, line + max_size_line, '\0'); //const char* last = std::find(line, line + max_size_line, '\0');
if (line[0] == '#') // if (line[0] == '#')
return; // return;
int result; // int result;
char key[64]; // char key[64];
char opt[512]; // char opt[512];
opt[0] = '\0'; // opt[0] = '\0';
// Check for empty lines, and options within "abc". // // Check for empty lines, and options within "abc".
if ((result = std::sscanf(line, "%63s = \"%511[^\"]", key, opt)) != 2 && // if ((result = std::sscanf(line, "%63s = \"%511[^\"]", 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 torrent::input_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';
if (result >= 1) // if (result >= 1)
m_slotOption(key, opt); // m_slotOption(key, opt);
} // }
+1 -1
View File
@@ -46,7 +46,7 @@ public:
static const int max_size_opt = 1024; 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::slot1<void, const std::string&> SlotStringPair;
// Returns false when the file doesn't exist or cannot be opened. // Returns false when the file doesn't exist or cannot be opened.
bool process_file(const std::string& filename); bool process_file(const std::string& filename);
+36 -43
View File
@@ -55,6 +55,7 @@
#include "utils/variable_generic.h" #include "utils/variable_generic.h"
#include "utils/variable_map.h" #include "utils/variable_map.h"
#include "globals.h"
#include "control.h" #include "control.h"
#include "option_handler_rules.h" #include "option_handler_rules.h"
#include "command_scheduler.h" #include "command_scheduler.h"
@@ -178,11 +179,6 @@ apply_port_range(Control* m, const std::string& arg) {
m->core()->set_port_range(a, b); m->core()->set_port_range(a, b);
} }
void
apply_port_random(Control* m, const std::string& arg) {
m->core()->set_port_random(arg == "yes");
}
void void
apply_tracker_dump(Control* m, const std::string& arg) { apply_tracker_dump(Control* m, const std::string& arg) {
if (arg == "yes") if (arg == "yes")
@@ -199,14 +195,6 @@ apply_use_udp_trackers(Control* m, const std::string& arg) {
m->core()->get_download_list().slot_map_insert()["1_use_udp_trackers"] = sigc::bind(sigc::mem_fun(&core::Download::enable_udp_trackers), false); m->core()->get_download_list().slot_map_insert()["1_use_udp_trackers"] = sigc::bind(sigc::mem_fun(&core::Download::enable_udp_trackers), false);
} }
void
apply_check_hash(Control* m, const std::string& arg) {
if (arg == "yes")
m->core()->set_check_hash(true);
else
m->core()->set_check_hash(false);
}
void void
apply_http_proxy(Control* m, const std::string& arg) { apply_http_proxy(Control* m, const std::string& arg) {
m->core()->get_poll_manager()->get_http_stack()->set_http_proxy(arg); m->core()->get_poll_manager()->get_http_stack()->set_http_proxy(arg);
@@ -299,44 +287,49 @@ apply_schedule_remove(Control* m, const std::string& arg) {
void void
initialize_option_handler(Control* c) { initialize_option_handler(Control* c) {
c->variables()->insert("bind", new utils::VariableSlotString<>(NULL, rak::mem_fn(c->core(), &core::Manager::bind))); utils::VariableMap* variables = control->variables();
c->variables()->insert("ip", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_ip, c))); // Cleaned up.
c->variables()->insert("port_range", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_port_range, c))); variables->insert("check_hash", new utils::VariableValue("yes"));
c->variables()->insert("port_random", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_port_random, c))); variables->insert("port_random", new utils::VariableValue("yes"));
variables->insert("session", new utils::VariableSlotString<>(NULL, rak::mem_fn(&control->core()->get_download_store(), &core::DownloadStore::use)));
c->variables()->insert("check_hash", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_check_hash, c))); // Old.
c->variables()->insert("directory", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_download_directory, c))); variables->insert("bind", new utils::VariableSlotString<>(NULL, rak::mem_fn(control->core(), &core::Manager::bind)));
c->variables()->insert("max_peers", new utils::VariableSlotValue<int, int>(NULL, rak::bind_ptr_fn(&apply_download_max_peers, c), "%i")); variables->insert("ip", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_ip, c)));
c->variables()->insert("min_peers", new utils::VariableSlotValue<int, int>(NULL, rak::bind_ptr_fn(&apply_download_min_peers, c), "%i")); variables->insert("port_range", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_port_range, c)));
c->variables()->insert("max_uploads", new utils::VariableSlotValue<int, int>(NULL, rak::bind_ptr_fn(&apply_download_max_uploads, c), "%i"));
c->variables()->insert("download_rate", new utils::VariableSlotValue<int, int>(NULL, rak::bind_ptr_fn(&apply_global_download_rate, c), "%i")); variables->insert("directory", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_download_directory, c)));
c->variables()->insert("upload_rate", new utils::VariableSlotValue<int, int>(NULL, rak::bind_ptr_fn(&apply_global_upload_rate, c), "%i"));
c->variables()->insert("hash_read_ahead", new utils::VariableSlotValue<int, int>(NULL, rak::bind_ptr_fn(&apply_hash_read_ahead, c), "%i")); variables->insert("max_peers", new utils::VariableSlotValue<int, int>(NULL, rak::bind_ptr_fn(&apply_download_max_peers, c), "%i"));
c->variables()->insert("hash_interval", new utils::VariableSlotValue<int, int>(NULL, rak::bind_ptr_fn(&apply_hash_interval, c), "%i")); variables->insert("min_peers", new utils::VariableSlotValue<int, int>(NULL, rak::bind_ptr_fn(&apply_download_min_peers, c), "%i"));
c->variables()->insert("hash_max_tries", new utils::VariableSlotValue<int, int>(NULL, rak::bind_ptr_fn(&apply_hash_max_tries, c), "%i")); variables->insert("max_uploads", new utils::VariableSlotValue<int, int>(NULL, rak::bind_ptr_fn(&apply_download_max_uploads, c), "%i"));
c->variables()->insert("max_open_files", new utils::VariableSlotValue<int, int>(NULL, rak::bind_ptr_fn(&apply_max_open_files, c), "%i"));
c->variables()->insert("max_open_sockets", new utils::VariableSlotValue<int, int>(NULL, rak::bind_ptr_fn(&apply_max_open_sockets, c), "%i"));
c->variables()->insert("umask", new utils::VariableSlotValue<int, int>(NULL, rak::bind_ptr_fn(&apply_umask, c), "%o")); variables->insert("download_rate", new utils::VariableSlotValue<int, int>(NULL, rak::bind_ptr_fn(&apply_global_download_rate, c), "%i"));
variables->insert("upload_rate", new utils::VariableSlotValue<int, int>(NULL, rak::bind_ptr_fn(&apply_global_upload_rate, c), "%i"));
c->variables()->insert("connection_leech", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_connection_leech, c))); variables->insert("hash_read_ahead", new utils::VariableSlotValue<int, int>(NULL, rak::bind_ptr_fn(&apply_hash_read_ahead, c), "%i"));
c->variables()->insert("connection_seed", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_connection_seed, c))); variables->insert("hash_interval", new utils::VariableSlotValue<int, int>(NULL, rak::bind_ptr_fn(&apply_hash_interval, c), "%i"));
variables->insert("hash_max_tries", new utils::VariableSlotValue<int, int>(NULL, rak::bind_ptr_fn(&apply_hash_max_tries, c), "%i"));
variables->insert("max_open_files", new utils::VariableSlotValue<int, int>(NULL, rak::bind_ptr_fn(&apply_max_open_files, c), "%i"));
variables->insert("max_open_sockets", new utils::VariableSlotValue<int, int>(NULL, rak::bind_ptr_fn(&apply_max_open_sockets, c), "%i"));
c->variables()->insert("load", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_load, c))); variables->insert("umask", new utils::VariableSlotValue<int, int>(NULL, rak::bind_ptr_fn(&apply_umask, c), "%o"));
c->variables()->insert("load_start", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_load_start, c)));
c->variables()->insert("stop_untied", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_stop_untied, c)));
c->variables()->insert("remove_untied", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_remove_untied, c)));
c->variables()->insert("session", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_session_directory, c))); variables->insert("connection_leech", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_connection_leech, c)));
c->variables()->insert("encoding_list", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_encoding_list, c))); variables->insert("connection_seed", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_connection_seed, c)));
c->variables()->insert("tracker_dump", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_tracker_dump, c)));
c->variables()->insert("use_udp_trackers", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_use_udp_trackers, c)));
c->variables()->insert("http_proxy", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_http_proxy, c))); variables->insert("load", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_load, c)));
c->variables()->insert("schedule", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_schedule, c))); variables->insert("load_start", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_load_start, c)));
c->variables()->insert("schedule_remove", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_schedule_remove, c))); variables->insert("stop_untied", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_stop_untied, c)));
variables->insert("remove_untied", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_remove_untied, c)));
variables->insert("encoding_list", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_encoding_list, c)));
variables->insert("tracker_dump", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_tracker_dump, c)));
variables->insert("use_udp_trackers", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_use_udp_trackers, c)));
variables->insert("http_proxy", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_http_proxy, c)));
variables->insert("schedule", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_schedule, c)));
variables->insert("schedule_remove", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_schedule_remove, c)));
} }
+10 -10
View File
@@ -40,17 +40,17 @@
namespace utils { namespace utils {
// VariableString::~VariableString() { VariableValue::~VariableValue() {
// } }
// std::string const torrent::Bencode&
// VariableString::get() { VariableValue::get() {
// return m_variable; return m_variable;
// } }
// void void
// VariableString::set(const std::string& arg) { VariableValue::set(const torrent::Bencode& arg) {
// m_variable = arg; m_variable = arg;
// } }
} }
+25 -14
View File
@@ -39,6 +39,7 @@
#include <cstdio> #include <cstdio>
#include <string> #include <string>
#include <limits>
#include <inttypes.h> #include <inttypes.h>
#include <rak/functional_fun.h> #include <rak/functional_fun.h>
#include <torrent/bencode.h> #include <torrent/bencode.h>
@@ -48,19 +49,18 @@
namespace utils { namespace utils {
// class VariableS : public Variable { class VariableValue : public Variable {
// public: public:
// VariableString(const std::string& v = "") : m_variable(v) {} VariableValue(const torrent::Bencode& v = torrent::Bencode()) : m_variable(v) {}
// virtual ~VariableString(); virtual ~VariableValue();
// virtual const torrent::Bencode& get(); virtual const torrent::Bencode& get();
// virtual void set(const torrent::Bencode& arg); virtual void set(const torrent::Bencode& arg);
// private: private:
// std::string m_variable; torrent::Bencode m_variable;
// }; };
// VariableSlot?
template <typename Get = std::string, typename Set = const std::string&> template <typename Get = std::string, typename Set = const std::string&>
class VariableSlotString : public Variable { class VariableSlotString : public Variable {
public: public:
@@ -84,10 +84,16 @@ public:
} }
virtual void set(const torrent::Bencode& arg) { virtual void set(const torrent::Bencode& arg) {
if (!arg.is_string()) switch (arg.get_type()) {
throw torrent::internal_error("VariableSlotString::set(...) got wrong type."); case torrent::Bencode::TYPE_STRING:
m_slotSet(arg.as_string()); m_slotSet(arg.as_string());
break;
case torrent::Bencode::TYPE_NONE:
m_slotSet("");
break;
default:
throw torrent::internal_error("VariableSlotString::set(...) got wrong type.");
}
} }
private: private:
@@ -105,13 +111,17 @@ class VariableSlotValue : public Variable {
public: public:
typedef rak::function0<Get> SlotGet; typedef rak::function0<Get> SlotGet;
typedef rak::function1<void, Set> SlotSet; typedef rak::function1<void, Set> SlotSet;
typedef std::pair<int64_t, int64_t> Range;
VariableSlotValue(typename SlotGet::base_type* slotGet, VariableSlotValue(typename SlotGet::base_type* slotGet,
typename SlotSet::base_type* slotSet, typename SlotSet::base_type* slotSet,
const char* pattern) { const char* pattern,
Range range = Range(std::numeric_limits<int64_t>::min(),
std::numeric_limits<int64_t>::max())) {
m_slotGet.set(slotGet); m_slotGet.set(slotGet);
m_slotSet.set(slotSet); m_slotSet.set(slotSet);
m_pattern = pattern; m_pattern = pattern;
m_range = range;
} }
virtual ~VariableSlotValue() {} virtual ~VariableSlotValue() {}
@@ -148,6 +158,7 @@ private:
SlotSet m_slotSet; SlotSet m_slotSet;
const char* m_pattern; const char* m_pattern;
Range m_range;
// Store the cache here to avoid unnessesary copying and such. This // Store the cache here to avoid unnessesary copying and such. This
// should not result in any unresonable memory usage since few // should not result in any unresonable memory usage since few
+72 -5
View File
@@ -82,16 +82,83 @@ VariableMap::set(const std::string& key, const torrent::Bencode& arg) {
itr->second->set(arg); itr->second->set(arg);
} }
std::string::const_iterator
parse_name(std::string::const_iterator first, std::string::const_iterator last, std::string* dest) {
if (first == last || !std::isalpha(*first))
throw torrent::input_error("Invalid start of name.");
for ( ; first != last && (std::isalnum(*first) || *first == '_'); ++first)
dest->push_back(*first);
return first;
}
std::string::const_iterator
parse_unknown(std::string::const_iterator first, std::string::const_iterator last, torrent::Bencode* dest) {
if (*first == '"') {
std::string::const_iterator next = std::find_if(++first, last, std::bind2nd(std::equal_to<char>(), '"'));
if (first == last ||
first == next ||
next == last)
throw torrent::input_error("Could not find closing '\"'.");
*dest = std::string(first, next);
return ++next;
} else {
// Add rak::or and check for ','.
std::string::const_iterator next = std::find_if(first, last, std::ptr_fun(&std::isspace));
*dest = std::string(first, next);
return next;
}
}
std::string::const_iterator
parse_args(std::string::const_iterator first, std::string::const_iterator last, torrent::Bencode::List* dest) {
first = std::find_if(first, last, std::not1(std::ptr_fun(&std::isspace)));
while (first != last) {
dest->push_back(torrent::Bencode());
first = parse_unknown(first, last, &dest->back());
first = std::find_if(first, last, std::not1(std::ptr_fun(&std::isspace)));
if (first != last && *first != ',')
throw torrent::input_error("A string with blanks must be quoted.");
}
return first;
}
void void
VariableMap::process_command(const std::string& command) { VariableMap::process_command(const std::string& command) {
std::string::size_type pos = command.find('='); std::string::const_iterator pos = command.begin();
pos = std::find_if(pos, command.end(), std::not1(std::ptr_fun(&std::isspace)));
if (pos == std::string::npos) if (pos == command.end() || *pos == '#')
throw torrent::input_error("Option handler could not find '=' in command."); return;
// Do sscanf, check for integer. Later move and make it smarter. // Replace with parse_unknown?
std::string key;
pos = parse_name(pos, command.end(), &key);
pos = std::find_if(pos, command.end(), std::not1(std::ptr_fun(&std::isspace)));
set(command.substr(0, pos), torrent::Bencode(command.substr(pos + 1, std::string::npos))); if (pos == command.end() || *pos != '=')
throw torrent::input_error("Could not find '='.");
torrent::Bencode args(torrent::Bencode::TYPE_LIST);
parse_args(pos + 1, command.end(), &args.as_list());
if (args.as_list().empty())
set(key, torrent::Bencode());
else if (++args.as_list().begin() == args.as_list().end())
set(key, *args.as_list().begin());
else
set(key, args);
} }
} }