]> git.lizzy.rs Git - minetest.git/blobdiff - src/httpfetch.cpp
Set acceleration only once in falling node
[minetest.git] / src / httpfetch.cpp
index c60e141fc087fbdcd40fc09d1ec2a437db1a88da..f64c9f717a62c36f9e976da22e98a363532684f0 100644 (file)
@@ -18,14 +18,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 #include "socket.h" // for select()
-#include "porting.h" // for sleep_ms(), get_sysinfo()
+#include "porting.h" // for sleep_ms(), get_sysinfo(), secure_rand_fill_buf()
 #include "httpfetch.h"
 #include <iostream>
 #include <sstream>
 #include <list>
 #include <map>
 #include <errno.h>
-#include "jthread/jevent.h"
+#include "threading/event.h"
 #include "config.h"
 #include "exceptions.h"
 #include "debug.h"
@@ -34,9 +34,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "util/thread.h"
 #include "version.h"
 #include "settings.h"
+#include "noise.h"
 
-JMutex g_httpfetch_mutex;
+Mutex g_httpfetch_mutex;
 std::map<unsigned long, std::queue<HTTPFetchResult> > g_httpfetch_results;
+PcgRandom g_callerid_randomness;
 
 HTTPFetchRequest::HTTPFetchRequest()
 {
@@ -55,7 +57,7 @@ static void httpfetch_deliver_result(const HTTPFetchResult &fetch_result)
 {
        unsigned long caller = fetch_result.caller;
        if (caller != HTTPFETCH_DISCARD) {
-               JMutexAutoLock lock(g_httpfetch_mutex);
+               MutexAutoLock lock(g_httpfetch_mutex);
                g_httpfetch_results[caller].push(fetch_result);
        }
 }
@@ -64,7 +66,7 @@ static void httpfetch_request_clear(unsigned long caller);
 
 unsigned long httpfetch_caller_alloc()
 {
-       JMutexAutoLock lock(g_httpfetch_mutex);
+       MutexAutoLock lock(g_httpfetch_mutex);
 
        // Check each caller ID except HTTPFETCH_DISCARD
        const unsigned long discard = HTTPFETCH_DISCARD;
@@ -84,6 +86,34 @@ unsigned long httpfetch_caller_alloc()
        return discard;
 }
 
+unsigned long httpfetch_caller_alloc_secure()
+{
+       MutexAutoLock lock(g_httpfetch_mutex);
+
+       // Generate random caller IDs and make sure they're not
+       // already used or equal to HTTPFETCH_DISCARD
+       // Give up after 100 tries to prevent infinite loop
+       u8 tries = 100;
+       unsigned long caller;
+
+       do {
+               caller = (((u64) g_callerid_randomness.next()) << 32) |
+                               g_callerid_randomness.next();
+
+               if (--tries < 1) {
+                       FATAL_ERROR("httpfetch_caller_alloc_secure: ran out of caller IDs");
+                       return HTTPFETCH_DISCARD;
+               }
+       } while (g_httpfetch_results.find(caller) != g_httpfetch_results.end());
+
+       verbosestream << "httpfetch_caller_alloc_secure: allocating "
+               << caller << std::endl;
+
+       // Access element to create it
+       g_httpfetch_results[caller];
+       return caller;
+}
+
 void httpfetch_caller_free(unsigned long caller)
 {
        verbosestream<<"httpfetch_caller_free: freeing "
@@ -91,14 +121,14 @@ void httpfetch_caller_free(unsigned long caller)
 
        httpfetch_request_clear(caller);
        if (caller != HTTPFETCH_DISCARD) {
-               JMutexAutoLock lock(g_httpfetch_mutex);
+               MutexAutoLock lock(g_httpfetch_mutex);
                g_httpfetch_results.erase(caller);
        }
 }
 
 bool httpfetch_async_get(unsigned long caller, HTTPFetchResult &fetch_result)
 {
-       JMutexAutoLock lock(g_httpfetch_mutex);
+       MutexAutoLock lock(g_httpfetch_mutex);
 
        // Check that caller exists
        std::map<unsigned long, std::queue<HTTPFetchResult> >::iterator
@@ -262,12 +292,11 @@ HTTPFetchOngoing::HTTPFetchOngoing(HTTPFetchRequest request_, CurlHandlePool *po
        }
 
        // Set POST (or GET) data
-       if (request.post_fields.empty()) {
+       if (request.post_fields.empty() && request.post_data.empty()) {
                curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
        } else if (request.multipart) {
                curl_httppost *last = NULL;
-               for (std::map<std::string, std::string>::iterator it =
-                                       request.post_fields.begin();
+               for (StringMap::iterator it = request.post_fields.begin();
                                it != request.post_fields.end(); ++it) {
                        curl_formadd(&post, &last,
                                        CURLFORM_NAMELENGTH, it->first.size(),
@@ -282,10 +311,8 @@ HTTPFetchOngoing::HTTPFetchOngoing(HTTPFetchRequest request_, CurlHandlePool *po
        } else if (request.post_data.empty()) {
                curl_easy_setopt(curl, CURLOPT_POST, 1);
                std::string str;
-               for (std::map<std::string, std::string>::iterator it =
-                                       request.post_fields.begin();
-                               it != request.post_fields.end();
-                               ++it) {
+               for (StringMap::iterator it = request.post_fields.begin();
+                               it != request.post_fields.end(); ++it) {
                        if (str != "")
                                str += "&";
                        str += urlencode(it->first);
@@ -393,7 +420,7 @@ HTTPFetchOngoing::~HTTPFetchOngoing()
 }
 
 
-class CurlFetchThread : public JThread
+class CurlFetchThread : public Thread
 {
 protected:
        enum RequestType {
@@ -417,7 +444,8 @@ class CurlFetchThread : public JThread
        std::list<HTTPFetchRequest> m_queued_fetches;
 
 public:
-       CurlFetchThread(int parallel_limit)
+       CurlFetchThread(int parallel_limit) :
+               Thread("CurlFetch")
        {
                if (parallel_limit >= 1)
                        m_parallel_limit = parallel_limit;
@@ -616,13 +644,9 @@ class CurlFetchThread : public JThread
                }
        }
 
-       void * Thread()
+       void *run()
        {
-               ThreadStarted();
-               log_register_thread("CurlFetchThread");
-               DSTACK(__FUNCTION_NAME);
-
-               porting::setThreadName("CurlFetchThread");
+               DSTACK(FUNCTION_NAME);
 
                CurlHandlePool pool;
 
@@ -634,7 +658,7 @@ class CurlFetchThread : public JThread
 
                FATAL_ERROR_IF(!m_all_ongoing.empty(), "Expected empty");
 
-               while (!StopRequested()) {
+               while (!stopRequested()) {
                        BEGIN_DEBUG_EXCEPTION_HANDLER
 
                        /*
@@ -683,7 +707,7 @@ class CurlFetchThread : public JThread
                        else
                                waitForIO(100);
 
-                       END_DEBUG_EXCEPTION_HANDLER(errorstream)
+                       END_DEBUG_EXCEPTION_HANDLER
                }
 
                // Call curl_multi_remove_handle and cleanup easy handles
@@ -716,15 +740,20 @@ void httpfetch_init(int parallel_limit)
        FATAL_ERROR_IF(res != CURLE_OK, "CURL init failed");
 
        g_httpfetch_thread = new CurlFetchThread(parallel_limit);
+
+       // Initialize g_callerid_randomness for httpfetch_caller_alloc_secure
+       u64 randbuf[2];
+       porting::secure_rand_fill_buf(randbuf, sizeof(u64) * 2);
+       g_callerid_randomness = PcgRandom(randbuf[0], randbuf[1]);
 }
 
 void httpfetch_cleanup()
 {
        verbosestream<<"httpfetch_cleanup: cleaning up"<<std::endl;
 
-       g_httpfetch_thread->Stop();
+       g_httpfetch_thread->stop();
        g_httpfetch_thread->requestWakeUp();
-       g_httpfetch_thread->Wait();
+       g_httpfetch_thread->wait();
        delete g_httpfetch_thread;
 
        curl_global_cleanup();
@@ -733,18 +762,17 @@ void httpfetch_cleanup()
 void httpfetch_async(const HTTPFetchRequest &fetch_request)
 {
        g_httpfetch_thread->requestFetch(fetch_request);
-       if (!g_httpfetch_thread->IsRunning())
-               g_httpfetch_thread->Start();
+       if (!g_httpfetch_thread->isRunning())
+               g_httpfetch_thread->start();
 }
 
 static void httpfetch_request_clear(unsigned long caller)
 {
-       if (g_httpfetch_thread->IsRunning()) {
+       if (g_httpfetch_thread->isRunning()) {
                Event event;
                g_httpfetch_thread->requestClear(caller, &event);
                event.wait();
-       }
-       else {
+       } else {
                g_httpfetch_thread->requestClear(caller, NULL);
        }
 }