X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fhttpfetch.cpp;h=1307bfec3af0072bfd94bddcb64a3a406fdfdef5;hb=5c89a0e12a1e679180b14bf92bdcdb1614e3982e;hp=3b3f5d33126d11a0da4b84132f14cfa1802c1fcd;hpb=f98bbe193e0093aca8d8957cec82fdbd28639915;p=dragonfireclient.git diff --git a/src/httpfetch.cpp b/src/httpfetch.cpp index 3b3f5d331..1307bfec3 100644 --- a/src/httpfetch.cpp +++ b/src/httpfetch.cpp @@ -17,14 +17,15 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "socket.h" // for select() -#include "porting.h" // for sleep_ms(), get_sysinfo(), secure_rand_fill_buf() #include "httpfetch.h" +#include "porting.h" // for sleep_ms(), get_sysinfo(), secure_rand_fill_buf() #include #include #include -#include -#include +#include +#include +#include +#include "network/socket.h" // for select() #include "threading/event.h" #include "config.h" #include "exceptions.h" @@ -36,17 +37,14 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "settings.h" #include "noise.h" -Mutex g_httpfetch_mutex; -std::map > g_httpfetch_results; -PcgRandom g_callerid_randomness; +static std::mutex g_httpfetch_mutex; +static std::unordered_map> + g_httpfetch_results; +static PcgRandom g_callerid_randomness; HTTPFetchRequest::HTTPFetchRequest() : - url(""), - caller(HTTPFETCH_DISCARD), - request_id(0), timeout(g_settings->getS32("curl_timeout")), - connect_timeout(timeout), - multipart(false), + connect_timeout(10 * 1000), useragent(std::string(PROJECT_NAME_C "/") + g_version_hash + " (" + porting::get_sysinfo() + ")") { } @@ -57,7 +55,7 @@ static void httpfetch_deliver_result(const HTTPFetchResult &fetch_result) unsigned long caller = fetch_result.caller; if (caller != HTTPFETCH_DISCARD) { MutexAutoLock lock(g_httpfetch_mutex); - g_httpfetch_results[caller].push(fetch_result); + g_httpfetch_results[caller].emplace(fetch_result); } } @@ -70,8 +68,7 @@ unsigned long httpfetch_caller_alloc() // Check each caller ID except HTTPFETCH_DISCARD const unsigned long discard = HTTPFETCH_DISCARD; for (unsigned long caller = discard + 1; caller != discard; ++caller) { - std::map >::iterator - it = g_httpfetch_results.find(caller); + auto it = g_httpfetch_results.find(caller); if (it == g_httpfetch_results.end()) { verbosestream << "httpfetch_caller_alloc: allocating " << caller << std::endl; @@ -130,8 +127,7 @@ bool httpfetch_async_get(unsigned long caller, HTTPFetchResult &fetch_result) MutexAutoLock lock(g_httpfetch_mutex); // Check that caller exists - std::map >::iterator - it = g_httpfetch_results.find(caller); + auto it = g_httpfetch_results.find(caller); if (it == g_httpfetch_results.end()) return false; @@ -141,7 +137,7 @@ bool httpfetch_async_get(unsigned long caller, HTTPFetchResult &fetch_result) return false; // Pop first result - fetch_result = caller_results.front(); + fetch_result = std::move(caller_results.front()); caller_results.pop(); return true; } @@ -173,7 +169,8 @@ class CurlHandlePool std::list handles; public: - CurlHandlePool() {} + CurlHandlePool() = default; + ~CurlHandlePool() { for (std::list::iterator it = handles.begin(); @@ -247,13 +244,18 @@ HTTPFetchOngoing::HTTPFetchOngoing(const HTTPFetchRequest &request_, curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); - curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 1); + curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 3); + curl_easy_setopt(curl, CURLOPT_ENCODING, "gzip"); std::string bind_address = g_settings->get("bind_address"); if (!bind_address.empty()) { curl_easy_setopt(curl, CURLOPT_INTERFACE, bind_address.c_str()); } + if (!g_settings->getBool("enable_ipv6")) { + curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); + } + #if LIBCURL_VERSION_NUM >= 0x071304 // Restrict protocols so that curl vulnerabilities in // other protocols don't affect us. @@ -275,7 +277,7 @@ HTTPFetchOngoing::HTTPFetchOngoing(const HTTPFetchRequest &request_, curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS, request.connect_timeout); - if (request.useragent != "") + if (!request.useragent.empty()) curl_easy_setopt(curl, CURLOPT_USERAGENT, request.useragent.c_str()); // Set up a write callback that writes to the @@ -291,13 +293,11 @@ HTTPFetchOngoing::HTTPFetchOngoing(const HTTPFetchRequest &request_, curl_easy_setopt(curl, CURLOPT_WRITEDATA, &oss); } - // Set POST (or GET) data - if (request.post_fields.empty() && request.post_data.empty()) { - curl_easy_setopt(curl, CURLOPT_HTTPGET, 1); - } else if (request.multipart) { + // Set data from fields or raw_data + if (request.multipart) { curl_httppost *last = NULL; - for (StringMap::iterator it = request.post_fields.begin(); - it != request.post_fields.end(); ++it) { + for (StringMap::iterator it = request.fields.begin(); + it != request.fields.end(); ++it) { curl_formadd(&post, &last, CURLFORM_NAMELENGTH, it->first.size(), CURLFORM_PTRNAME, it->first.c_str(), @@ -308,34 +308,46 @@ HTTPFetchOngoing::HTTPFetchOngoing(const HTTPFetchRequest &request_, curl_easy_setopt(curl, CURLOPT_HTTPPOST, post); // request.post_fields must now *never* be // modified until CURLOPT_HTTPPOST is cleared - } else if (request.post_data.empty()) { - curl_easy_setopt(curl, CURLOPT_POST, 1); - std::string str; - for (StringMap::iterator it = request.post_fields.begin(); - it != request.post_fields.end(); ++it) { - if (str != "") - str += "&"; - str += urlencode(it->first); - str += "="; - str += urlencode(it->second); - } - curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, - str.size()); - curl_easy_setopt(curl, CURLOPT_COPYPOSTFIELDS, - str.c_str()); } else { - curl_easy_setopt(curl, CURLOPT_POST, 1); - curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, - request.post_data.size()); - curl_easy_setopt(curl, CURLOPT_POSTFIELDS, - request.post_data.c_str()); - // request.post_data must now *never* be - // modified until CURLOPT_POSTFIELDS is cleared + switch (request.method) { + case HTTP_GET: + curl_easy_setopt(curl, CURLOPT_HTTPGET, 1); + break; + case HTTP_POST: + curl_easy_setopt(curl, CURLOPT_POST, 1); + break; + case HTTP_PUT: + curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT"); + break; + case HTTP_DELETE: + curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE"); + break; + } + if (request.method != HTTP_GET) { + if (!request.raw_data.empty()) { + curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, + request.raw_data.size()); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, + request.raw_data.c_str()); + } else if (!request.fields.empty()) { + std::string str; + for (auto &field : request.fields) { + if (!str.empty()) + str += "&"; + str += urlencode(field.first); + str += "="; + str += urlencode(field.second); + } + curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, + str.size()); + curl_easy_setopt(curl, CURLOPT_COPYPOSTFIELDS, + str.c_str()); + } + } } // Set additional HTTP headers - for (std::vector::iterator it = request.extra_headers.begin(); - it != request.extra_headers.end(); ++it) { - http_header = curl_slist_append(http_header, it->c_str()); + for (const std::string &extra_header : request.extra_headers) { + http_header = curl_slist_append(http_header, extra_header.c_str()); } curl_easy_setopt(curl, CURLOPT_HTTPHEADER, http_header); @@ -646,8 +658,6 @@ class CurlFetchThread : public Thread void *run() { - DSTACK(FUNCTION_NAME); - CurlHandlePool pool; m_multi = curl_multi_init(); @@ -711,8 +721,8 @@ class CurlFetchThread : public Thread } // Call curl_multi_remove_handle and cleanup easy handles - for (size_t i = 0; i < m_all_ongoing.size(); ++i) { - delete m_all_ongoing[i]; + for (HTTPFetchOngoing *i : m_all_ongoing) { + delete i; } m_all_ongoing.clear(); @@ -751,10 +761,12 @@ void httpfetch_cleanup() { verbosestream<<"httpfetch_cleanup: cleaning up"<stop(); - g_httpfetch_thread->requestWakeUp(); - g_httpfetch_thread->wait(); - delete g_httpfetch_thread; + if (g_httpfetch_thread) { + g_httpfetch_thread->stop(); + g_httpfetch_thread->requestWakeUp(); + g_httpfetch_thread->wait(); + delete g_httpfetch_thread; + } curl_global_cleanup(); }