diff options
Diffstat (limited to 'indra/llmessage/llcurl.h')
-rw-r--r-- | indra/llmessage/llcurl.h | 194 |
1 files changed, 189 insertions, 5 deletions
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h index 4ce3fa1078..705cdcbbcc 100644 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -41,8 +41,11 @@ #include "llbuffer.h" #include "lliopipe.h" #include "llsd.h" +#include "llthread.h" +#include "llqueuedthread.h" class LLMutex; +class LLCurlThread; // For whatever reason, this is not typedef'd in curl.h typedef size_t (*curl_header_callback)(void *ptr, size_t size, size_t nmemb, void *stream); @@ -159,7 +162,7 @@ public: /** * @ brief Initialize LLCurl class */ - static void initClass(); + static void initClass(bool multi_threaded = false); /** * @ brief Cleanup LLCurl class @@ -178,12 +181,184 @@ public: static void ssl_locking_callback(int mode, int type, const char *file, int line); static unsigned long ssl_thread_id(void); + static LLCurlThread* getCurlThread() { return sCurlThread ;} private: static std::string sCAPath; static std::string sCAFile; static const unsigned int MAX_REDIRECTS; + static LLCurlThread* sCurlThread; }; +class LLCurl::Easy +{ + LOG_CLASS(Easy); + +private: + Easy(); + +public: + static Easy* getEasy(); + ~Easy(); + + CURL* getCurlHandle() const { return mCurlEasyHandle; } + + void setErrorBuffer(); + void setCA(); + + void setopt(CURLoption option, S32 value); + // These assume the setter does not free value! + void setopt(CURLoption option, void* value); + void setopt(CURLoption option, char* value); + // Copies the string so that it is guaranteed to stick around + void setoptString(CURLoption option, const std::string& value); + + void slist_append(const char* str); + void setHeaders(); + + U32 report(CURLcode); + void getTransferInfo(LLCurl::TransferInfo* info); + + void prepRequest(const std::string& url, const std::vector<std::string>& headers, LLCurl::ResponderPtr, S32 time_out = 0, bool post = false); + + const char* getErrorBuffer(); + + std::stringstream& getInput() { return mInput; } + std::stringstream& getHeaderOutput() { return mHeaderOutput; } + LLIOPipe::buffer_ptr_t& getOutput() { return mOutput; } + const LLChannelDescriptors& getChannels() { return mChannels; } + + void resetState(); + + static CURL* allocEasyHandle(); + static void releaseEasyHandle(CURL* handle); + +private: + friend class LLCurl; + friend class LLCurl::Multi; + + CURL* mCurlEasyHandle; + struct curl_slist* mHeaders; + + std::stringstream mRequest; + LLChannelDescriptors mChannels; + LLIOPipe::buffer_ptr_t mOutput; + std::stringstream mInput; + std::stringstream mHeaderOutput; + char mErrorBuffer[CURL_ERROR_SIZE]; + + // Note: char*'s not strings since we pass pointers to curl + std::vector<char*> mStrings; + + LLCurl::ResponderPtr mResponder; + + static std::set<CURL*> sFreeHandles; + static std::set<CURL*> sActiveHandles; + static LLMutex* sHandleMutexp ; +}; + +class LLCurl::Multi +{ + LOG_CLASS(Multi); + + friend class LLCurlThread ; + +private: + ~Multi(); + + void markDead() ; + bool doPerform(); + +public: + + typedef enum + { + STATE_READY=0, + STATE_PERFORMING=1, + STATE_COMPLETED=2 + } ePerformState; + + Multi(); + + LLCurl::Easy* allocEasy(); + bool addEasy(LLCurl::Easy* easy); + void removeEasy(LLCurl::Easy* easy); + + void lock() ; + void unlock() ; + + void setState(ePerformState state) ; + ePerformState getState() ; + bool isCompleted() ; + + bool waitToComplete() ; + + S32 process(); + + CURLMsg* info_read(S32* msgs_in_queue); + + S32 mQueued; + S32 mErrorCount; + + static CURLM* initMulti() ; +private: + void easyFree(LLCurl::Easy*); + + CURLM* mCurlMultiHandle; + + typedef std::set<LLCurl::Easy*> easy_active_list_t; + easy_active_list_t mEasyActiveList; + typedef std::map<CURL*, LLCurl::Easy*> easy_active_map_t; + easy_active_map_t mEasyActiveMap; + typedef std::set<LLCurl::Easy*> easy_free_list_t; + easy_free_list_t mEasyFreeList; + + LLQueuedThread::handle_t mHandle ; + ePerformState mState; + + BOOL mDead ; + LLMutex* mMutexp ; + LLMutex* mDeletionMutexp ; + LLMutex* mEasyMutexp ; + + static LLMutex* sMultiInitMutexp ; +}; + +class LLCurlThread : public LLQueuedThread +{ +public: + + class CurlRequest : public LLQueuedThread::QueuedRequest + { + protected: + virtual ~CurlRequest(); // use deleteRequest() + + public: + CurlRequest(handle_t handle, LLCurl::Multi* multi, LLCurlThread* curl_thread); + + /*virtual*/ bool processRequest(); + /*virtual*/ void finishRequest(bool completed); + + private: + // input + LLCurl::Multi* mMulti; + LLCurlThread* mCurlThread; + }; + friend class CurlRequest; + +public: + LLCurlThread(bool threaded = true) ; + virtual ~LLCurlThread() ; + + S32 update(U32 max_time_ms); + + void addMulti(LLCurl::Multi* multi) ; + void killMulti(LLCurl::Multi* multi) ; + +private: + bool doMultiPerform(LLCurl::Multi* multi) ; + void deleteMulti(LLCurl::Multi* multi) ; +} ; + namespace boost { void intrusive_ptr_add_ref(LLCurl::Responder* p); @@ -201,8 +376,8 @@ public: void get(const std::string& url, LLCurl::ResponderPtr responder); bool getByteRange(const std::string& url, const headers_t& headers, S32 offset, S32 length, LLCurl::ResponderPtr responder); - bool post(const std::string& url, const headers_t& headers, const LLSD& data, LLCurl::ResponderPtr responder); - bool post(const std::string& url, const headers_t& headers, const std::string& data, LLCurl::ResponderPtr responder); + bool post(const std::string& url, const headers_t& headers, const LLSD& data, LLCurl::ResponderPtr responder, S32 time_out = 0); + bool post(const std::string& url, const headers_t& headers, const std::string& data, LLCurl::ResponderPtr responder, S32 time_out = 0); S32 process(); S32 getQueued(); @@ -218,7 +393,6 @@ private: LLCurl::Multi* mActiveMulti; S32 mActiveRequestCount; BOOL mProcessing; - U32 mThreadID; // debug }; class LLCurlEasyRequest @@ -236,9 +410,12 @@ public: void slist_append(const char* str); void sendRequest(const std::string& url); void requestComplete(); - S32 perform(); bool getResult(CURLcode* result, LLCurl::TransferInfo* info = NULL); std::string getErrorString(); + bool isCompleted() {return mMulti->isCompleted() ;} + bool wait() { return mMulti->waitToComplete(); } + + LLCurl::Easy* getEasy() const { return mEasy; } private: CURLMsg* info_read(S32* queue, LLCurl::TransferInfo* info); @@ -250,4 +427,11 @@ private: bool mResultReturned; }; +// Provide access to LLCurl free functions outside of llcurl.cpp without polluting the global namespace. +namespace LLCurlFF +{ + void check_easy_code(CURLcode code); + void check_multi_code(CURLMcode code); +} + #endif // LL_LLCURL_H |