aboutsummaryrefslogtreecommitdiff
path: root/src/httpfetch.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/httpfetch.cpp')
-rw-r--r--src/httpfetch.cpp81
1 files changed, 56 insertions, 25 deletions
diff --git a/src/httpfetch.cpp b/src/httpfetch.cpp
index 56cdad2b1..f64c9f717 100644
--- a/src/httpfetch.cpp
+++ b/src/httpfetch.cpp
@@ -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,7 +292,7 @@ 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;
@@ -390,7 +420,7 @@ HTTPFetchOngoing::~HTTPFetchOngoing()
}
-class CurlFetchThread : public JThread
+class CurlFetchThread : public Thread
{
protected:
enum RequestType {
@@ -414,7 +444,8 @@ protected:
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;
@@ -613,13 +644,9 @@ protected:
}
}
- void * Thread()
+ void *run()
{
- ThreadStarted();
- log_register_thread("CurlFetchThread");
- DSTACK(__FUNCTION_NAME);
-
- porting::setThreadName("CurlFetchThread");
+ DSTACK(FUNCTION_NAME);
CurlHandlePool pool;
@@ -631,7 +658,7 @@ protected:
FATAL_ERROR_IF(!m_all_ongoing.empty(), "Expected empty");
- while (!StopRequested()) {
+ while (!stopRequested()) {
BEGIN_DEBUG_EXCEPTION_HANDLER
/*
@@ -680,7 +707,7 @@ protected:
else
waitForIO(100);
- END_DEBUG_EXCEPTION_HANDLER(errorstream)
+ END_DEBUG_EXCEPTION_HANDLER
}
// Call curl_multi_remove_handle and cleanup easy handles
@@ -713,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();
@@ -730,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);
}
}