]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/httpfetch.cpp
serverpackethandler: Minor log message fixes
[dragonfireclient.git] / src / httpfetch.cpp
index f64c9f717a62c36f9e976da22e98a363532684f0..65202ce3ebac5ff72c6d14777b2e94cdc0aee35b 100644 (file)
@@ -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 <iostream>
 #include <sstream>
 #include <list>
 #include <map>
-#include <errno.h>
+#include <cerrno>
+#include <mutex>
+#include "network/socket.h" // for select()
 #include "threading/event.h"
 #include "config.h"
 #include "exceptions.h"
@@ -36,20 +37,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "settings.h"
 #include "noise.h"
 
-Mutex g_httpfetch_mutex;
+std::mutex g_httpfetch_mutex;
 std::map<unsigned long, std::queue<HTTPFetchResult> > g_httpfetch_results;
 PcgRandom g_callerid_randomness;
 
-HTTPFetchRequest::HTTPFetchRequest()
+HTTPFetchRequest::HTTPFetchRequest() :
+       timeout(g_settings->getS32("curl_timeout")),
+       connect_timeout(timeout),
+       useragent(std::string(PROJECT_NAME_C "/") + g_version_hash + " (" + porting::get_sysinfo() + ")")
 {
-       url = "";
-       caller = HTTPFETCH_DISCARD;
-       request_id = 0;
-       timeout = g_settings->getS32("curl_timeout");
-       connect_timeout = timeout;
-       multipart = false;
-
-       useragent = std::string(PROJECT_NAME_C "/") + g_version_hash + " (" + porting::get_sysinfo() + ")";
 }
 
 
@@ -174,7 +170,8 @@ class CurlHandlePool
        std::list<CURL*> handles;
 
 public:
-       CurlHandlePool() {}
+       CurlHandlePool() = default;
+
        ~CurlHandlePool()
        {
                for (std::list<CURL*>::iterator it = handles.begin();
@@ -207,7 +204,7 @@ class CurlHandlePool
 class HTTPFetchOngoing
 {
 public:
-       HTTPFetchOngoing(HTTPFetchRequest request, CurlHandlePool *pool);
+       HTTPFetchOngoing(const HTTPFetchRequest &request, CurlHandlePool *pool);
        ~HTTPFetchOngoing();
 
        CURLcode start(CURLM *multi);
@@ -228,7 +225,8 @@ class HTTPFetchOngoing
 };
 
 
-HTTPFetchOngoing::HTTPFetchOngoing(HTTPFetchRequest request_, CurlHandlePool *pool_):
+HTTPFetchOngoing::HTTPFetchOngoing(const HTTPFetchRequest &request_,
+               CurlHandlePool *pool_):
        pool(pool_),
        curl(NULL),
        multi(NULL),
@@ -247,13 +245,18 @@ HTTPFetchOngoing::HTTPFetchOngoing(HTTPFetchRequest request_, CurlHandlePool *po
        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 +278,7 @@ HTTPFetchOngoing::HTTPFetchOngoing(HTTPFetchRequest request_, CurlHandlePool *po
        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 +294,11 @@ HTTPFetchOngoing::HTTPFetchOngoing(HTTPFetchRequest request_, CurlHandlePool *po
                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 +309,46 @@ HTTPFetchOngoing::HTTPFetchOngoing(HTTPFetchRequest request_, CurlHandlePool *po
                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<std::string>::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 +659,6 @@ class CurlFetchThread : public Thread
 
        void *run()
        {
-               DSTACK(FUNCTION_NAME);
-
                CurlHandlePool pool;
 
                m_multi = curl_multi_init();
@@ -711,8 +722,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();