#include "../../shared/ThreadMonitor.h" #include "CurlThread.h" ///////////////////////////////////////////////////////////////////// // CurlRequest ///////////////////////////////////////////////////////////////////// size_t CurlRequest::writeFunctionImpl(void *ptr, size_t size, size_t nmemb) { size_t bytes = size * nmemb; _result.append((char const *)ptr, bytes); return bytes; } size_t CurlRequest::writeFunction(void *ptr, size_t size, size_t nmemb, void *userdata) { return ((CurlRequest *)userdata)->writeFunctionImpl(ptr, size, nmemb); } char const *CurlRequest::getSafePointer(std::string s) { _savedStrings.push_back(s); return s.c_str(); } void CurlRequest::clearSafePointers() { _savedStrings.clear(); } CurlRequest::CurlRequest(SocketInfo *socket, RequestListener *returnThread, int returnId) : Request(socket), _returnThread(returnThread), _returnId(returnId), _handle(curl_easy_init()) { // Capture the output curl_easy_setopt(_handle, CURLOPT_WRITEFUNCTION, writeFunction); curl_easy_setopt(_handle, CURLOPT_WRITEDATA, this); // Signals are a bad idea in a multithreaded program. curl_easy_setopt(_handle, CURLOPT_NOSIGNAL, 1); // Set some reasonable defaults. Because we only send one request at a // time, having no timeout or a very long timeout seems like a bad idea. curl_easy_setopt(_handle, CURLOPT_TIMEOUT, 15); curl_easy_setopt(_handle, CURLOPT_CONNECTTIMEOUT, 5); } CurlRequest::~CurlRequest() { curl_easy_cleanup(_handle); } void CurlRequest::doInThread() { _result.clear(); _status = curl_easy_perform(_handle); ThreadMonitor::find().increment(_status?"CURL_SUCCESS":"CURL_ERROR"); callbackId = _returnId; _returnThread->newRequest(this); } ///////////////////////////////////////////////////////////////////// // CurlThread ///////////////////////////////////////////////////////////////////// void CurlThread::threadFunction() { ThreadMonitor &tm = ThreadMonitor::find(); while (true) { while (Request *current = _incoming.getRequest()) { switch (current->callbackId) { case mtNewRequest: { tm.setState("mtNewRequest"); CurlRequest *request = dynamic_cast< CurlRequest * >(current); request->doInThread(); current = NULL; break; } case mtQuit: { delete current; return; } } delete current; } tm.setState("waitForRequest()"); _incoming.waitForRequest(); } } CurlThread::CurlThread() : ThreadClass("CurlThread"), _incoming(getName()) { startThread(); } CurlThread::~CurlThread() { Request *r = new Request(NULL); r->callbackId = mtQuit; _incoming.newRequest(r); }