diff options
Diffstat (limited to 'indra/llmessage/llcorehttputil.cpp')
| -rw-r--r-- | indra/llmessage/llcorehttputil.cpp | 132 |
1 files changed, 95 insertions, 37 deletions
diff --git a/indra/llmessage/llcorehttputil.cpp b/indra/llmessage/llcorehttputil.cpp index b24e5e4fcc..647064f607 100644 --- a/indra/llmessage/llcorehttputil.cpp +++ b/indra/llmessage/llcorehttputil.cpp @@ -37,6 +37,7 @@ #include "llsdserialize.h" #include "boost/json.hpp" // Boost.Json #include "llfilesystem.h" +#include "workqueue.h" #include "message.h" // for getting the port @@ -295,41 +296,73 @@ void HttpCoroHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRespons } else { - try + constexpr size_t MAX_BODY_SIZE_THRESHOLD = 65536; + bool posted = false; + // Some messsages (ex: AISAPI) can return large bodies. + // If the body is larger than our threshold, post the + // parsing to the general queue to avoid stalling the + // main thread. + if (response->getBodySize() > MAX_BODY_SIZE_THRESHOLD) { - result = this->handleSuccess(response, status); - } - catch (std::bad_alloc&) - { - LLError::LLUserWarningMsg::showOutOfMemory(); - LL_ERRS("CoreHTTP") << "Failed to allocate memory for response handling." << LL_ENDL; - } - } + response->addRef(); - buildStatusEntry(response, status, result); + LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop"); + LL::WorkQueue::ptr_t general_queue = LL::WorkQueue::getInstance("General"); + posted = main_queue->postTo( + general_queue, + [handler = shared_from_this(), response, status]() // Work done on general queue + { + std::pair<LLSD, LLCore::HttpStatus> result; + result.second = status; + try + { + result.first = handler->handleSuccess(response, result.second); + } + catch (std::bad_alloc&) + { + LLError::LLUserWarningMsg::showOutOfMemory(); + LL_ERRS("CoreHTTP") << "Failed to allocate memory for response handling (threaded)." << LL_ENDL; + } + // LLSD is not thread safe! Be carefull with moving the result around. + return result; + }, + [handler = shared_from_this(), response](std::pair<LLSD, LLCore::HttpStatus> result) mutable // Callback to main thread + { + handler->replyPost(response, result.second, result.first); + response->release(); + }); - if (!status) - { - LLSD &httpStatus = result[HttpCoroutineAdapter::HTTP_RESULTS]; + if (posted) + { + // Thread will do the cleanup and notify the pump. Done. + return; + } + else + { + // For whatever reason, failed to post, clean up and + // do the work on the main thread. + response->release(); + } + } - LLCore::BufferArray *body = response->getBody(); - LLCore::BufferArrayStream bas(body); - LLSD::String bodyData; - bodyData.reserve(response->getBodySize()); - bas >> std::noskipws; - bodyData.assign(std::istream_iterator<U8>(bas), std::istream_iterator<U8>()); - httpStatus["error_body"] = LLSD(bodyData); - if (getBoolSetting(HTTP_LOGBODY_KEY)) + if (!posted) { - // commenting out, but keeping since this can be useful for debugging - LL_WARNS("CoreHTTP") << "Returned body=" << std::endl << httpStatus["error_body"].asString() << LL_ENDL; + try + { + result = this->handleSuccess(response, status); + } + catch (std::bad_alloc&) + { + LLError::LLUserWarningMsg::showOutOfMemory(); + LL_ERRS("CoreHTTP") << "Failed to allocate memory for response handling." << LL_ENDL; + } } } - mReplyPump.post(result); + replyPost(response, status, result); } -void HttpCoroHandler::buildStatusEntry(LLCore::HttpResponse *response, LLCore::HttpStatus status, LLSD &result) +void HttpCoroHandler::buildStatusEntry(LLCore::HttpResponse *response, LLCore::HttpStatus status, LLSD &result) const { LLSD httpresults = LLSD::emptyMap(); @@ -357,6 +390,31 @@ void HttpCoroHandler::buildStatusEntry(LLCore::HttpResponse *response, LLCore::H result[HttpCoroutineAdapter::HTTP_RESULTS] = httpresults; } +void HttpCoroHandler::replyPost(LLCore::HttpResponse* response, LLCore::HttpStatus &status, LLSD& result) +{ + buildStatusEntry(response, status, result); + + if (!status) + { + LLSD& httpStatus = result[HttpCoroutineAdapter::HTTP_RESULTS]; + + LLCore::BufferArray* body = response->getBody(); + LLCore::BufferArrayStream bas(body); + LLSD::String bodyData; + bodyData.reserve(response->getBodySize()); + bas >> std::noskipws; + bodyData.assign(std::istream_iterator<U8>(bas), std::istream_iterator<U8>()); + httpStatus["error_body"] = LLSD(bodyData); + if (getBoolSetting(HTTP_LOGBODY_KEY)) + { + // commenting out, but keeping since this can be useful for debugging + LL_WARNS("CoreHTTP") << "Returned body=" << std::endl << httpStatus["error_body"].asString() << LL_ENDL; + } + } + + mReplyPump.post(result); +} + void HttpCoroHandler::writeStatusCodes(LLCore::HttpStatus status, const std::string &url, LLSD &result) { result[HttpCoroutineAdapter::HTTP_RESULTS_SUCCESS] = static_cast<LLSD::Boolean>(status); @@ -389,8 +447,8 @@ public: HttpCoroLLSDHandler(LLEventStream &reply); protected: - virtual LLSD handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status); - virtual LLSD parseBody(LLCore::HttpResponse *response, bool &success); + virtual LLSD handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status) const; + virtual LLSD parseBody(LLCore::HttpResponse *response, bool &success) const; }; //------------------------------------------------------------------------- @@ -400,7 +458,7 @@ HttpCoroLLSDHandler::HttpCoroLLSDHandler(LLEventStream &reply): } -LLSD HttpCoroLLSDHandler::handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status) +LLSD HttpCoroLLSDHandler::handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status) const { LLSD result; @@ -465,7 +523,7 @@ LLSD HttpCoroLLSDHandler::handleSuccess(LLCore::HttpResponse * response, LLCore: return result; } -LLSD HttpCoroLLSDHandler::parseBody(LLCore::HttpResponse *response, bool &success) +LLSD HttpCoroLLSDHandler::parseBody(LLCore::HttpResponse *response, bool &success) const { success = true; if (response->getBodySize() == 0) @@ -496,8 +554,8 @@ class HttpCoroRawHandler : public HttpCoroHandler public: HttpCoroRawHandler(LLEventStream &reply); - virtual LLSD handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status); - virtual LLSD parseBody(LLCore::HttpResponse *response, bool &success); + virtual LLSD handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status) const; + virtual LLSD parseBody(LLCore::HttpResponse *response, bool &success) const; }; //------------------------------------------------------------------------- @@ -506,7 +564,7 @@ HttpCoroRawHandler::HttpCoroRawHandler(LLEventStream &reply): { } -LLSD HttpCoroRawHandler::handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status) +LLSD HttpCoroRawHandler::handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status) const { LLSD result = LLSD::emptyMap(); @@ -552,7 +610,7 @@ LLSD HttpCoroRawHandler::handleSuccess(LLCore::HttpResponse * response, LLCore:: return result; } -LLSD HttpCoroRawHandler::parseBody(LLCore::HttpResponse *response, bool &success) +LLSD HttpCoroRawHandler::parseBody(LLCore::HttpResponse *response, bool &success) const { success = true; return LLSD(); @@ -571,8 +629,8 @@ class HttpCoroJSONHandler : public HttpCoroHandler public: HttpCoroJSONHandler(LLEventStream &reply); - virtual LLSD handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status); - virtual LLSD parseBody(LLCore::HttpResponse *response, bool &success); + virtual LLSD handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status) const; + virtual LLSD parseBody(LLCore::HttpResponse *response, bool &success) const; }; //------------------------------------------------------------------------- @@ -581,7 +639,7 @@ HttpCoroJSONHandler::HttpCoroJSONHandler(LLEventStream &reply) : { } -LLSD HttpCoroJSONHandler::handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status) +LLSD HttpCoroJSONHandler::handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status) const { LLSD result = LLSD::emptyMap(); @@ -607,7 +665,7 @@ LLSD HttpCoroJSONHandler::handleSuccess(LLCore::HttpResponse * response, LLCore: return result; } -LLSD HttpCoroJSONHandler::parseBody(LLCore::HttpResponse *response, bool &success) +LLSD HttpCoroJSONHandler::parseBody(LLCore::HttpResponse *response, bool &success) const { success = true; BufferArray * body(response->getBody()); |
