summaryrefslogtreecommitdiff
path: root/indra/llmessage/llcorehttputil.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llmessage/llcorehttputil.cpp')
-rw-r--r--indra/llmessage/llcorehttputil.cpp132
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());