#ifndef __CurlThread_h_ #define __CurlThread_h_ #include #include "../../shared/Messages.h" #include "../../shared/ThreadClass.h" /* This is a simple wrapper around lib curl which allows us to send https * requests and receive a result. For simplicity we only support the * "easy" interface and we only send one request at a time. * * This was aimed at SMB, which uses XML RPC to tell us if the username / * password combination is valid. However, this particular unit is very * generic and should allow any "easy" curl tasks. * * This unit takes care of some basics, including creating and releasing * the curl handle, and collecting the results. The curl thread will do the * curl_easy_perform operation. The caller is responsible for most of the * calls to curl_easy_setopt. * * I created a seperate thread so most of the program could continue running * while the https requests were handled asynchronously. Performance is * still limited because we can only send one request at a time. However, * I don't expect that to be a problem. There might be some value to the * curl "multi" interface, or to having more than one curl thread. However, * if we get too much traffic we can go a different route, like caching the * results, and/or asking them for the valid ids in a different way. */ class CurlRequest : public Request { private: RequestListener *const _returnThread; const int _returnId; CURL *const _handle; std::string _result; CURLcode _status; std::vector< std::string > _savedStrings; size_t writeFunctionImpl(void *ptr, size_t size, size_t nmemb); static size_t writeFunction(void *ptr, size_t size, size_t nmemb, void *userdata); public: // Access the curl stuff. This is all public because you can use this // class as is. You don't have to make a subclass. CURL *getHandle() const { return _handle; } std::string const &getResult() const { return _result; } CURLcode getStatus() const { return _status; } // Store a copy of the string in this object. That way you can use the // pointer in curl_easy_setopt. The strings are automatically cleared // when this object is destroyed. You can clear the saved strings sooner // if you wish. That might be helpful if you plan to reuse on of these // requests several times. We do not clear the curl options at the end of // a request, so we do not clear this cache. char const *getSafePointer(std::string s); void clearSafePointers(); void setStringOpt(CURLoption opt, std::string s) { curl_easy_setopt(_handle, opt, getSafePointer(s)); } CurlRequest(SocketInfo *socket, RequestListener *returnThread, int returnId); ~CurlRequest(); void doInThread(); }; class CurlThread : private ThreadClass { private: enum { mtNewRequest, mtQuit }; RequestQueue _incoming; protected: virtual void threadFunction(); public: CurlThread(); ~CurlThread(); void newRequest(CurlRequest *request) { request->callbackId = mtNewRequest; _incoming.newRequest(request); } }; #endif