diff --git a/Makefile.am b/Makefile.am index 7364aa5e..240e0972 100644 --- a/Makefile.am +++ b/Makefile.am @@ -7,6 +7,7 @@ EXTRA_DIST= \ rak/algorithm.h \ rak/error_number.h \ rak/functional.h \ + rak/functional_fun.h \ rak/string_manip.h \ rak/timer.h \ rak/unordered_vector.h \ diff --git a/doc/rtorrent.1.xml b/doc/rtorrent.1.xml index 198652c5..9d134ed9 100644 --- a/doc/rtorrent.1.xml +++ b/doc/rtorrent.1.xml @@ -394,6 +394,15 @@ + + http_proxy = url + + + Use a http proxy. Use an empty string to disable. + + + + encoding_list = encoding @@ -464,22 +473,32 @@ - throttle_interval = ms + umask = 0644 - Interval between throttle ticks in milli-seconds, must be - between 1-5000 and defaults to - 1000. Shorter intervals will cause less - bandwidth usage spikes while requiring more CPU resources. + + Set the umask for this process, which is applied to all + files created by the program. + - - tracker_dump = yes | no - - Dump data received from trackers to the files - "./tracker_dump.*". - - + + + + + + + + + + + + + + + + + diff --git a/rak/functional_fun.h b/rak/functional_fun.h new file mode 100644 index 00000000..7d4dc850 --- /dev/null +++ b/rak/functional_fun.h @@ -0,0 +1,149 @@ +// rak - Rakshasa's toolbox +// Copyright (C) 2005, 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 +// +// Skomakerveien 33 +// 3185 Skoppum, NORWAY + +// This file contains functors that wrap function points and member +// function pointers. +// +// 'fn' functors are polymorphic and derives from 'rak::function' and +// thus is less strict about types, this adds the cost of calling a +// virtual function. +// +// 'fun' functors are non-polymorphic and thus cheaper, but requires +// the target object's type in the functor's template arguments. +// +// This should be replaced with TR1 stuff when it becomes widely +// available. At the moment it behaves like std::auto_ptr, so be +// careful when copying. + +#ifndef RAK_FUNCTIONAL_FUN_H +#define RAK_FUNCTIONAL_FUN_H + +namespace rak { + +template +class function_base { +public: + virtual ~function_base() {} + + virtual _Result operator () () = 0; +}; + +template +struct function_ref { + explicit function_ref(_Base* b) : m_base(b) {} + + _Base* m_base; +}; + +template +class function { +public: + typedef _Result result_type; + typedef function_base<_Result> _Base; + + function() : m_base(0) {} + function(function_ref<_Base> f) : m_base(f.m_base) {} + explicit function(function_base<_Result>* base) { m_base = base; } + + ~function() { delete m_base; } + + function& operator = (function& f) { m_base = f.release(); return *this; } + + function& operator = (function_ref<_Base> f) { + if (m_base != f.m_base) { + delete m_base; + m_base = f.m_base; + } + + return *this; + } + + template + operator function_ref<_T> () { return function_ref<_T>(this->release()); } + + _Result operator () () { return (*m_base)(); } + +private: + _Base* release() { _Base* tmp = m_base; m_base = 0; return tmp; } + + _Base* m_base; +}; + +template +class _mem_fn0 : public function_base<_Result> { +public: + typedef _Result (_Object::*_Func)(); + + _mem_fn0(_Object* object, _Func func) : m_object(object), m_func(func) {} + virtual ~_mem_fn0() {} + + virtual _Result operator () () { return (m_object->*m_func)(); } + +private: + _Object* m_object; + _Func m_func; +}; + +template +class _const_mem_fn0 : public function_base<_Result> { +public: + typedef _Result (_Object::*_Func)() const; + + _const_mem_fn0(const _Object* object, _Func func) : m_object(object), m_func(func) {} + virtual ~_const_mem_fn0() {} + + virtual _Result operator () () { return (m_object->*m_func)(); } + +private: + const _Object* m_object; + _Func m_func; +}; + +template +function<_Result> +mem_fn(_Object* object, _Result (_Object::*func)()) { + return function<_Result>(static_cast*>(new _mem_fn0<_Object, _Result>(object, func))); +} + +template +function<_Result> +mem_fn(const _Object* object, _Result (_Object::*func)() const) { + return function<_Result>(static_cast*>(new _const_mem_fn0<_Object, _Result>(object, func))); +} + +} + +#endif diff --git a/src/control.cc b/src/control.cc index b5a65b90..e1d28875 100644 --- a/src/control.cc +++ b/src/control.cc @@ -60,7 +60,7 @@ Control::Control() : m_inputStdin->slot_pressed(sigc::mem_fun(m_input, &input::Manager::pressed)); m_taskShutdown.set_iterator(taskScheduler.end()); - m_taskShutdown.set_slot(sigc::mem_fun(*this, &Control::receive_shutdown)); + m_taskShutdown.set_slot(rak::mem_fn(this, &Control::receive_shutdown)); } Control::~Control() { diff --git a/src/core/curl_get.cc b/src/core/curl_get.cc index 5f6750ea..5b52edab 100644 --- a/src/core/curl_get.cc +++ b/src/core/curl_get.cc @@ -132,6 +132,11 @@ CurlGet::set_user_agent(const char* s) { curl_easy_setopt(m_handle, CURLOPT_USERAGENT, s); } +void +CurlGet::set_http_proxy(const char* s) { + curl_easy_setopt(m_handle, CURLOPT_PROXY, s); +} + void CurlGet::perform(CURLMsg* msg) { if (msg->msg != CURLMSG_DONE) diff --git a/src/core/curl_get.h b/src/core/curl_get.h index fbd42893..17c43ea1 100644 --- a/src/core/curl_get.h +++ b/src/core/curl_get.h @@ -67,6 +67,7 @@ class CurlGet : public torrent::Http { double size_total(); void set_user_agent(const char* s); + void set_http_proxy(const char* s); protected: CURL* handle() { return m_handle; } diff --git a/src/core/curl_stack.cc b/src/core/curl_stack.cc index e52acb36..13a419d2 100644 --- a/src/core/curl_stack.cc +++ b/src/core/curl_stack.cc @@ -103,7 +103,11 @@ CurlStack::fdset(fd_set* readfds, fd_set* writefds, fd_set* exceptfds) { void CurlStack::add_get(CurlGet* get) { - get->set_user_agent(m_userAgent.c_str()); + if (!m_userAgent.empty()) + get->set_user_agent(m_userAgent.c_str()); + + if (!m_httpProxy.empty()) + get->set_http_proxy(m_httpProxy.c_str()); CURLMcode code; diff --git a/src/core/curl_stack.h b/src/core/curl_stack.h index 41be3639..ad5b36d3 100644 --- a/src/core/curl_stack.h +++ b/src/core/curl_stack.h @@ -68,6 +68,9 @@ class CurlStack { const std::string& user_agent() const { return m_userAgent; } void set_user_agent(const std::string& s) { m_userAgent = s; } + const std::string& http_proxy() const { return m_httpProxy; } + void set_http_proxy(const std::string& s) { m_httpProxy = s; } + static void global_init(); static void global_cleanup(); @@ -85,6 +88,7 @@ class CurlStack { CurlGetList m_getList; std::string m_userAgent; + std::string m_httpProxy; }; } diff --git a/src/core/download_factory.cc b/src/core/download_factory.cc index 14511bd8..359ece6b 100644 --- a/src/core/download_factory.cc +++ b/src/core/download_factory.cc @@ -61,10 +61,10 @@ DownloadFactory::DownloadFactory(const std::string& uri, Manager* m) : m_start(false) { m_taskLoad.set_iterator(taskScheduler.end()); - m_taskLoad.set_slot(sigc::mem_fun(*this, &DownloadFactory::receive_load)); + m_taskLoad.set_slot(rak::mem_fn(this, &DownloadFactory::receive_load)); m_taskCommit.set_iterator(taskScheduler.end()); - m_taskCommit.set_slot(sigc::mem_fun(*this, &DownloadFactory::receive_commit)); + m_taskCommit.set_slot(rak::mem_fn(this, &DownloadFactory::receive_commit)); } DownloadFactory::~DownloadFactory() { diff --git a/src/display/window.cc b/src/display/window.cc index d8fbd3a2..5107a620 100644 --- a/src/display/window.cc +++ b/src/display/window.cc @@ -51,7 +51,7 @@ Window::Window(Canvas* c, bool d, int h) : m_minHeight(h) { m_taskUpdate.set_iterator(displayScheduler.end()); - m_taskUpdate.set_slot(sigc::mem_fun(*this, &Window::redraw)); + m_taskUpdate.set_slot(rak::mem_fn(this, &Window::redraw)); } Window::~Window() { diff --git a/src/main.cc b/src/main.cc index 43672f09..a28fe416 100644 --- a/src/main.cc +++ b/src/main.cc @@ -136,6 +136,8 @@ initialize_option_handler(Control* c, OptionHandler* optionHandler) { optionHandler->insert("max_open_files", new OptionHandlerInt(c, &apply_max_open_files)); optionHandler->insert("max_open_sockets", new OptionHandlerInt(c, &apply_max_open_sockets)); + optionHandler->insert("umask", new OptionHandlerOctal(c, &apply_umask)); + optionHandler->insert("connection_leech", new OptionHandlerString(c, &apply_connection_leech)); optionHandler->insert("connection_seed", new OptionHandlerString(c, &apply_connection_seed)); @@ -143,6 +145,8 @@ initialize_option_handler(Control* c, OptionHandler* optionHandler) { optionHandler->insert("encoding_list", new OptionHandlerString(c, &apply_encoding_list)); optionHandler->insert("tracker_dump", new OptionHandlerString(c, &apply_tracker_dump)); optionHandler->insert("use_udp_trackers", new OptionHandlerString(c, &apply_use_udp_trackers)); + + optionHandler->insert("http_proxy", new OptionHandlerString(c, &apply_http_proxy)); } void diff --git a/src/option_handler_rules.cc b/src/option_handler_rules.cc index da533a93..e23abbcd 100644 --- a/src/option_handler_rules.cc +++ b/src/option_handler_rules.cc @@ -37,9 +37,11 @@ #include "config.h" #include +#include +#include +#include #include #include -#include #include "core/manager.h" #include "ui/root.h" @@ -55,7 +57,17 @@ OptionHandlerInt::process(const std::string& key, const std::string& arg) { int a; if (std::sscanf(arg.c_str(), "%i", &a) != 1) - throw torrent::input_error("Invalid argument for \"" + key + "\": \"" + arg + "\""); + throw torrent::input_error("Invalid argument for \"" + key + "\": \"" + arg + "\", must be an integer."); + + m_apply(m_control, a); +} + +void +OptionHandlerOctal::process(const std::string& key, const std::string& arg) { + int a; + + if (std::sscanf(arg.c_str(), "%o", &a) != 1) + throw torrent::input_error("Invalid argument for \"" + key + "\": \"" + arg + "\", must be an octal."); m_apply(m_control, a); } @@ -110,6 +122,11 @@ apply_global_upload_rate(Control* m, int arg) { m->ui()->set_up_throttle(arg); } +void +apply_umask(Control* m, int arg) { + umask(arg); +} + void apply_hash_read_ahead(Control* m, int arg) { torrent::set_hash_read_ahead(arg << 20); @@ -185,6 +202,11 @@ apply_check_hash(Control* m, const std::string& arg) { m->core()->set_check_hash(false); } +void +apply_http_proxy(Control* m, const std::string& arg) { + m->core()->get_poll_manager()->get_http_stack()->set_http_proxy(arg); +} + void apply_session_directory(Control* m, const std::string& arg) { m->core()->get_download_store().use(arg); diff --git a/src/option_handler_rules.h b/src/option_handler_rules.h index e8eb9c9f..82b09280 100644 --- a/src/option_handler_rules.h +++ b/src/option_handler_rules.h @@ -59,6 +59,8 @@ void apply_connection_seed(Control* m, const std::string& arg); void apply_global_download_rate(Control* m, int arg); void apply_global_upload_rate(Control* m, int arg); +void apply_umask(Control* m, int arg); + void apply_hash_read_ahead(Control* m, int arg); void apply_hash_interval(Control* m, int arg); void apply_hash_max_tries(Control* m, int arg); @@ -73,6 +75,8 @@ void apply_tracker_dump(Control* m, const std::string& arg); void apply_use_udp_trackers(Control* m, const std::string& arg); void apply_check_hash(Control* m, const std::string& arg); +void apply_http_proxy(Control* m, const std::string& arg); + void apply_session_directory(Control* m, const std::string& arg); void apply_encoding_list(Control* m, const std::string& arg); @@ -90,6 +94,20 @@ private: Apply m_apply; }; +class OptionHandlerOctal : public OptionHandlerBase { +public: + typedef void (*Apply)(Control*, int); + + OptionHandlerOctal(Control* c, Apply a) : + m_control(c), m_apply(a) {} + + virtual void process(const std::string& key, const std::string& arg); + +private: + Control* m_control; + Apply m_apply; +}; + class OptionHandlerString : public OptionHandlerBase { public: typedef void (*Apply)(Control*, const std::string&); diff --git a/src/ui/download_list.cc b/src/ui/download_list.cc index fde6ecce..4fcf5cf6 100644 --- a/src/ui/download_list.cc +++ b/src/ui/download_list.cc @@ -86,7 +86,7 @@ DownloadList::DownloadList(Control* c) : m_windowLog = new WLog(&m_control->core()->get_log_important()); m_taskUpdate.set_iterator(taskScheduler.end()); - m_taskUpdate.set_slot(sigc::mem_fun(*this, &DownloadList::task_update)), + m_taskUpdate.set_slot(rak::mem_fn(this, &DownloadList::task_update)), setup_keys(); setup_input(); diff --git a/src/utils/task_item.h b/src/utils/task_item.h index a32868a8..1ab69938 100644 --- a/src/utils/task_item.h +++ b/src/utils/task_item.h @@ -39,7 +39,7 @@ #include #include -#include +#include namespace utils { @@ -47,10 +47,10 @@ namespace utils { class TaskItem { public: - typedef sigc::slot Slot; + typedef rak::function Slot; typedef std::list >::iterator iterator; - TaskItem(Slot s = Slot()) : m_slot(s) {} + TaskItem() {} Slot& get_slot() { return m_slot; } void set_slot(Slot s) { m_slot = s; }