committed by
GitHub
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 167 additions and 911 deletions
-
9.github/workflows/static-analysis.yml
-
18.github/workflows/unit-tests.yml
-
7configure.ac
-
6src/Makefile.am
-
42src/command_network.cc
-
42src/control.cc
-
45src/control.h
-
122src/core/curl_get.cc
-
54src/core/curl_get.h
-
99src/core/curl_socket.cc
-
37src/core/curl_socket.h
-
243src/core/curl_stack.cc
-
120src/core/curl_stack.h
-
23src/core/download_factory.cc
-
37src/core/http_queue.cc
-
16src/core/http_queue.h
-
38src/core/manager.cc
-
5src/core/manager.h
-
20src/display/utils.cc
-
37src/display/utils.h
-
31src/display/window_http_queue.cc
-
18src/display/window_http_queue.h
-
9src/main.cc
@ -1,122 +0,0 @@ |
|||
#include "config.h"
|
|||
|
|||
#include "core/curl_get.h"
|
|||
|
|||
#include <iostream>
|
|||
#include <curl/curl.h>
|
|||
#include <curl/easy.h>
|
|||
#include <torrent/exceptions.h>
|
|||
|
|||
#include "globals.h"
|
|||
#include "core/curl_stack.h"
|
|||
|
|||
namespace core { |
|||
|
|||
size_t |
|||
curl_get_receive_write(void* data, size_t size, size_t nmemb, void* handle) { |
|||
if (!((CurlGet*)handle)->stream()->write((const char*)data, size * nmemb).fail()) |
|||
return size * nmemb; |
|||
else |
|||
return 0; |
|||
} |
|||
|
|||
CurlGet::CurlGet(CurlStack* s) : |
|||
m_stack(s) { |
|||
|
|||
m_task_timeout.slot() = [this]() { receive_timeout(); }; |
|||
} |
|||
|
|||
CurlGet::~CurlGet() { |
|||
close(); |
|||
} |
|||
|
|||
void |
|||
CurlGet::start() { |
|||
if (is_busy()) |
|||
throw torrent::internal_error("Tried to call CurlGet::start on a busy object."); |
|||
|
|||
if (m_stream == NULL) |
|||
throw torrent::internal_error("Tried to call CurlGet::start without a valid output stream."); |
|||
|
|||
if (!m_stack->is_running()) |
|||
return; |
|||
|
|||
m_handle = curl_easy_init(); |
|||
|
|||
if (m_handle == NULL) |
|||
throw torrent::internal_error("Call to curl_easy_init() failed."); |
|||
|
|||
curl_easy_setopt(m_handle, CURLOPT_URL, m_url.c_str()); |
|||
curl_easy_setopt(m_handle, CURLOPT_WRITEFUNCTION, &curl_get_receive_write); |
|||
curl_easy_setopt(m_handle, CURLOPT_WRITEDATA, this); |
|||
|
|||
if (m_timeout != 0) { |
|||
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.
|
|||
torrent::this_thread::scheduler()->update_wait_for_ceil_seconds(&m_task_timeout, 5s + 1s*m_timeout); |
|||
} |
|||
|
|||
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_WHATEVER); |
|||
|
|||
curl_easy_setopt(m_handle, CURLOPT_ENCODING, ""); |
|||
|
|||
m_ipv6 = false; |
|||
|
|||
m_stack->add_get(this); |
|||
} |
|||
|
|||
void |
|||
CurlGet::close() { |
|||
torrent::this_thread::scheduler()->erase(&m_task_timeout); |
|||
|
|||
if (!is_busy()) |
|||
return; |
|||
|
|||
m_stack->remove_get(this); |
|||
|
|||
curl_easy_cleanup(m_handle); |
|||
|
|||
m_handle = NULL; |
|||
} |
|||
|
|||
void |
|||
CurlGet::retry_ipv6() { |
|||
CURL* nhandle = curl_easy_duphandle(m_handle); |
|||
|
|||
curl_easy_setopt(nhandle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6); |
|||
curl_easy_cleanup(m_handle); |
|||
|
|||
m_handle = nhandle; |
|||
m_ipv6 = true; |
|||
} |
|||
|
|||
void |
|||
CurlGet::receive_timeout() { |
|||
return m_stack->transfer_done(m_handle, "Timed out"); |
|||
} |
|||
|
|||
curl_off_t |
|||
CurlGet::size_done() { |
|||
curl_off_t d = 0; |
|||
curl_easy_getinfo(m_handle, CURLINFO_SIZE_DOWNLOAD_T, &d); |
|||
|
|||
return d; |
|||
} |
|||
|
|||
curl_off_t |
|||
CurlGet::size_total() { |
|||
curl_off_t d = 0; |
|||
curl_easy_getinfo(m_handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &d); |
|||
|
|||
return d; |
|||
} |
|||
|
|||
} |
@ -1,54 +0,0 @@ |
|||
#ifndef RTORRENT_CORE_CURL_GET_H |
|||
#define RTORRENT_CORE_CURL_GET_H |
|||
|
|||
#include <iosfwd> |
|||
#include <string> |
|||
#include <curl/curl.h> |
|||
#include <torrent/http.h> |
|||
#include <torrent/utils/scheduler.h> |
|||
|
|||
namespace core { |
|||
|
|||
class CurlStack; |
|||
|
|||
class CurlGet : public torrent::Http { |
|||
public: |
|||
CurlGet(CurlStack* s); |
|||
virtual ~CurlGet(); |
|||
|
|||
void start(); |
|||
void close(); |
|||
|
|||
bool is_using_ipv6() { return m_ipv6; } |
|||
void retry_ipv6(); |
|||
|
|||
bool is_busy() const { return m_handle; } |
|||
bool is_active() const { return m_active; } |
|||
|
|||
void set_active(bool a) { m_active = a; } |
|||
|
|||
curl_off_t size_done(); |
|||
curl_off_t size_total(); |
|||
|
|||
CURL* handle() { return m_handle; } |
|||
|
|||
private: |
|||
friend class CurlStack; |
|||
|
|||
CurlGet(const CurlGet&) = delete; |
|||
void operator = (const CurlGet&) = delete; |
|||
|
|||
void receive_timeout(); |
|||
|
|||
bool m_active{}; |
|||
bool m_ipv6; |
|||
|
|||
torrent::utils::SchedulerEntry m_task_timeout; |
|||
|
|||
CURL* m_handle{}; |
|||
CurlStack* m_stack; |
|||
}; |
|||
|
|||
} |
|||
|
|||
#endif |
@ -1,99 +0,0 @@ |
|||
#include "config.h"
|
|||
|
|||
#include "curl_socket.h"
|
|||
|
|||
#include <cassert>
|
|||
#include <curl/multi.h>
|
|||
#include <torrent/poll.h>
|
|||
#include <torrent/exceptions.h>
|
|||
#include <torrent/utils/thread.h>
|
|||
|
|||
#include "control.h"
|
|||
#include "core/curl_stack.h"
|
|||
|
|||
namespace core { |
|||
|
|||
int |
|||
CurlSocket::receive_socket([[maybe_unused]] void* easy_handle, curl_socket_t fd, int what, void* userp, void* socketp) { |
|||
CurlStack* stack = (CurlStack*)userp; |
|||
CurlSocket* socket = (CurlSocket*)socketp; |
|||
|
|||
if (!stack->is_running()) |
|||
return 0; |
|||
|
|||
if (what == CURL_POLL_REMOVE) { |
|||
// We also probably need the special code here as we're not
|
|||
// guaranteed that the fd will be closed, afaik.
|
|||
if (socket != NULL) |
|||
socket->close(); |
|||
|
|||
// TODO: Consider the possibility that we'll need to set the
|
|||
// fd-associated pointer curl holds to NULL.
|
|||
|
|||
delete socket; |
|||
return 0; |
|||
} |
|||
|
|||
if (socket == NULL) { |
|||
socket = stack->new_socket(fd); |
|||
torrent::this_thread::poll()->open(socket); |
|||
|
|||
// No interface for libcurl to signal when it's interested in error events.
|
|||
// Assume that hence it must always be interested in them.
|
|||
torrent::this_thread::poll()->insert_error(socket); |
|||
} |
|||
|
|||
if (what == CURL_POLL_NONE || what == CURL_POLL_OUT) |
|||
torrent::this_thread::poll()->remove_read(socket); |
|||
else |
|||
torrent::this_thread::poll()->insert_read(socket); |
|||
|
|||
if (what == CURL_POLL_NONE || what == CURL_POLL_IN) |
|||
torrent::this_thread::poll()->remove_write(socket); |
|||
else |
|||
torrent::this_thread::poll()->insert_write(socket); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
CurlSocket::~CurlSocket() { |
|||
assert(m_fileDesc == -1 && "CurlSocket::~CurlSocket() m_fileDesc != -1."); |
|||
} |
|||
|
|||
void |
|||
CurlSocket::close() { |
|||
if (m_fileDesc == -1) |
|||
throw torrent::internal_error("CurlSocket::close() m_fileDesc == -1."); |
|||
|
|||
torrent::this_thread::poll()->closed(this); |
|||
m_fileDesc = -1; |
|||
} |
|||
|
|||
void |
|||
CurlSocket::event_read() { |
|||
#if (LIBCURL_VERSION_NUM >= 0x071003)
|
|||
return m_stack->receive_action(this, CURL_CSELECT_IN); |
|||
#else
|
|||
return m_stack->receive_action(this, 0); |
|||
#endif
|
|||
} |
|||
|
|||
void |
|||
CurlSocket::event_write() { |
|||
#if (LIBCURL_VERSION_NUM >= 0x071003)
|
|||
return m_stack->receive_action(this, CURL_CSELECT_OUT); |
|||
#else
|
|||
return m_stack->receive_action(this, 0); |
|||
#endif
|
|||
} |
|||
|
|||
void |
|||
CurlSocket::event_error() { |
|||
#if (LIBCURL_VERSION_NUM >= 0x071003)
|
|||
return m_stack->receive_action(this, CURL_CSELECT_ERR); |
|||
#else
|
|||
return m_stack->receive_action(this, 0); |
|||
#endif
|
|||
} |
|||
|
|||
} |
@ -1,37 +0,0 @@ |
|||
#ifndef RTORRENT_CORE_CURL_SOCKET_H |
|||
#define RTORRENT_CORE_CURL_SOCKET_H |
|||
|
|||
#include <curl/curl.h> |
|||
#include <torrent/event.h> |
|||
|
|||
#include "globals.h" |
|||
|
|||
namespace core { |
|||
|
|||
class CurlStack; |
|||
|
|||
class CurlSocket : public torrent::Event { |
|||
public: |
|||
CurlSocket(int fd, CurlStack* stack) : m_stack(stack) { m_fileDesc = fd; } |
|||
~CurlSocket(); |
|||
|
|||
const char* type_name() const { return "curl"; } |
|||
|
|||
void close(); |
|||
|
|||
static int receive_socket(void* easy_handle, curl_socket_t fd, int what, void* userp, void* socketp); |
|||
|
|||
private: |
|||
CurlSocket(const CurlSocket&); |
|||
void operator = (const CurlSocket&); |
|||
|
|||
virtual void event_read(); |
|||
virtual void event_write(); |
|||
virtual void event_error(); |
|||
|
|||
CurlStack* m_stack; |
|||
}; |
|||
|
|||
} |
|||
|
|||
#endif |
@ -1,243 +0,0 @@ |
|||
#include "config.h"
|
|||
|
|||
#include <algorithm>
|
|||
#include <curl/multi.h>
|
|||
#include <torrent/exceptions.h>
|
|||
|
|||
#include "curl_get.h"
|
|||
#include "curl_socket.h"
|
|||
#include "curl_stack.h"
|
|||
|
|||
namespace core { |
|||
|
|||
CurlStack::CurlStack() { |
|||
m_handle = (void*)curl_multi_init(); |
|||
m_task_timeout.slot() = std::bind(&CurlStack::receive_timeout, this); |
|||
|
|||
#if (LIBCURL_VERSION_NUM >= 0x071000)
|
|||
curl_multi_setopt((CURLM*)m_handle, CURLMOPT_TIMERDATA, this); |
|||
curl_multi_setopt((CURLM*)m_handle, CURLMOPT_TIMERFUNCTION, &CurlStack::set_timeout); |
|||
#endif
|
|||
curl_multi_setopt((CURLM*)m_handle, CURLMOPT_SOCKETDATA, this); |
|||
curl_multi_setopt((CURLM*)m_handle, CURLMOPT_SOCKETFUNCTION, &CurlSocket::receive_socket); |
|||
} |
|||
|
|||
CurlStack::~CurlStack() { |
|||
shutdown(); |
|||
} |
|||
|
|||
void |
|||
CurlStack::shutdown() { |
|||
if (!m_running) |
|||
return; |
|||
|
|||
m_running = false; |
|||
|
|||
while (!empty()) |
|||
front()->close(); |
|||
|
|||
curl_multi_cleanup((CURLM*)m_handle); |
|||
|
|||
torrent::this_thread::scheduler()->erase(&m_task_timeout); |
|||
} |
|||
|
|||
CurlGet* |
|||
CurlStack::new_object() { |
|||
return new CurlGet(this); |
|||
} |
|||
|
|||
CurlSocket* |
|||
CurlStack::new_socket(int fd) { |
|||
if (!m_running) |
|||
throw torrent::internal_error("CurlStack::new_socket() called when not running."); |
|||
|
|||
CurlSocket* socket = new CurlSocket(fd, this); |
|||
curl_multi_assign((CURLM*)m_handle, fd, socket); |
|||
return socket; |
|||
} |
|||
|
|||
void |
|||
CurlStack::receive_action(CurlSocket* socket, int events) { |
|||
CURLMcode code; |
|||
|
|||
do { |
|||
int count; |
|||
#if (LIBCURL_VERSION_NUM >= 0x071003)
|
|||
code = curl_multi_socket_action((CURLM*)m_handle, |
|||
socket != NULL ? socket->file_descriptor() : CURL_SOCKET_TIMEOUT, |
|||
events, |
|||
&count); |
|||
#else
|
|||
code = curl_multi_socket((CURLM*)m_handle, |
|||
socket != NULL ? socket->file_descriptor() : CURL_SOCKET_TIMEOUT, |
|||
&count); |
|||
#endif
|
|||
|
|||
if (code > 0) |
|||
throw torrent::internal_error("Error calling curl_multi_socket_action."); |
|||
|
|||
// Socket might be removed when cleaning handles below, future
|
|||
// calls should not use it.
|
|||
socket = NULL; |
|||
events = 0; |
|||
|
|||
if ((unsigned int)count != size()) { |
|||
while (process_done_handle()) |
|||
; // Do nothing.
|
|||
|
|||
if (empty()) |
|||
torrent::this_thread::scheduler()->erase(&m_task_timeout); |
|||
} |
|||
|
|||
} while (code == CURLM_CALL_MULTI_PERFORM); |
|||
} |
|||
|
|||
bool |
|||
CurlStack::process_done_handle() { |
|||
int remaining_msgs = 0; |
|||
CURLMsg* msg = curl_multi_info_read((CURLM*)m_handle, &remaining_msgs); |
|||
|
|||
if (msg == NULL) |
|||
return false; |
|||
|
|||
if (msg->msg != CURLMSG_DONE) |
|||
throw torrent::internal_error("CurlStack::receive_action() msg->msg != CURLMSG_DONE."); |
|||
|
|||
if (msg->data.result == CURLE_COULDNT_RESOLVE_HOST) { |
|||
iterator itr = std::find_if(begin(), end(), [&msg](CurlGet* get) { return get->handle() == msg->easy_handle; }); |
|||
|
|||
if (itr == end()) |
|||
throw torrent::internal_error("Could not find CurlGet when calling CurlStack::receive_action."); |
|||
|
|||
if (!(*itr)->is_using_ipv6()) { |
|||
(*itr)->retry_ipv6(); |
|||
|
|||
if (curl_multi_add_handle((CURLM*)m_handle, (*itr)->handle()) > 0) |
|||
throw torrent::internal_error("Error calling curl_multi_add_handle."); |
|||
} |
|||
|
|||
} else { |
|||
transfer_done(msg->easy_handle, |
|||
msg->data.result == CURLE_OK ? NULL : curl_easy_strerror(msg->data.result)); |
|||
} |
|||
|
|||
return remaining_msgs != 0; |
|||
} |
|||
|
|||
void |
|||
CurlStack::transfer_done(void* handle, const char* msg) { |
|||
iterator itr = std::find_if(begin(), end(), [&handle](CurlGet* get) { return get->handle() == handle; }); |
|||
|
|||
if (itr == end()) |
|||
throw torrent::internal_error("Could not find CurlGet with the right easy_handle."); |
|||
|
|||
if (msg == NULL) |
|||
(*itr)->trigger_done(); |
|||
else |
|||
(*itr)->trigger_failed(msg); |
|||
} |
|||
|
|||
void |
|||
CurlStack::receive_timeout() { |
|||
receive_action(NULL, 0); |
|||
|
|||
if (!empty() && !m_task_timeout.is_scheduled()) { |
|||
// Sometimes libcurl forgets to reset the timeout. Try to poll the value in that case, or use 10
|
|||
// seconds max.
|
|||
long timeout_ms; |
|||
curl_multi_timeout((CURLM*)m_handle, &timeout_ms); |
|||
|
|||
auto timeout = std::max<std::chrono::microseconds>(std::chrono::milliseconds(timeout_ms), 10s); |
|||
|
|||
torrent::this_thread::scheduler()->wait_for_ceil_seconds(&m_task_timeout, timeout); |
|||
} |
|||
} |
|||
|
|||
void |
|||
CurlStack::add_get(CurlGet* get) { |
|||
if (!m_user_agent.empty()) |
|||
curl_easy_setopt(get->handle(), CURLOPT_USERAGENT, m_user_agent.c_str()); |
|||
|
|||
if (!m_http_proxy.empty()) |
|||
curl_easy_setopt(get->handle(), CURLOPT_PROXY, m_http_proxy.c_str()); |
|||
|
|||
if (!m_bind_address.empty()) |
|||
curl_easy_setopt(get->handle(), CURLOPT_INTERFACE, m_bind_address.c_str()); |
|||
|
|||
if (!m_http_ca_path.empty()) |
|||
curl_easy_setopt(get->handle(), CURLOPT_CAPATH, m_http_ca_path.c_str()); |
|||
|
|||
if (!m_http_ca_cert.empty()) |
|||
curl_easy_setopt(get->handle(), CURLOPT_CAINFO, m_http_ca_cert.c_str()); |
|||
|
|||
curl_easy_setopt(get->handle(), CURLOPT_SSL_VERIFYHOST, (long)(m_ssl_verify_host ? 2 : 0)); |
|||
curl_easy_setopt(get->handle(), CURLOPT_SSL_VERIFYPEER, (long)(m_ssl_verify_peer ? 1 : 0)); |
|||
curl_easy_setopt(get->handle(), CURLOPT_DNS_CACHE_TIMEOUT, m_dns_timeout); |
|||
|
|||
base_type::push_back(get); |
|||
|
|||
if (m_active >= m_max_active) |
|||
return; |
|||
|
|||
m_active++; |
|||
get->set_active(true); |
|||
|
|||
if (curl_multi_add_handle((CURLM*)m_handle, get->handle()) > 0) |
|||
throw torrent::internal_error("Error calling curl_multi_add_handle."); |
|||
|
|||
#if (LIBCURL_VERSION_NUM < 0x071000)
|
|||
receive_timeout(); |
|||
#endif
|
|||
} |
|||
|
|||
void |
|||
CurlStack::remove_get(CurlGet* get) { |
|||
iterator itr = std::find(begin(), end(), get); |
|||
|
|||
if (itr == end()) |
|||
throw torrent::internal_error("Could not find CurlGet when calling CurlStack::remove."); |
|||
|
|||
base_type::erase(itr); |
|||
|
|||
// The CurlGet object was never activated, so we just skip this one.
|
|||
if (!get->is_active()) |
|||
return; |
|||
|
|||
get->set_active(false); |
|||
|
|||
if (curl_multi_remove_handle((CURLM*)m_handle, get->handle()) > 0) |
|||
throw torrent::internal_error("Error calling curl_multi_remove_handle."); |
|||
|
|||
if (m_active == m_max_active && |
|||
(itr = std::find_if(begin(), end(), [](CurlGet* get) { return !get->is_active(); })) != end()) { |
|||
(*itr)->set_active(true); |
|||
|
|||
if (curl_multi_add_handle((CURLM*)m_handle, (*itr)->handle()) > 0) |
|||
throw torrent::internal_error("Error calling curl_multi_add_handle."); |
|||
|
|||
} else { |
|||
m_active--; |
|||
} |
|||
} |
|||
|
|||
void |
|||
CurlStack::global_init() { |
|||
curl_global_init(CURL_GLOBAL_ALL); |
|||
} |
|||
|
|||
void |
|||
CurlStack::global_cleanup() { |
|||
curl_global_cleanup(); |
|||
} |
|||
|
|||
// TODO: Is this function supposed to set a per-handle timeout, or is
|
|||
// it the shortest timeout amongst all handles?
|
|||
int |
|||
CurlStack::set_timeout([[maybe_unused]] void* handle, std::chrono::microseconds timeout, void* userp) { |
|||
CurlStack* stack = (CurlStack*)userp; |
|||
|
|||
torrent::this_thread::scheduler()->update_wait_for_ceil_seconds(&stack->m_task_timeout, timeout); |
|||
return 0; |
|||
} |
|||
|
|||
} |
@ -1,120 +0,0 @@ |
|||
#ifndef RTORRENT_CORE_CURL_STACK_H |
|||
#define RTORRENT_CORE_CURL_STACK_H |
|||
|
|||
#include <deque> |
|||
#include <string> |
|||
#include <torrent/utils/scheduler.h> |
|||
|
|||
namespace core { |
|||
|
|||
class CurlGet; |
|||
class CurlSocket; |
|||
|
|||
// By using a deque instead of vector we allow for cheaper removal of |
|||
// the oldest elements, those that will be first in the in the |
|||
// deque. |
|||
// |
|||
// This should fit well with the use-case of a http stack, thus |
|||
// we get most of the cache locality benefits of a vector with fast |
|||
// removal of elements. |
|||
|
|||
class CurlStack : std::deque<CurlGet*> { |
|||
public: |
|||
friend class CurlGet; |
|||
|
|||
typedef std::deque<CurlGet*> base_type; |
|||
|
|||
using base_type::value_type; |
|||
using base_type::iterator; |
|||
using base_type::const_iterator; |
|||
using base_type::reverse_iterator; |
|||
using base_type::const_reverse_iterator; |
|||
|
|||
using base_type::begin; |
|||
using base_type::end; |
|||
using base_type::rbegin; |
|||
using base_type::rend; |
|||
|
|||
using base_type::back; |
|||
using base_type::front; |
|||
|
|||
using base_type::size; |
|||
using base_type::empty; |
|||
|
|||
CurlStack(); |
|||
~CurlStack(); |
|||
|
|||
void shutdown(); |
|||
bool is_running() const { return m_running; } |
|||
|
|||
CurlGet* new_object(); |
|||
CurlSocket* new_socket(int fd); |
|||
|
|||
unsigned int active() const { return m_active; } |
|||
unsigned int max_active() const { return m_max_active; } |
|||
void set_max_active(unsigned int a) { m_max_active = a; } |
|||
|
|||
const std::string& user_agent() const { return m_user_agent; } |
|||
const std::string& http_proxy() const { return m_http_proxy; } |
|||
const std::string& bind_address() const { return m_bind_address; } |
|||
const std::string& http_capath() const { return m_http_ca_path; } |
|||
const std::string& http_cacert() const { return m_http_ca_cert; } |
|||
|
|||
void set_user_agent(const std::string& s) { m_user_agent = s; } |
|||
void set_http_proxy(const std::string& s) { m_http_proxy = s; } |
|||
void set_bind_address(const std::string& s) { m_bind_address = s; } |
|||
void set_http_capath(const std::string& s) { m_http_ca_path = s; } |
|||
void set_http_cacert(const std::string& s) { m_http_ca_cert = s; } |
|||
|
|||
bool ssl_verify_host() const { return m_ssl_verify_host; } |
|||
bool ssl_verify_peer() const { return m_ssl_verify_peer; } |
|||
void set_ssl_verify_host(bool s) { m_ssl_verify_host = s; } |
|||
void set_ssl_verify_peer(bool s) { m_ssl_verify_peer = s; } |
|||
|
|||
long dns_timeout() const { return m_dns_timeout; } |
|||
void set_dns_timeout(long timeout) { m_dns_timeout = timeout; } |
|||
|
|||
static void global_init(); |
|||
static void global_cleanup(); |
|||
|
|||
void receive_action(CurlSocket* socket, int type); |
|||
|
|||
static int set_timeout(void* handle, std::chrono::microseconds timeout, void* userp); |
|||
|
|||
void transfer_done(void* handle, const char* msg); |
|||
|
|||
protected: |
|||
void add_get(CurlGet* get); |
|||
void remove_get(CurlGet* get); |
|||
|
|||
private: |
|||
CurlStack(const CurlStack&) = delete; |
|||
void operator = (const CurlStack&) = delete; |
|||
|
|||
void receive_timeout(); |
|||
|
|||
bool process_done_handle(); |
|||
|
|||
void* m_handle; |
|||
|
|||
bool m_running{true}; |
|||
|
|||
unsigned int m_active{0}; |
|||
unsigned int m_max_active{32}; |
|||
|
|||
torrent::utils::SchedulerEntry m_task_timeout; |
|||
|
|||
std::string m_user_agent; |
|||
std::string m_http_proxy; |
|||
std::string m_bind_address; |
|||
std::string m_http_ca_path; |
|||
std::string m_http_ca_cert; |
|||
|
|||
bool m_ssl_verify_host{true}; |
|||
bool m_ssl_verify_peer{true}; |
|||
long m_dns_timeout{60}; |
|||
}; |
|||
|
|||
} |
|||
|
|||
#endif |
Write
Preview
Loading…
Cancel
Save
Reference in new issue