*/
#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 <mutex>
#include "threading/event.h"
#include "config.h"
#include "exceptions.h"
#include "util/thread.h"
#include "version.h"
#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() + ")";
}
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 "
class HTTPFetchOngoing
{
public:
- HTTPFetchOngoing(HTTPFetchRequest request, CurlHandlePool *pool);
+ HTTPFetchOngoing(const HTTPFetchRequest &request, CurlHandlePool *pool);
~HTTPFetchOngoing();
CURLcode start(CURLM *multi);
};
-HTTPFetchOngoing::HTTPFetchOngoing(HTTPFetchRequest request_, CurlHandlePool *pool_):
+HTTPFetchOngoing::HTTPFetchOngoing(const HTTPFetchRequest &request_,
+ CurlHandlePool *pool_):
pool(pool_),
curl(NULL),
multi(NULL),
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()