From 68ad5411c94b38b1821a86c866091d51ddaa6943 Mon Sep 17 00:00:00 2001 From: Siana Gearz Date: Tue, 7 Aug 2012 13:12:56 +0200 Subject: [PATCH] Shyotl's old llcurl --- indra/llmessage/llcurl.cpp | 763 +++++++------------------- indra/llmessage/llcurl.h | 165 ++---- indra/llmessage/llhttpclient.cpp | 52 +- indra/llmessage/llhttpclient.h | 6 +- indra/llmessage/llurlrequest.cpp | 55 +- indra/llmessage/llurlrequest.h | 11 +- indra/newview/llappviewer.cpp | 5 +- indra/newview/llxmlrpctransaction.cpp | 14 +- 8 files changed, 290 insertions(+), 781 deletions(-) diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 617d43980..fc057d969 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -72,9 +72,10 @@ static const U32 EASY_HANDLE_POOL_SIZE = 5; static const S32 MULTI_PERFORM_CALL_REPEAT = 5; -static const S32 CURL_REQUEST_TIMEOUT = 30; // seconds per operation +static const S32 CURL_REQUEST_TIMEOUT = 30; // seconds static const S32 MAX_ACTIVE_REQUEST_COUNT = 100; +static // DEBUG // S32 gCurlEasyCount = 0; S32 gCurlMultiCount = 0; @@ -85,12 +86,9 @@ S32 gCurlMultiCount = 0; std::vector LLCurl::sSSLMutex; std::string LLCurl::sCAPath; std::string LLCurl::sCAFile; -LLCurlThread* LLCurl::sCurlThread = NULL ; -LLMutex* LLCurl::sHandleMutexp = NULL ; -S32 LLCurl::sTotalHandles = 0 ; -bool LLCurl::sNotQuitting = true; -F32 LLCurl::sCurlRequestTimeOut = 120.f; //seonds -S32 LLCurl::sMaxHandles = 256; //max number of handles, (multi handles and easy handles combined). + +bool LLCurl::sMultiThreaded = false; +static U32 sMainThreadID = 0; void check_curl_code(CURLcode code) { @@ -179,7 +177,6 @@ void LLCurl::Responder::completedRaw( { llinfos << "Failed to deserialize LLSD. " << mURL << " [" << status << "]: " << reason << llendl; } - completed(status, reason, content); } @@ -202,8 +199,8 @@ void LLCurl::Responder::completedHeader(U32 status, const std::string& reason, c } -//namespace boost -//{ +namespace boost +{ void intrusive_ptr_add_ref(LLCurl::Responder* p) { ++p->mReferenceCount; @@ -211,32 +208,29 @@ void LLCurl::Responder::completedHeader(U32 status, const std::string& reason, c void intrusive_ptr_release(LLCurl::Responder* p) { - if (p && 0 == --p->mReferenceCount) + if(p && 0 == --p->mReferenceCount) { delete p; } } -//}; +}; ////////////////////////////////////////////////////////////////////////////// std::set LLCurl::Easy::sFreeHandles; std::set LLCurl::Easy::sActiveHandles; -LLMutex* LLCurl::Easy::sHandleMutexp = NULL ; +LLMutex* LLCurl::Easy::sHandleMutex = NULL; +LLMutex* LLCurl::Easy::sMultiMutex = NULL; //static CURL* LLCurl::Easy::allocEasyHandle() { - llassert(LLCurl::getCurlThread()) ; - CURL* ret = NULL; - - LLMutexLock lock(sHandleMutexp) ; - + LLMutexLock lock(sHandleMutex); if (sFreeHandles.empty()) { - ret = LLCurl::newEasyHandle(); + ret = curl_easy_init(); } else { @@ -256,29 +250,19 @@ CURL* LLCurl::Easy::allocEasyHandle() //static void LLCurl::Easy::releaseEasyHandle(CURL* handle) { - static const S32 MAX_NUM_FREE_HANDLES = 32 ; - if (!handle) { - return ; //handle allocation failed. - //llerrs << "handle cannot be NULL!" << llendl; + llerrs << "handle cannot be NULL!" << llendl; } - LLMutexLock lock(sHandleMutexp) ; + LLMutexLock lock(sHandleMutex); + if (sActiveHandles.find(handle) != sActiveHandles.end()) { sActiveHandles.erase(handle); - - if(sFreeHandles.size() < MAX_NUM_FREE_HANDLES) - { sFreeHandles.insert(handle); } else - { - LLCurl::deleteEasyHandle(handle) ; - } - } - else { llerrs << "Invalid handle." << llendl; } @@ -308,7 +292,7 @@ LLCurl::Easy* LLCurl::Easy::getEasy() // multi handles cache if they are added to one. CURLcode result = curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_DNS_CACHE_TIMEOUT, 0); check_curl_code(result); - + // Disable SSL/TLS session caching. Some servers refuse to talk to us when session ids are enabled. // id.secondlife.com is such a server, when greeted with a SSL HELLO and a session id, it immediatly returns a RST packet and closes // the connections. @@ -316,7 +300,6 @@ LLCurl::Easy* LLCurl::Easy::getEasy() result = curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_SSL_SESSIONID_CACHE, 0); check_curl_code(result); - ++gCurlEasyCount; return easy; } @@ -327,14 +310,6 @@ LLCurl::Easy::~Easy() --gCurlEasyCount; curl_slist_free_all(mHeaders); for_each(mStrings.begin(), mStrings.end(), DeletePointerArray()); - - if (mResponder && LLCurl::sNotQuitting) //aborted - { - std::string reason("Request timeout, aborted.") ; - mResponder->completedRaw(408, //HTTP_REQUEST_TIME_OUT, timeout, abort - reason, mChannels, mOutput); - } - mResponder = NULL; } void LLCurl::Easy::resetState() @@ -373,11 +348,11 @@ const char* LLCurl::Easy::getErrorBuffer() void LLCurl::Easy::setCA() { - if (!sCAPath.empty()) + if(!sCAPath.empty()) { setoptString(CURLOPT_CAPATH, sCAPath); } - if (!sCAFile.empty()) + if(!sCAFile.empty()) { setoptString(CURLOPT_CAINFO, sCAFile); } @@ -403,7 +378,7 @@ U32 LLCurl::Easy::report(CURLcode code) if (code == CURLE_OK) { check_curl_code(curl_easy_getinfo(mCurlEasyHandle, CURLINFO_RESPONSE_CODE, &responseCode)); - //*TODO: get reason from first line of mHeaderOutput + // *TODO: get reason from first line of mHeaderOutput } else { @@ -411,7 +386,7 @@ U32 LLCurl::Easy::report(CURLcode code) responseReason = strerror(code) + " : " + mErrorBuffer; setopt(CURLOPT_FRESH_CONNECT, TRUE); } - + if (mResponder) { mResponder->completedRaw(responseCode, responseReason, mChannels, mOutput); @@ -507,7 +482,6 @@ void LLCurl::Easy::prepRequest(const std::string& url, LLProxy::getInstance()->applyProxySettings(this); mOutput.reset(new LLBufferArray); - mOutput->setThreaded(true); setopt(CURLOPT_WRITEFUNCTION, (void*)&curlWriteCallback); setopt(CURLOPT_WRITEDATA, (void*)this); @@ -516,9 +490,8 @@ void LLCurl::Easy::prepRequest(const std::string& url, setopt(CURLOPT_HEADERFUNCTION, (void*)&curlHeaderCallback); setopt(CURLOPT_HEADERDATA, (void*)this); - // Allow up to five redirects - if (responder && responder->followRedir()) + if(responder && responder->followRedir()) { setopt(CURLOPT_FOLLOWLOCATION, 1); setopt(CURLOPT_MAXREDIRS, MAX_REDIRECTS); @@ -551,74 +524,54 @@ void LLCurl::Easy::prepRequest(const std::string& url, } //////////////////////////////////////////////////////////////////////////// -LLCurl::Multi::Multi(F32 idle_time_out) - : mQueued(0), + +LLCurl::Multi::Multi() + : LLThread("Curl Multi"), + mQueued(0), mErrorCount(0), - mState(STATE_READY), - mDead(FALSE), - mValid(TRUE), - mMutexp(NULL), - mDeletionMutexp(NULL), - mEasyMutexp(NULL) + mPerformState(PERFORM_STATE_READY) { - mCurlMultiHandle = LLCurl::newMultiHandle(); + mQuitting = false; + + mThreaded = LLCurl::sMultiThreaded && LLThread::currentID() == sMainThreadID; + if (mThreaded) + { + mSignal = new LLCondition; + } + else + { + mSignal = NULL; + } + + mCurlMultiHandle = curl_multi_init(); if (!mCurlMultiHandle) { llwarns << "curl_multi_init() returned NULL! Easy handles: " << gCurlEasyCount << " Multi handles: " << gCurlMultiCount << llendl; - mCurlMultiHandle = LLCurl::newMultiHandle(); + mCurlMultiHandle = curl_multi_init(); } - //llassert_always(mCurlMultiHandle); - - if(mCurlMultiHandle) - { - if(LLCurl::getCurlThread()->getThreaded()) - { - mMutexp = new LLMutex() ; - mDeletionMutexp = new LLMutex() ; - mEasyMutexp = new LLMutex() ; - } - LLCurl::getCurlThread()->addMulti(this) ; - - mIdleTimeOut = idle_time_out ; - if(mIdleTimeOut < LLCurl::sCurlRequestTimeOut) - { - mIdleTimeOut = LLCurl::sCurlRequestTimeOut ; - } - + llassert_always(mCurlMultiHandle); ++gCurlMultiCount; } -} LLCurl::Multi::~Multi() { - cleanup(true) ; - - delete mDeletionMutexp ; - mDeletionMutexp = NULL ; -} + llassert(isStopped()); -void LLCurl::Multi::cleanup(bool deleted) -{ - if(!mCurlMultiHandle) + if (LLCurl::sMultiThreaded) { - return ; //nothing to clean. + LLCurl::Easy::sMultiMutex->lock(); } - llassert_always(deleted || !mValid) ; - LLMutexLock lock(mDeletionMutexp); - + delete mSignal; + mSignal = NULL; + // Clean up active for(easy_active_list_t::iterator iter = mEasyActiveList.begin(); iter != mEasyActiveList.end(); ++iter) { Easy* easy = *iter; check_curl_multi_code(curl_multi_remove_handle(mCurlMultiHandle, easy->getCurlHandle())); - - if(deleted) - { - easy->mResponder = NULL ; //avoid triggering mResponder. - } delete easy; } mEasyActiveList.clear(); @@ -628,169 +581,84 @@ void LLCurl::Multi::cleanup(bool deleted) for_each(mEasyFreeList.begin(), mEasyFreeList.end(), DeletePointer()); mEasyFreeList.clear(); - check_curl_multi_code(LLCurl::deleteMultiHandle(mCurlMultiHandle)); - mCurlMultiHandle = NULL ; - - delete mMutexp ; - mMutexp = NULL ; - delete mEasyMutexp ; - mEasyMutexp = NULL ; - - mQueued = 0 ; - mState = STATE_COMPLETED; - + check_curl_multi_code(curl_multi_cleanup(mCurlMultiHandle)); --gCurlMultiCount; - return ; -} - -void LLCurl::Multi::lock() -{ - if(mMutexp) + if (LLCurl::sMultiThreaded) { - mMutexp->lock() ; + LLCurl::Easy::sMultiMutex->unlock(); } } -void LLCurl::Multi::unlock() -{ - if(mMutexp) - { - mMutexp->unlock() ; - } -} - -void LLCurl::Multi::markDead() -{ - { - LLMutexLock lock(mDeletionMutexp) ; - - if(mCurlMultiHandle != NULL) - { - mDead = TRUE ; - LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_URGENT) ; - - return; - } - } - - //not valid, delete it. - delete this; -} - -void LLCurl::Multi::setState(LLCurl::Multi::ePerformState state) -{ - lock() ; - mState = state ; - unlock() ; - - if(mState == STATE_READY) - { - LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_NORMAL) ; - } -} - -LLCurl::Multi::ePerformState LLCurl::Multi::getState() -{ - return mState; -} - -bool LLCurl::Multi::isCompleted() -{ - return STATE_COMPLETED == getState() ; -} - -bool LLCurl::Multi::waitToComplete() -{ - if(!isValid()) - { - return true ; - } - - if(!mMutexp) //not threaded - { - doPerform() ; - return true ; - } - - bool completed = (STATE_COMPLETED == mState) ; - if(!completed) - { - LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_HIGH) ; - } - - return completed; -} - CURLMsg* LLCurl::Multi::info_read(S32* msgs_in_queue) { - LLMutexLock lock(mMutexp) ; - CURLMsg* curlmsg = curl_multi_info_read(mCurlMultiHandle, msgs_in_queue); return curlmsg; } -//return true if dead -bool LLCurl::Multi::doPerform() +void LLCurl::Multi::perform() { - LLMutexLock lock(mDeletionMutexp) ; - - bool dead = mDead ; - - if(mDead) + if (mThreaded) { - setState(STATE_COMPLETED); - mQueued = 0 ; - } - else if(getState() != STATE_COMPLETED) - { - setState(STATE_PERFORMING); - - S32 q = 0; - for (S32 call_count = 0; - call_count < MULTI_PERFORM_CALL_REPEAT; - call_count++) + mSignal->lock(); + if (mPerformState == PERFORM_STATE_READY) { - LLMutexLock lock(mMutexp) ; - - //WARNING: curl_multi_perform will block for many hundreds of milliseconds - // NEVER call this from the main thread, and NEVER allow the main thread to - // wait on a mutex held by this thread while curl_multi_perform is executing - CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q); - if (CURLM_CALL_MULTI_PERFORM != code || q == 0) - { - check_curl_multi_code(code); - - break; - } + mSignal->signal(); } - - mQueued = q; - setState(STATE_COMPLETED) ; - mIdleTimer.reset() ; + mSignal->unlock(); } - else if(!mValid && mIdleTimer.getElapsedTimeF32() > mIdleTimeOut) //idle for too long, remove it. + else { - dead = true ; - } - else if(mValid && mIdleTimer.getElapsedTimeF32() > mIdleTimeOut - 1.f) //idle for too long, mark it invalid. - { - mValid = FALSE ; - } + doPerform(); + } +} - return dead ; +void LLCurl::Multi::run() +{ + llassert(mThreaded); + + mSignal->lock(); + while (!mQuitting) + { + mSignal->wait(); + mPerformState = PERFORM_STATE_PERFORMING; + if (!mQuitting) + { + LLMutexLock lock(LLCurl::Easy::sMultiMutex); + doPerform(); + } + } + mSignal->unlock(); +} + +void LLCurl::Multi::doPerform() +{ + S32 q = 0; + if (mThreaded) + mSignal->unlock(); + for (S32 call_count = 0; + call_count < MULTI_PERFORM_CALL_REPEAT; + call_count += 1) + { + CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q); + if (CURLM_CALL_MULTI_PERFORM != code || q == 0) + { + check_curl_multi_code(code); + break; + } + + } + if (mThreaded) + mSignal->lock(); + mQueued = q; + mPerformState = PERFORM_STATE_COMPLETED; } S32 LLCurl::Multi::process() { - if(!isValid()) - { - return 0 ; - } + perform(); - waitToComplete() ; - - if (getState() != STATE_COMPLETED) + if (mPerformState != PERFORM_STATE_COMPLETED) { return 0; } @@ -805,26 +673,17 @@ S32 LLCurl::Multi::process() if (msg->msg == CURLMSG_DONE) { U32 response = 0; - Easy* easy = NULL ; - - { - LLMutexLock lock(mEasyMutexp) ; - easy_active_map_t::iterator iter = mEasyActiveMap.find(msg->easy_handle); - if (iter != mEasyActiveMap.end()) - { - easy = iter->second; - } - } - - if(easy) + easy_active_map_t::iterator iter = mEasyActiveMap.find(msg->easy_handle); + if (iter != mEasyActiveMap.end()) { + Easy* easy = iter->second; response = easy->report(msg->data.result); removeEasy(easy); } else { response = 499; - //*TODO: change to llwarns + // *TODO: change to llwarns llerrs << "cleaned up curl request completed!" << llendl; } if (response >= 400) @@ -835,28 +694,25 @@ S32 LLCurl::Multi::process() } } - setState(STATE_READY); - + mPerformState = PERFORM_STATE_READY; return processed; } LLCurl::Easy* LLCurl::Multi::allocEasy() { - Easy* easy = 0; + Easy* easy = 0; if (mEasyFreeList.empty()) - { + { easy = Easy::getEasy(); } else { - LLMutexLock lock(mEasyMutexp) ; easy = *(mEasyFreeList.begin()); mEasyFreeList.erase(easy); } if (easy) { - LLMutexLock lock(mEasyMutexp) ; mEasyActiveList.insert(easy); mEasyActiveMap[easy->getCurlHandle()] = easy; } @@ -865,7 +721,6 @@ LLCurl::Easy* LLCurl::Multi::allocEasy() bool LLCurl::Multi::addEasy(Easy* easy) { - LLMutexLock lock(mMutexp) ; CURLMcode mcode = curl_multi_add_handle(mCurlMultiHandle, easy->getCurlHandle()); check_curl_multi_code(mcode); //if (mcode != CURLM_OK) @@ -878,153 +733,25 @@ bool LLCurl::Multi::addEasy(Easy* easy) void LLCurl::Multi::easyFree(Easy* easy) { - if(mEasyMutexp) - { - mEasyMutexp->lock() ; - } - mEasyActiveList.erase(easy); mEasyActiveMap.erase(easy->getCurlHandle()); - if (mEasyFreeList.size() < EASY_HANDLE_POOL_SIZE) - { - mEasyFreeList.insert(easy); - - if(mEasyMutexp) - { - mEasyMutexp->unlock() ; - } - + { easy->resetState(); + mEasyFreeList.insert(easy); } else { - if(mEasyMutexp) - { - mEasyMutexp->unlock() ; - } delete easy; } } void LLCurl::Multi::removeEasy(Easy* easy) { - { - LLMutexLock lock(mMutexp) ; - check_curl_multi_code(curl_multi_remove_handle(mCurlMultiHandle, easy->getCurlHandle())); - } + check_curl_multi_code(curl_multi_remove_handle(mCurlMultiHandle, easy->getCurlHandle())); easyFree(easy); } -//------------------------------------------------------------ -//LLCurlThread -LLCurlThread::CurlRequest::CurlRequest(handle_t handle, LLCurl::Multi* multi, LLCurlThread* curl_thread) : - LLQueuedThread::QueuedRequest(handle, LLQueuedThread::PRIORITY_NORMAL, FLAG_AUTO_COMPLETE), - mMulti(multi), - mCurlThread(curl_thread) -{ -} - -LLCurlThread::CurlRequest::~CurlRequest() -{ - if(mMulti) - { - mCurlThread->deleteMulti(mMulti) ; - mMulti = NULL ; - } -} - -bool LLCurlThread::CurlRequest::processRequest() -{ - bool completed = true ; - if(mMulti) - { - completed = mCurlThread->doMultiPerform(mMulti) ; - - if(!completed) - { - setPriority(LLQueuedThread::PRIORITY_LOW) ; - } - } - - return completed ; -} - -void LLCurlThread::CurlRequest::finishRequest(bool completed) -{ - if(mMulti->isDead()) - { - mCurlThread->deleteMulti(mMulti) ; - } - else - { - mCurlThread->cleanupMulti(mMulti) ; //being idle too long, remove the request. - } - - mMulti = NULL ; -} - -LLCurlThread::LLCurlThread(bool threaded) : - LLQueuedThread("curlthread", threaded) -{ -} - -//virtual -LLCurlThread::~LLCurlThread() -{ -} - -S32 LLCurlThread::update(F32 max_time_ms) -{ - return LLQueuedThread::update(max_time_ms); -} - -void LLCurlThread::addMulti(LLCurl::Multi* multi) -{ - multi->mHandle = generateHandle() ; - - CurlRequest* req = new CurlRequest(multi->mHandle, multi, this) ; - - if (!addRequest(req)) - { - llwarns << "curl request added when the thread is quitted" << llendl; - } -} - -void LLCurlThread::killMulti(LLCurl::Multi* multi) -{ - if(!multi) - { - return ; - } - - multi->markDead() ; -} - -//private -bool LLCurlThread::doMultiPerform(LLCurl::Multi* multi) -{ - return multi->doPerform() ; -} - -//private -void LLCurlThread::deleteMulti(LLCurl::Multi* multi) -{ - delete multi ; -} - -//private -void LLCurlThread::cleanupMulti(LLCurl::Multi* multi) -{ - multi->cleanup() ; - if(multi->isDead()) //check if marked dead during cleaning up. - { - deleteMulti(multi) ; - } -} - -//------------------------------------------------------------ - //static std::string LLCurl::strerror(CURLcode errorcode) { @@ -1039,30 +766,45 @@ LLCurlRequest::LLCurlRequest() : mActiveMulti(NULL), mActiveRequestCount(0) { + mThreadID = LLThread::currentID(); mProcessing = FALSE; } LLCurlRequest::~LLCurlRequest() { + llassert_always(mThreadID == LLThread::currentID()); + //stop all Multi handle background threads for (curlmulti_set_t::iterator iter = mMultiSet.begin(); iter != mMultiSet.end(); ++iter) { - LLCurl::getCurlThread()->killMulti(*iter) ; + LLCurl::Multi* multi = *iter; + if (multi->mThreaded) + multi->mSignal->lock(); + multi->mQuitting = true; + if (multi->mThreaded) + { + while (!multi->isStopped()) + { + multi->mSignal->signal(); + multi->mSignal->unlock(); + apr_sleep(1000); + multi->mSignal->lock(); + } + } + if (multi->mThreaded) + multi->mSignal->unlock(); } - mMultiSet.clear() ; + for_each(mMultiSet.begin(), mMultiSet.end(), DeletePointer()); } void LLCurlRequest::addMulti() { + llassert_always(mThreadID == LLThread::currentID()); LLCurl::Multi* multi = new LLCurl::Multi(); - if(!multi->isValid()) + if (multi->mThreaded) { - LLCurl::getCurlThread()->killMulti(multi) ; - mActiveMulti = NULL ; - mActiveRequestCount = 0 ; - return; + multi->start(); } - mMultiSet.insert(multi); mActiveMulti = multi; mActiveRequestCount = 0; @@ -1076,12 +818,7 @@ LLCurl::Easy* LLCurlRequest::allocEasy() { addMulti(); } - if(!mActiveMulti) - { - return NULL ; - } - - //llassert_always(mActiveMulti); + llassert_always(mActiveMulti); ++mActiveRequestCount; LLCurl::Easy* easy = mActiveMulti->allocEasy(); return easy; @@ -1183,6 +920,7 @@ bool LLCurlRequest::post(const std::string& url, // Note: call once per frame S32 LLCurlRequest::process() { + llassert_always(mThreadID == LLThread::currentID()); S32 res = 0; mProcessing = TRUE; @@ -1191,25 +929,28 @@ S32 LLCurlRequest::process() { curlmulti_set_t::iterator curiter = iter++; LLCurl::Multi* multi = *curiter; - - if(!multi->isValid()) - { - if(multi == mActiveMulti) - { - mActiveMulti = NULL ; - mActiveRequestCount = 0 ; - } - mMultiSet.erase(curiter) ; - LLCurl::getCurlThread()->killMulti(multi) ; - continue ; - } - S32 tres = multi->process(); res += tres; if (multi != mActiveMulti && tres == 0 && multi->mQueued == 0) { mMultiSet.erase(curiter); - LLCurl::getCurlThread()->killMulti(multi); + if (multi->mThreaded) + multi->mSignal->lock(); + multi->mQuitting = true; + if (multi->mThreaded) + { + while (!multi->isStopped()) + { + multi->mSignal->signal(); + multi->mSignal->unlock(); + apr_sleep(1000); + multi->mSignal->unlock(); + } + } + if (multi->mThreaded) + multi->mSignal->unlock(); + + delete multi; } } mProcessing = FALSE; @@ -1218,27 +959,15 @@ S32 LLCurlRequest::process() S32 LLCurlRequest::getQueued() { + llassert_always(mThreadID == LLThread::currentID()); S32 queued = 0; for (curlmulti_set_t::iterator iter = mMultiSet.begin(); iter != mMultiSet.end(); ) { curlmulti_set_t::iterator curiter = iter++; LLCurl::Multi* multi = *curiter; - - if(!multi->isValid()) - { - if(multi == mActiveMulti) - { - mActiveMulti = NULL ; - mActiveRequestCount = 0 ; - } - LLCurl::getCurlThread()->killMulti(multi); - mMultiSet.erase(curiter) ; - continue ; - } - queued += multi->mQueued; - if (multi->getState() != LLCurl::Multi::STATE_READY) + if (multi->mPerformState != LLCurl::Multi::PERFORM_STATE_READY) { ++queued; } @@ -1255,34 +984,41 @@ LLCurlEasyRequest::LLCurlEasyRequest() mResultReturned(false) { mMulti = new LLCurl::Multi(); - - if(mMulti->isValid()) + if (mMulti->mThreaded) { + mMulti->start(); + } mEasy = mMulti->allocEasy(); if (mEasy) { mEasy->setErrorBuffer(); mEasy->setCA(); - // Set proxy settings if configured to do so. - LLProxy::getInstance()->applyProxySettings(mEasy); - } -} - else - { - LLCurl::getCurlThread()->killMulti(mMulti) ; - mEasy = NULL ; - mMulti = NULL ; } } LLCurlEasyRequest::~LLCurlEasyRequest() { - LLCurl::getCurlThread()->killMulti(mMulti) ; + if (mMulti->mThreaded) + mMulti->mSignal->lock(); + mMulti->mQuitting = true; + if (mMulti->mThreaded) + { + while (!mMulti->isStopped()) + { + mMulti->mSignal->signal(); + mMulti->mSignal->unlock(); + apr_sleep(1000); + mMulti->mSignal->lock(); + } + } + if (mMulti->mThreaded) + mMulti->mSignal->unlock(); + delete mMulti; } void LLCurlEasyRequest::setopt(CURLoption option, S32 value) { - if (isValid() && mEasy) + if (mEasy) { mEasy->setopt(option, value); } @@ -1290,7 +1026,7 @@ void LLCurlEasyRequest::setopt(CURLoption option, S32 value) void LLCurlEasyRequest::setoptString(CURLoption option, const std::string& value) { - if (isValid() && mEasy) + if (mEasy) { mEasy->setoptString(option, value); } @@ -1298,7 +1034,7 @@ void LLCurlEasyRequest::setoptString(CURLoption option, const std::string& value void LLCurlEasyRequest::setPost(char* postdata, S32 size) { - if (isValid() && mEasy) + if (mEasy) { mEasy->setopt(CURLOPT_POST, 1); mEasy->setopt(CURLOPT_POSTFIELDS, postdata); @@ -1308,7 +1044,7 @@ void LLCurlEasyRequest::setPost(char* postdata, S32 size) void LLCurlEasyRequest::setHeaderCallback(curl_header_callback callback, void* userdata) { - if (isValid() && mEasy) + if (mEasy) { mEasy->setopt(CURLOPT_HEADERFUNCTION, (void*)callback); mEasy->setopt(CURLOPT_HEADERDATA, userdata); // aka CURLOPT_WRITEHEADER @@ -1317,7 +1053,7 @@ void LLCurlEasyRequest::setHeaderCallback(curl_header_callback callback, void* u void LLCurlEasyRequest::setWriteCallback(curl_write_callback callback, void* userdata) { - if (isValid() && mEasy) + if (mEasy) { mEasy->setopt(CURLOPT_WRITEFUNCTION, (void*)callback); mEasy->setopt(CURLOPT_WRITEDATA, userdata); @@ -1326,7 +1062,7 @@ void LLCurlEasyRequest::setWriteCallback(curl_write_callback callback, void* use void LLCurlEasyRequest::setReadCallback(curl_read_callback callback, void* userdata) { - if (isValid() && mEasy) + if (mEasy) { mEasy->setopt(CURLOPT_READFUNCTION, (void*)callback); mEasy->setopt(CURLOPT_READDATA, userdata); @@ -1335,7 +1071,7 @@ void LLCurlEasyRequest::setReadCallback(curl_read_callback callback, void* userd void LLCurlEasyRequest::setSSLCtxCallback(curl_ssl_ctx_callback callback, void* userdata) { - if (isValid() && mEasy) + if (mEasy) { mEasy->setopt(CURLOPT_SSL_CTX_FUNCTION, (void*)callback); mEasy->setopt(CURLOPT_SSL_CTX_DATA, userdata); @@ -1344,7 +1080,7 @@ void LLCurlEasyRequest::setSSLCtxCallback(curl_ssl_ctx_callback callback, void* void LLCurlEasyRequest::slist_append(const char* str) { - if (isValid() && mEasy) + if (mEasy) { mEasy->slist_append(str); } @@ -1355,7 +1091,7 @@ void LLCurlEasyRequest::sendRequest(const std::string& url) llassert_always(!mRequestSent); mRequestSent = true; lldebugs << url << llendl; - if (isValid() && mEasy) + if (mEasy) { mEasy->setHeaders(); mEasy->setoptString(CURLOPT_URL, url); @@ -1367,24 +1103,25 @@ void LLCurlEasyRequest::requestComplete() { llassert_always(mRequestSent); mRequestSent = false; - if (isValid() && mEasy) + if (mEasy) { mMulti->removeEasy(mEasy); } } +void LLCurlEasyRequest::perform() +{ + mMulti->perform(); +} + // Usage: Call getRestult until it returns false (no more messages) bool LLCurlEasyRequest::getResult(CURLcode* result, LLCurl::TransferInfo* info) { - if(!isValid()) - { - return false ; - } - if (!mMulti->isCompleted()) + if (mMulti->mPerformState != LLCurl::Multi::PERFORM_STATE_COMPLETED) { //we're busy, try again later return false; } - mMulti->setState(LLCurl::Multi::STATE_READY) ; + mMulti->mPerformState = LLCurl::Multi::PERFORM_STATE_READY; if (!mEasy) { @@ -1444,7 +1181,7 @@ CURLMsg* LLCurlEasyRequest::info_read(S32* q, LLCurl::TransferInfo* info) std::string LLCurlEasyRequest::getErrorString() { - return isValid() && mEasy ? std::string(mEasy->getErrorBuffer()) : std::string(); + return mEasy ? std::string(mEasy->getErrorBuffer()) : std::string(); } //////////////////////////////////////////////////////////////////////////// @@ -1470,11 +1207,10 @@ unsigned long LLCurl::ssl_thread_id(void) } #endif -void LLCurl::initClass(F32 curl_reuest_timeout, S32 max_number_handles, bool multi_threaded) +void LLCurl::initClass(bool multi_threaded) { - sCurlRequestTimeOut = curl_reuest_timeout ; //seconds - sMaxHandles = max_number_handles ; //max number of handles, (multi handles and easy handles combined). - + sMainThreadID = LLThread::currentID(); + sMultiThreaded = multi_threaded; // Do not change this "unless you are familiar with and mean to control // internal operations of libcurl" // - http://curl.haxx.se/libcurl/c/curl_global_init.html @@ -1482,126 +1218,41 @@ void LLCurl::initClass(F32 curl_reuest_timeout, S32 max_number_handles, bool mul check_curl_code(code); + Easy::sHandleMutex = new LLMutex; + Easy::sMultiMutex = new LLMutex; + #if SAFE_SSL S32 mutex_count = CRYPTO_num_locks(); for (S32 i=0; iupdate(1)) //finish all tasks - { - break ; - } - } - sCurlThread->shutdown() ; - delete sCurlThread ; - sCurlThread = NULL ; - #if SAFE_SSL CRYPTO_set_locking_callback(NULL); for_each(sSSLMutex.begin(), sSSLMutex.end(), DeletePointer()); #endif + delete Easy::sHandleMutex; + Easy::sHandleMutex = NULL; + delete Easy::sMultiMutex; + Easy::sMultiMutex = NULL; + for (std::set::iterator iter = Easy::sFreeHandles.begin(); iter != Easy::sFreeHandles.end(); ++iter) { CURL* curl = *iter; - LLCurl::deleteEasyHandle(curl); + curl_easy_cleanup(curl); } Easy::sFreeHandles.clear(); - delete Easy::sHandleMutexp ; - Easy::sHandleMutexp = NULL ; - - delete sHandleMutexp ; - sHandleMutexp = NULL ; - - // removed as per https://jira.secondlife.com/browse/SH-3115 - //llassert(Easy::sActiveHandles.empty()); -} - -//static -CURLM* LLCurl::newMultiHandle() -{ - LLMutexLock lock(sHandleMutexp) ; - - if(sTotalHandles + 1 > sMaxHandles) - { - llwarns << "no more handles available." << llendl ; - return NULL ; //failed - } - sTotalHandles++; - - CURLM* ret = curl_multi_init() ; - if(!ret) - { - llwarns << "curl_multi_init failed." << llendl ; - } - - return ret ; -} - -//static -CURLMcode LLCurl::deleteMultiHandle(CURLM* handle) -{ - if(handle) - { - LLMutexLock lock(sHandleMutexp) ; - sTotalHandles-- ; - return curl_multi_cleanup(handle) ; - } - return CURLM_OK ; -} - -//static -CURL* LLCurl::newEasyHandle() -{ - LLMutexLock lock(sHandleMutexp) ; - - if(sTotalHandles + 1 > sMaxHandles) - { - llwarns << "no more handles available." << llendl ; - return NULL ; //failed - } - sTotalHandles++; - - CURL* ret = curl_easy_init() ; - if(!ret) - { - llwarns << "curl_easy_init failed." << llendl ; - } - - return ret ; -} - -//static -void LLCurl::deleteEasyHandle(CURL* handle) -{ - if(handle) - { - LLMutexLock lock(sHandleMutexp) ; - curl_easy_cleanup(handle) ; - sTotalHandles-- ; - } + llassert(Easy::sActiveHandles.empty()); } const unsigned int LLCurl::MAX_REDIRECTS = 5; diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h index 42ab93e58..76ef595e9 100644 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -42,11 +42,8 @@ #include "lliopipe.h" #include "llsd.h" #include "llthread.h" -#include "llqueuedthread.h" -#include "llframetimer.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); @@ -59,6 +56,8 @@ public: class Easy; class Multi; + static bool sMultiThreaded; + struct TransferInfo { TransferInfo() : mSizeDownload(0.0), mTotalTime(0.0), mSpeedDownload(0.0) {} @@ -125,7 +124,6 @@ public: { return false; } - public: /* but not really -- don't touch this */ U32 mReferenceCount; @@ -163,7 +161,7 @@ public: /** * @ brief Initialize LLCurl class */ - static void initClass(F32 curl_reuest_timeout = 120.f, S32 max_number_handles = 256, bool multi_threaded = false); + static void initClass(bool multi_threaded = false); /** * @ brief Cleanup LLCurl class @@ -182,25 +180,10 @@ 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 ;} - - static CURLM* newMultiHandle() ; - static CURLMcode deleteMultiHandle(CURLM* handle) ; - static CURL* newEasyHandle() ; - static void deleteEasyHandle(CURL* handle) ; - private: static std::string sCAPath; static std::string sCAFile; static const unsigned int MAX_REDIRECTS; - static LLCurlThread* sCurlThread; - - static LLMutex* sHandleMutexp ; - static S32 sTotalHandles ; - static S32 sMaxHandles; -public: - static bool sNotQuitting; - static F32 sCurlRequestTimeOut; }; class LLCurl::Easy @@ -209,7 +192,7 @@ class LLCurl::Easy private: Easy(); - + public: static Easy* getEasy(); ~Easy(); @@ -218,41 +201,41 @@ public: 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 + // Copies the string so that it is gauranteed 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& headers, LLCurl::ResponderPtr, S32 time_out = 0, bool post = false); - + void prepRequest(const std::string& url, const std::vector& headers, 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: +private: friend class LLCurl; friend class LLCurl::Multi; CURL* mCurlEasyHandle; struct curl_slist* mHeaders; - + std::stringstream mRequest; LLChannelDescriptors mChannels; LLIOPipe::buffer_ptr_t mOutput; @@ -262,125 +245,70 @@ private: // Note: char*'s not strings since we pass pointers to curl std::vector mStrings; - - LLCurl::ResponderPtr mResponder; + + ResponderPtr mResponder; static std::set sFreeHandles; static std::set sActiveHandles; - static LLMutex* sHandleMutexp ; + static LLMutex* sHandleMutex; + static LLMutex* sMultiMutex; }; -class LLCurl::Multi +class LLCurl::Multi : public LLThread { LOG_CLASS(Multi); - - friend class LLCurlThread ; - -private: - ~Multi(); - - void markDead() ; - bool doPerform(); - public: typedef enum { - STATE_READY=0, - STATE_PERFORMING=1, - STATE_COMPLETED=2 + PERFORM_STATE_READY=0, + PERFORM_STATE_PERFORMING=1, + PERFORM_STATE_COMPLETED=2 } ePerformState; - Multi(F32 idle_time_out = 0.f); + Multi(); + ~Multi(); - LLCurl::Easy* allocEasy(); - bool addEasy(LLCurl::Easy* easy); - void removeEasy(LLCurl::Easy* easy); + Easy* allocEasy(); + bool addEasy(Easy* easy); - void lock() ; - void unlock() ; - - void setState(ePerformState state) ; - ePerformState getState() ; - - bool isCompleted() ; - bool isValid() {return mCurlMultiHandle != NULL && mValid;} - bool isDead() {return mDead;} - - bool waitToComplete() ; + void removeEasy(Easy* easy); S32 process(); + void perform(); + void doPerform(); + virtual void run(); + CURLMsg* info_read(S32* msgs_in_queue); S32 mQueued; S32 mErrorCount; + S32 mPerformState; + + LLCondition* mSignal; + bool mQuitting; + bool mThreaded; + private: - void easyFree(LLCurl::Easy*); - void cleanup(bool deleted = false) ; + void easyFree(Easy*); CURLM* mCurlMultiHandle; - typedef std::set easy_active_list_t; + typedef std::set easy_active_list_t; easy_active_list_t mEasyActiveList; - typedef std::map easy_active_map_t; + typedef std::map easy_active_map_t; easy_active_map_t mEasyActiveMap; - typedef std::set easy_free_list_t; + typedef std::set easy_free_list_t; easy_free_list_t mEasyFreeList; - - LLQueuedThread::handle_t mHandle ; - ePerformState mState; - - BOOL mDead ; - BOOL mValid ; - LLMutex* mMutexp ; - LLMutex* mDeletionMutexp ; - LLMutex* mEasyMutexp ; - LLFrameTimer mIdleTimer ; - F32 mIdleTimeOut; }; -class LLCurlThread : public LLQueuedThread +namespace boost { -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(F32 max_time_ms); - - void addMulti(LLCurl::Multi* multi) ; - void killMulti(LLCurl::Multi* multi) ; - -private: - bool doMultiPerform(LLCurl::Multi* multi) ; - void deleteMulti(LLCurl::Multi* multi) ; - void cleanupMulti(LLCurl::Multi* multi) ; -} ; - - -void intrusive_ptr_add_ref(LLCurl::Responder* p); -void intrusive_ptr_release(LLCurl::Responder* p); + void intrusive_ptr_add_ref(LLCurl::Responder* p); + void intrusive_ptr_release(LLCurl::Responder* p); +}; class LLCurlRequest @@ -410,6 +338,7 @@ private: LLCurl::Multi* mActiveMulti; S32 mActiveRequestCount; BOOL mProcessing; + U32 mThreadID; // debug }; class LLCurlEasyRequest @@ -427,11 +356,9 @@ public: void slist_append(const char* str); void sendRequest(const std::string& url); void requestComplete(); + void perform(); bool getResult(CURLcode* result, LLCurl::TransferInfo* info = NULL); std::string getErrorString(); - bool isCompleted() {return mMulti->isCompleted() ;} - bool wait() { return mMulti->waitToComplete(); } - bool isValid() {return mMulti && mMulti->isValid(); } LLCurl::Easy* getEasy() const { return mEasy; } diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp index 75ccc3818..38b02c52c 100644 --- a/indra/llmessage/llhttpclient.cpp +++ b/indra/llmessage/llhttpclient.cpp @@ -25,7 +25,7 @@ */ #include "linden_common.h" -#include + #include "llhttpclient.h" #include "llassetstorage.h" @@ -40,10 +40,8 @@ #include "message.h" #include - const F32 HTTP_REQUEST_EXPIRY_SECS = 60.0f; LLURLRequest::SSLCertVerifyCallback LLHTTPClient::mCertVerifyCallback = NULL; - //////////////////////////////////////////////////////////////////////////// // Responder class moved to LLCurl @@ -160,7 +158,7 @@ namespace fstream.seekg(0, std::ios::end); U32 fileSize = (U32)fstream.tellg(); fstream.seekg(0, std::ios::beg); - std::vector fileBuffer(fileSize); + std::vector fileBuffer(fileSize); //Mem leak fix'd fstream.read(&fileBuffer[0], fileSize); ostream.write(&fileBuffer[0], fileSize); fstream.close(); @@ -189,11 +187,9 @@ namespace LLVFile vfile(gVFS, mUUID, mAssetType, LLVFile::READ); S32 fileSize = vfile.getSize(); - U8* fileBuffer; - fileBuffer = new U8 [fileSize]; - vfile.read(fileBuffer, fileSize); - ostream.write((char*)fileBuffer, fileSize); - delete [] fileBuffer; + std::vector fileBuffer(fileSize); + vfile.read(&fileBuffer[0], fileSize); + ostream.write((char*)&fileBuffer[0], fileSize); eos = true; return STATUS_DONE; } @@ -202,7 +198,6 @@ namespace LLAssetType::EType mAssetType; }; - LLPumpIO* theClientPump = NULL; } @@ -217,8 +212,7 @@ static void request( Injector* body_injector, LLCurl::ResponderPtr responder, const F32 timeout = HTTP_REQUEST_EXPIRY_SECS, - const LLSD& headers = LLSD() - ) + const LLSD& headers = LLSD()) { if (!LLHTTPClient::hasPump()) { @@ -228,26 +222,12 @@ static void request( LLPumpIO::chain_t chain; LLURLRequest* req = new LLURLRequest(method, url); - if(!req->isValid())//failed - { - delete req ; - return ; - } req->setSSLVerifyCallback(LLHTTPClient::getCertVerifyCallback(), (void *)req); - - lldebugs << LLURLRequest::actionAsVerb(method) << " " << url << " " - << headers << llendl; - - // Insert custom headers if the caller sent any - if (headers.isMap()) - { - if (headers.has("Cookie")) - { - req->allowCookies(); - } - + // Insert custom headers is the caller sent any + if (headers.isMap()) + { LLSD::map_const_iterator iter = headers.beginMap(); LLSD::map_const_iterator end = headers.endMap(); @@ -429,16 +409,11 @@ static LLSD blocking_request( { lldebugs << "blockingRequest of " << url << llendl; char curl_error_buffer[CURL_ERROR_SIZE] = "\0"; - CURL* curlp = LLCurl::newEasyHandle(); - llassert_always(curlp != NULL) ; - + CURL* curlp = curl_easy_init(); LLHTTPBuffer http_buffer; std::string body_str; // other request method checks root cert first, we skip? - - // Apply configured proxy settings - LLProxy::getInstance()->applyProxySettings(curlp); // * Set curl handle options curl_easy_setopt(curlp, CURLOPT_NOSIGNAL, 1); // don't use SIGALRM for timeouts @@ -447,7 +422,7 @@ static LLSD blocking_request( curl_easy_setopt(curlp, CURLOPT_WRITEDATA, &http_buffer); curl_easy_setopt(curlp, CURLOPT_URL, url.c_str()); curl_easy_setopt(curlp, CURLOPT_ERRORBUFFER, curl_error_buffer); - + // * Setup headers (don't forget to free them after the call!) curl_slist* headers_list = NULL; if (headers.isMap()) @@ -525,7 +500,7 @@ static LLSD blocking_request( } // * Cleanup - LLCurl::deleteEasyHandle(curlp); + curl_easy_cleanup(curlp); return response; } @@ -625,8 +600,7 @@ bool LLHTTPClient::hasPump() return theClientPump != NULL; } -//static -LLPumpIO& LLHTTPClient::getPump() +LLPumpIO &LLHTTPClient::getPump() { return *theClientPump; } diff --git a/indra/llmessage/llhttpclient.h b/indra/llmessage/llhttpclient.h index dda7d550f..2732b51b7 100644 --- a/indra/llmessage/llhttpclient.h +++ b/indra/llmessage/llhttpclient.h @@ -34,10 +34,11 @@ #include #include -#include "llurlrequest.h" + #include "llassettype.h" #include "llcurl.h" #include "lliopipe.h" +#include "llurlrequest.h" extern const F32 HTTP_REQUEST_EXPIRY_SECS; @@ -55,7 +56,6 @@ public: typedef LLCurl::Responder Responder; typedef LLCurl::ResponderPtr ResponderPtr; - /** @name non-blocking API */ //@{ static void head( @@ -155,7 +155,7 @@ public: ///< Hippo special static void setCertVerifyCallback(LLURLRequest::SSLCertVerifyCallback callback); - static LLURLRequest::SSLCertVerifyCallback getCertVerifyCallback() { return mCertVerifyCallback; } + static LLURLRequest::SSLCertVerifyCallback getCertVerifyCallback() { return mCertVerifyCallback; } protected: static LLURLRequest::SSLCertVerifyCallback mCertVerifyCallback; diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp index f5e08f393..f351873df 100644 --- a/indra/llmessage/llurlrequest.cpp +++ b/indra/llmessage/llurlrequest.cpp @@ -32,17 +32,17 @@ #include #include #include + #include "llcurl.h" -#include "llfasttimer.h" #include "llioutil.h" #include "llmemtype.h" -#include "llproxy.h" #include "llpumpio.h" #include "llsd.h" #include "llstring.h" #include "apr_env.h" #include "llapr.h" #include "llscopedvolatileaprpool.h" +#include "llfasttimer.h" static const U32 HTTP_STATUS_PIPE_ERROR = 499; /** @@ -66,7 +66,7 @@ public: ~LLURLRequestDetail(); std::string mURL; LLCurlEasyRequest* mCurlRequest; - LLIOPipe::buffer_ptr_t mResponseBuffer; + LLBufferArray* mResponseBuffer; LLChannelDescriptors mChannels; U8* mLastRead; U32 mBodyLimit; @@ -77,26 +77,21 @@ public: LLURLRequestDetail::LLURLRequestDetail() : mCurlRequest(NULL), + mResponseBuffer(NULL), mLastRead(NULL), mBodyLimit(0), mByteAccumulator(0), - mIsBodyLimitSet(false), - mSSLVerifyCallback(NULL) + mIsBodyLimitSet(false) { LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST); mCurlRequest = new LLCurlEasyRequest(); - - if(!mCurlRequest->isValid()) //failed. - { - delete mCurlRequest ; - mCurlRequest = NULL ; - } } LLURLRequestDetail::~LLURLRequestDetail() { LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST); delete mCurlRequest; + mResponseBuffer = NULL; mLastRead = NULL; } @@ -105,7 +100,7 @@ void LLURLRequest::setSSLVerifyCallback(SSLCertVerifyCallback callback, void *pa mDetail->mSSLVerifyCallback = callback; mDetail->mCurlRequest->setSSLCtxCallback(LLURLRequest::_sslCtxCallback, (void *)this); mDetail->mCurlRequest->setopt(CURLOPT_SSL_VERIFYPEER, true); - mDetail->mCurlRequest->setopt(CURLOPT_SSL_VERIFYHOST, 2); + mDetail->mCurlRequest->setopt(CURLOPT_SSL_VERIFYHOST, 2); } @@ -114,7 +109,7 @@ void LLURLRequest::setSSLVerifyCallback(SSLCertVerifyCallback callback, void *pa // used to configure the context for custom cert validation CURLcode LLURLRequest::_sslCtxCallback(CURL * curl, void *sslctx, void *param) -{ +{ LLURLRequest *req = (LLURLRequest *)param; if(req == NULL || req->mDetail->mSSLVerifyCallback == NULL) { @@ -128,7 +123,6 @@ CURLcode LLURLRequest::_sslCtxCallback(CURL * curl, void *sslctx, void *param) SSL_CTX_set_cert_verify_callback(ctx, req->mDetail->mSSLVerifyCallback, (void *)req); // the calls are void return CURLE_OK; - } /** @@ -189,7 +183,6 @@ std::string LLURLRequest::getURL() const { return mDetail->mURL; } - void LLURLRequest::addHeader(const char* header) { LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST); @@ -240,9 +233,9 @@ void LLURLRequest::useProxy(bool use_proxy) } } - lldebugs << "use_proxy = " << (use_proxy?'Y':'N') << ", env_proxy = \"" << env_proxy << "\"" << llendl; + LL_DEBUGS("Proxy") << "use_proxy = " << (use_proxy?'Y':'N') << ", env_proxy = " << (!env_proxy.empty() ? env_proxy : "(null)") << LL_ENDL; - if (use_proxy) + if (use_proxy && !env_proxy.empty()) { mDetail->mCurlRequest->setoptString(CURLOPT_PROXY, env_proxy); } @@ -262,24 +255,12 @@ void LLURLRequest::allowCookies() mDetail->mCurlRequest->setoptString(CURLOPT_COOKIEFILE, ""); } -//virtual -bool LLURLRequest::isValid() -{ - return mDetail->mCurlRequest && mDetail->mCurlRequest->isValid(); -} - // virtual LLIOPipe::EStatus LLURLRequest::handleError( LLIOPipe::EStatus status, LLPumpIO* pump) { LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST); - - if(!isValid()) - { - return STATUS_EXPIRED ; - } - if(mCompletionCallback && pump) { LLURLRequestComplete* complete = NULL; @@ -309,7 +290,8 @@ LLIOPipe::EStatus LLURLRequest::process_impl( LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST); //llinfos << "LLURLRequest::process_impl()" << llendl; if (!buffer) return STATUS_ERROR; - + if (!mDetail) return STATUS_ERROR; //Seems to happen on occasion. Need to hunt down why. + // we're still waiting or prcessing, check how many // bytes we have accumulated. const S32 MIN_ACCUMULATION = 100000; @@ -348,7 +330,7 @@ LLIOPipe::EStatus LLURLRequest::process_impl( // *FIX: bit of a hack, but it should work. The configure and // callback method expect this information to be ready. - mDetail->mResponseBuffer = buffer; + mDetail->mResponseBuffer = buffer.get(); mDetail->mChannels = channels; if(!configure()) { @@ -367,10 +349,7 @@ LLIOPipe::EStatus LLURLRequest::process_impl( static LLFastTimer::DeclareTimer FTM_URL_PERFORM("Perform"); { LLFastTimer t(FTM_URL_PERFORM); - if(!mDetail->mCurlRequest->wait()) - { - return status ; - } + mDetail->mCurlRequest->perform(); } while(1) @@ -465,12 +444,6 @@ void LLURLRequest::initialize() LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST); mState = STATE_INITIALIZED; mDetail = new LLURLRequestDetail; - - if(!isValid()) - { - return ; - } - mDetail->mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1); mDetail->mCurlRequest->setWriteCallback(&downCallback, (void*)this); mDetail->mCurlRequest->setReadCallback(&upCallback, (void*)this); diff --git a/indra/llmessage/llurlrequest.h b/indra/llmessage/llurlrequest.h index 1ba51a5ac..6e16067dc 100644 --- a/indra/llmessage/llurlrequest.h +++ b/indra/llmessage/llurlrequest.h @@ -40,7 +40,6 @@ #include "llerror.h" #include "llcurl.h" - extern const std::string CONTEXT_REQUEST; extern const std::string CONTEXT_DEST_URI_SD_LABEL; extern const std::string CONTEXT_RESPONSE; @@ -145,7 +144,6 @@ public: */ void setSSLVerifyCallback(SSLCertVerifyCallback callback, void * param); - /** * @brief Return at most size bytes of body. * @@ -190,14 +188,11 @@ public: */ void allowCookies(); - /*virtual*/ bool isValid() ; - public: /** * @brief Give this pipe a chance to handle a generated error */ virtual EStatus handleError(EStatus status, LLPumpIO* pump); - protected: /** @@ -223,11 +218,11 @@ protected: ERequestAction mAction; LLURLRequestDetail* mDetail; LLIOPipe::ptr_t mCompletionCallback; - S32 mRequestTransferedBytes; - S32 mResponseTransferedBytes; + S32 mRequestTransferedBytes; + S32 mResponseTransferedBytes; static CURLcode _sslCtxCallback(CURL * curl, void *sslctx, void *param); - + private: /** * @brief Initialize the object. Called during construction. diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index c0bb21085..26b224eda 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -637,9 +637,8 @@ bool LLAppViewer::init() mAlloc.setProfilingEnabled(gSavedSettings.getBOOL("MemProfiling")); // *NOTE:Mani - LLCurl::initClass is not thread safe. // Called before threads are created. - LLCurl::initClass(gSavedSettings.getF32("CurlRequestTimeOut"), - gSavedSettings.getS32("CurlMaximumNumberOfHandles"), - gSavedSettings.getBOOL("CurlUseMultipleThreads")); + LLCurl::initClass(gSavedSettings.getF32("CurlRequestTimeOut")); + LL_INFOS("InitInfo") << "LLCurl initialized." << LL_ENDL ; initThreads(); diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp index af5e977b2..11dc653aa 100644 --- a/indra/newview/llxmlrpctransaction.cpp +++ b/indra/newview/llxmlrpctransaction.cpp @@ -227,16 +227,6 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip) mCurlRequest = new LLCurlEasyRequest(); } - if(!mCurlRequest->isValid()) - { - llwarns << "mCurlRequest is invalid." << llendl ; - - delete mCurlRequest ; - mCurlRequest = NULL ; - return ; - } - - LLProxy::getInstance()->applyProxySettings(mCurlRequest); // mCurlRequest->setopt(CURLOPT_VERBOSE, 1); // usefull for debugging @@ -292,7 +282,7 @@ LLXMLRPCTransaction::Impl::~Impl() bool LLXMLRPCTransaction::Impl::process() { - if(!mCurlRequest || !mCurlRequest->isValid()) + if(!mCurlRequest || !mCurlRequest->getEasy()) { llwarns << "transaction failed." << llendl ; @@ -326,7 +316,7 @@ bool LLXMLRPCTransaction::Impl::process() //const F32 MAX_PROCESSING_TIME = 0.05f; //LLTimer timer; - mCurlRequest->wait(); + mCurlRequest->perform(); /*while (mCurlRequest->perform() > 0) {