* Enforce an http transfer timeout when libcurl fails to honor

it. Also set a 5-minute timeout for (previously unlimited) torrent
transfers and fixes the argument type for curl_easy_setopt values.

* Allows bandwidth throttles to work without floating point support.

* Adds a d.add_peer=host[:port] command to manually add a peer (not
for torrents marked "private"), port is 6881 by default.

* Allows banning the selected peer with "B". No unbanning is possible
yet.

All the above patches were written by Josef Drexler.

* Differentiate between commands that have no target, and those that
take generic targets, when using XMLRPC.


git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@1073 e378c898-3ddf-0310-93e7-cc216c733640
This commit is contained in:
rakshasa
2008-10-22 13:23:48 +00:00
parent 85f5b7dc46
commit 29ba4ff4bc
14 changed files with 139 additions and 24 deletions
+18 -6
View File
@@ -41,6 +41,7 @@
#include <curl/easy.h>
#include <torrent/exceptions.h>
#include "globals.h"
#include "curl_get.h"
#include "curl_stack.h"
@@ -73,14 +74,20 @@ CurlGet::start() {
curl_easy_setopt(m_handle, CURLOPT_WRITEDATA, this);
if (m_timeout != 0) {
curl_easy_setopt(m_handle, CURLOPT_CONNECTTIMEOUT, 60);
curl_easy_setopt(m_handle, CURLOPT_TIMEOUT, m_timeout);
curl_easy_setopt(m_handle, CURLOPT_CONNECTTIMEOUT, (long)60);
curl_easy_setopt(m_handle, CURLOPT_TIMEOUT, (long)m_timeout);
// Normally libcurl should handle the timeout. But sometimes that doesn't
// work right so we do a fallback timeout that just aborts the transfer.
m_taskTimeout.set_slot(rak::mem_fn(this, &CurlGet::receive_timeout));
priority_queue_erase(&taskScheduler, &m_taskTimeout);
priority_queue_insert(&taskScheduler, &m_taskTimeout, cachedTime + rak::timer::from_seconds(m_timeout + 5));
}
curl_easy_setopt(m_handle, CURLOPT_FORBID_REUSE, 1);
curl_easy_setopt(m_handle, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt(m_handle, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(m_handle, CURLOPT_MAXREDIRS, 5);
curl_easy_setopt(m_handle, CURLOPT_FORBID_REUSE, (long)1);
curl_easy_setopt(m_handle, CURLOPT_NOSIGNAL, (long)1);
curl_easy_setopt(m_handle, CURLOPT_FOLLOWLOCATION, (long)1);
curl_easy_setopt(m_handle, CURLOPT_MAXREDIRS, (long)5);
curl_easy_setopt(m_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
curl_easy_setopt(m_handle, CURLOPT_ENCODING, "");
@@ -89,6 +96,7 @@ CurlGet::start() {
void
CurlGet::close() {
priority_queue_erase(&taskScheduler, &m_taskTimeout);
if (!is_busy())
return;
@@ -99,6 +107,10 @@ CurlGet::close() {
m_handle = NULL;
}
void
CurlGet::receive_timeout() {
return m_stack->transfer_done(m_handle, "Timed out");
}
double
CurlGet::size_done() {
+6
View File
@@ -43,6 +43,8 @@
#include <sigc++/signal.h>
#include <torrent/http.h>
#include "rak/priority_queue_default.h"
namespace core {
class CurlStack;
@@ -69,8 +71,12 @@ private:
CurlGet(const CurlGet&);
void operator = (const CurlGet&);
void receive_timeout();
bool m_active;
rak::priority_item m_taskTimeout;
CURL* m_handle;
CurlStack* m_stack;
};
+14 -9
View File
@@ -111,15 +111,7 @@ CurlStack::receive_action(CurlSocket* socket, int events) {
if (msg->msg != CURLMSG_DONE)
throw torrent::internal_error("CurlStack::receive_action() msg->msg != CURLMSG_DONE.");
iterator itr = std::find_if(begin(), end(), rak::equal(msg->easy_handle, std::mem_fun(&CurlGet::handle)));
if (itr == end())
throw torrent::internal_error("Could not find CurlGet with the right easy_handle.");
if (msg->data.result == CURLE_OK)
(*itr)->signal_done().emit();
else
(*itr)->signal_failed().emit(curl_easy_strerror(msg->data.result));
transfer_done(msg->easy_handle, msg->data.result == CURLE_OK ? NULL : curl_easy_strerror(msg->data.result));
}
if (empty())
@@ -129,6 +121,19 @@ CurlStack::receive_action(CurlSocket* socket, int events) {
} while (code == CURLM_CALL_MULTI_PERFORM);
}
void
CurlStack::transfer_done(void* handle, const char* msg) {
iterator itr = std::find_if(begin(), end(), rak::equal(handle, std::mem_fun(&CurlGet::handle)));
if (itr == end())
throw torrent::internal_error("Could not find CurlGet with the right easy_handle.");
if (msg == NULL)
(*itr)->signal_done().emit();
else
(*itr)->signal_failed().emit(msg);
}
void
CurlStack::receive_timeout() {
receive_action(NULL, 0);
+2
View File
@@ -111,6 +111,8 @@ class CurlStack : std::deque<CurlGet*> {
static int set_timeout(void* handle, long timeout_ms, void* userp);
void transfer_done(void* handle, const char* msg);
protected:
void add_get(CurlGet* get);
void remove_get(CurlGet* get);
+1
View File
@@ -54,6 +54,7 @@ HttpQueue::insert(const std::string& url, std::iostream* s) {
h->set_url(url);
h->set_stream(s);
h->set_timeout(5 * 60);
iterator itr = Base::insert(end(), h.get());