summaryrefslogtreecommitdiff
path: root/indra/llmessage
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llmessage')
-rwxr-xr-xindra/llmessage/CMakeLists.txt48
-rwxr-xr-xindra/llmessage/llassetstorage.cpp2
-rwxr-xr-xindra/llmessage/llavatarnamecache.cpp274
-rwxr-xr-xindra/llmessage/llavatarnamecache.h5
-rwxr-xr-xindra/llmessage/llcachename.cpp2
-rw-r--r--indra/llmessage/llcorehttputil.cpp1151
-rw-r--r--indra/llmessage/llcorehttputil.h512
-rwxr-xr-xindra/llmessage/llcurl.cpp858
-rwxr-xr-xindra/llmessage/llcurl.h96
-rwxr-xr-xindra/llmessage/llhost.cpp2
-rwxr-xr-xindra/llmessage/llhost.h9
-rwxr-xr-xindra/llmessage/llhttpclient.cpp4
-rwxr-xr-xindra/llmessage/llhttpclientadapter.cpp73
-rwxr-xr-xindra/llmessage/llhttpclientadapter.h51
-rwxr-xr-xindra/llmessage/llhttpclientinterface.h16
-rw-r--r--indra/llmessage/llhttpsdhandler.cpp105
-rw-r--r--indra/llmessage/llhttpsdhandler.h72
-rwxr-xr-xindra/llmessage/llhttpsender.cpp94
-rwxr-xr-xindra/llmessage/llhttpsender.h59
-rwxr-xr-xindra/llmessage/llsdmessage.cpp168
-rwxr-xr-xindra/llmessage/llsdmessage.h168
-rwxr-xr-xindra/llmessage/llsdrpcclient.h8
-rwxr-xr-xindra/llmessage/message.cpp127
-rwxr-xr-xindra/llmessage/message.h5
-rwxr-xr-xindra/llmessage/tests/llhttpclientadapter_test.cpp221
-rwxr-xr-xindra/llmessage/tests/llsdmessage_test.cpp130
-rwxr-xr-xindra/llmessage/tests/lltesthttpclientadapter.cpp61
-rwxr-xr-xindra/llmessage/tests/lltesthttpclientadapter.h57
28 files changed, 2481 insertions, 1897 deletions
diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt
index 0a308fbf10..9739f7c607 100755
--- a/indra/llmessage/CMakeLists.txt
+++ b/indra/llmessage/CMakeLists.txt
@@ -14,6 +14,7 @@ include(LLAddBuildTest)
include(Python)
include(Tut)
include(Python)
+include(JsonCpp)
include_directories (${CMAKE_CURRENT_SOURCE_DIR})
@@ -23,6 +24,7 @@ include_directories(
${LLMATH_INCLUDE_DIRS}
${LLMESSAGE_INCLUDE_DIRS}
${LLVFS_INCLUDE_DIRS}
+ ${JSONCPP_INCLUDE_DIR}
)
set(llmessage_SOURCE_FILES
@@ -47,10 +49,9 @@ set(llmessage_SOURCE_FILES
llhost.cpp
llhttpassetstorage.cpp
llhttpclient.cpp
- llhttpclientadapter.cpp
llhttpconstants.cpp
llhttpnode.cpp
- llhttpsender.cpp
+ llhttpsdhandler.cpp
llinstantmessage.cpp
lliobuffer.cpp
lliohttpserver.cpp
@@ -74,7 +75,6 @@ set(llmessage_SOURCE_FILES
llpumpio.cpp
llsdappservices.cpp
llsdhttpserver.cpp
- llsdmessage.cpp
llsdmessagebuilder.cpp
llsdmessagereader.cpp
llsdrpcclient.cpp
@@ -142,11 +142,10 @@ set(llmessage_HEADER_FILES
llhttpassetstorage.h
llhttpclient.h
llhttpclientinterface.h
- llhttpclientadapter.h
llhttpconstants.h
llhttpnode.h
llhttpnodeadapter.h
- llhttpsender.h
+ llhttpsdhandler.h
llinstantmessage.h
llinvite.h
lliobuffer.h
@@ -176,7 +175,6 @@ set(llmessage_HEADER_FILES
llregionhandle.h
llsdappservices.h
llsdhttpserver.h
- llsdmessage.h
llsdmessagebuilder.h
llsdmessagereader.h
llsdrpcclient.h
@@ -226,12 +224,17 @@ target_link_libraries(
llmessage
${CURL_LIBRARIES}
${LLCOMMON_LIBRARIES}
- ${LLVFS_LIBRARES}
+ ${LLVFS_LIBRARIES}
${LLMATH_LIBRARIES}
${CARES_LIBRARIES}
+ ${JSONCPP_LIBRARIES}
${OPENSSL_LIBRARIES}
${CRYPTO_LIBRARIES}
${XMLRPCEPI_LIBRARIES}
+ ${LLCOREHTTP_LIBRARIES}
+ ${BOOST_COROUTINE_LIBRARY}
+ ${BOOST_CONTEXT_LIBRARY}
+ ${BOOST_SYSTEM_LIBRARY}
)
# tests
@@ -243,36 +246,25 @@ if (LL_TESTS)
)
LL_ADD_PROJECT_UNIT_TESTS(llmessage "${llmessage_TEST_SOURCE_FILES}")
+
# set(TEST_DEBUG on)
+
set(test_libs
- ${CURL_LIBRARIES}
- ${LLMESSAGE_LIBRARIES}
${WINDOWS_LIBRARIES}
${LLVFS_LIBRARIES}
${LLMATH_LIBRARIES}
+ ${CURL_LIBRARIES}
${LLCOMMON_LIBRARIES}
- ${GOOGLEMOCK_LIBRARIES}
- )
-
- LL_ADD_INTEGRATION_TEST(
- llsdmessage
- "llsdmessage.cpp"
- "${test_libs}"
- ${PYTHON_EXECUTABLE}
- "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_llsdmessage_peer.py"
- )
-
- LL_ADD_INTEGRATION_TEST(
- llhttpclient
- "llhttpclient.cpp"
- "${test_libs}"
- ${PYTHON_EXECUTABLE}
- "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_llsdmessage_peer.py"
+ ${LLMESSAGE_LIBRARIES}
+ ${LLCOREHTTP_LIBRARIES}
+ ${JSONCPP_LIBRARIES}
+ ${BOOST_COROUTINE_LIBRARY}
+ ${BOOST_CONTEXT_LIBRARY}
+ ${GOOGLEMOCK_LIBRARIES}
)
- LL_ADD_INTEGRATION_TEST(llavatarnamecache "" "${test_libs}")
+ #LL_ADD_INTEGRATION_TEST(llavatarnamecache "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llhost "" "${test_libs}")
- LL_ADD_INTEGRATION_TEST(llhttpclientadapter "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llpartdata "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llxfer_file "" "${test_libs}")
endif (LL_TESTS)
diff --git a/indra/llmessage/llassetstorage.cpp b/indra/llmessage/llassetstorage.cpp
index 61663e1982..5740b8f7da 100755
--- a/indra/llmessage/llassetstorage.cpp
+++ b/indra/llmessage/llassetstorage.cpp
@@ -290,7 +290,7 @@ LLAssetStorage::LLAssetStorage(LLMessageSystem *msg, LLXferManager *xfer, LLVFS
LLAssetStorage::LLAssetStorage(LLMessageSystem *msg, LLXferManager *xfer,
LLVFS *vfs, LLVFS *static_vfs)
{
- _init(msg, xfer, vfs, static_vfs, LLHost::invalid);
+ _init(msg, xfer, vfs, static_vfs, LLHost());
}
diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp
index 549708097a..d262862c80 100755
--- a/indra/llmessage/llavatarnamecache.cpp
+++ b/indra/llmessage/llavatarnamecache.cpp
@@ -30,12 +30,20 @@
#include "llcachename.h" // we wrap this system
#include "llframetimer.h"
-#include "llhttpclient.h"
#include "llsd.h"
#include "llsdserialize.h"
-
+#include "httpresponse.h"
+#include "llhttpsdhandler.h"
#include <boost/tokenizer.hpp>
+#include "httpcommon.h"
+#include "httprequest.h"
+#include "httpheaders.h"
+#include "httpoptions.h"
+#include "llcoros.h"
+#include "lleventcoro.h"
+#include "llcorehttputil.h"
+
#include <map>
#include <set>
@@ -90,6 +98,12 @@ namespace LLAvatarNameCache
// Time-to-live for a temp cache entry.
const F64 TEMP_CACHE_ENTRY_LIFETIME = 60.0;
+ LLCore::HttpRequest::ptr_t sHttpRequest;
+ LLCore::HttpHeaders::ptr_t sHttpHeaders;
+ LLCore::HttpOptions::ptr_t sHttpOptions;
+ LLCore::HttpRequest::policy_t sHttpPolicy;
+ LLCore::HttpRequest::priority_t sHttpPriority;
+
//-----------------------------------------------------------------------
// Internal methods
//-----------------------------------------------------------------------
@@ -121,7 +135,12 @@ namespace LLAvatarNameCache
// Erase expired names from cache
void eraseUnrefreshed();
- bool expirationFromCacheControl(const LLSD& headers, F64 *expires);
+ bool expirationFromCacheControl(const LLSD& headers, F64 *expires);
+
+ // This is a coroutine.
+ void requestAvatarNameCache_(std::string url, std::vector<LLUUID> agentIds);
+
+ void handleAvNameCacheSuccess(const LLSD &data, const LLSD &httpResult);
}
/* Sample response:
@@ -163,94 +182,117 @@ namespace LLAvatarNameCache
</llsd>
*/
-class LLAvatarNameResponder : public LLHTTPClient::Responder
+// Coroutine for sending and processing avatar name cache requests.
+// Do not call directly. See documentation in lleventcoro.h and llcoro.h for
+// further explanation.
+void LLAvatarNameCache::requestAvatarNameCache_(std::string url, std::vector<LLUUID> agentIds)
{
- LOG_CLASS(LLAvatarNameResponder);
-private:
- // need to store agent ids that are part of this request in case of
- // an error, so we can flag them as unavailable
- std::vector<LLUUID> mAgentIDs;
-
-public:
- LLAvatarNameResponder(const std::vector<LLUUID>& agent_ids)
- : mAgentIDs(agent_ids)
- { }
-
-protected:
- /*virtual*/ void httpSuccess()
- {
- const LLSD& content = getContent();
- if (!content.isMap())
- {
- failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
- return;
- }
- // Pull expiration out of headers if available
- F64 expires = LLAvatarNameCache::nameExpirationFromHeaders(getResponseHeaders());
- F64 now = LLFrameTimer::getTotalSeconds();
+ LL_DEBUGS("AvNameCache") << "Entering coroutine " << LLCoros::instance().getName()
+ << " with url '" << url << "', requesting " << agentIds.size() << " Agent Ids" << LL_ENDL;
- const LLSD& agents = content["agents"];
- LLSD::array_const_iterator it = agents.beginArray();
- for ( ; it != agents.endArray(); ++it)
- {
- const LLSD& row = *it;
- LLUUID agent_id = row["id"].asUUID();
+ try
+ {
+ bool success = true;
- LLAvatarName av_name;
- av_name.fromLLSD(row);
+ LLCoreHttpUtil::HttpCoroutineAdapter httpAdapter("NameCache", LLAvatarNameCache::sHttpPolicy);
+ LLSD results = httpAdapter.getAndYield(sHttpRequest, url);
+ LLSD httpResults;
- // Use expiration time from header
- av_name.mExpires = expires;
+ LL_DEBUGS() << results << LL_ENDL;
- LL_DEBUGS("AvNameCache") << "LLAvatarNameResponder::result for " << agent_id << LL_ENDL;
- av_name.dump();
-
- // cache it and fire signals
- LLAvatarNameCache::processName(agent_id, av_name);
- }
+ if (!results.isMap())
+ {
+ LL_WARNS("AvNameCache") << " Invalid result returned from LLCoreHttpUtil::HttpCoroHandler." << LL_ENDL;
+ success = false;
+ }
+ else
+ {
+ httpResults = results["http_result"];
+ success = httpResults["success"].asBoolean();
+ if (!success)
+ {
+ LL_WARNS("AvNameCache") << "Error result from LLCoreHttpUtil::HttpCoroHandler. Code "
+ << httpResults["status"] << ": '" << httpResults["message"] << "'" << LL_ENDL;
+ }
+ }
- // Same logic as error response case
- const LLSD& unresolved_agents = content["bad_ids"];
- S32 num_unresolved = unresolved_agents.size();
- if (num_unresolved > 0)
- {
- LL_WARNS("AvNameCache") << "LLAvatarNameResponder::result " << num_unresolved << " unresolved ids; "
- << "expires in " << expires - now << " seconds"
- << LL_ENDL;
- it = unresolved_agents.beginArray();
- for ( ; it != unresolved_agents.endArray(); ++it)
- {
- const LLUUID& agent_id = *it;
+ if (!success)
+ { // on any sort of failure add dummy records for any agent IDs
+ // in this request that we do not have cached already
+ std::vector<LLUUID>::const_iterator it = agentIds.begin();
+ for ( ; it != agentIds.end(); ++it)
+ {
+ const LLUUID& agent_id = *it;
+ LLAvatarNameCache::handleAgentError(agent_id);
+ }
+ return;
+ }
- LL_WARNS("AvNameCache") << "LLAvatarNameResponder::result "
- << "failed id " << agent_id
- << LL_ENDL;
+ LLAvatarNameCache::handleAvNameCacheSuccess(results, httpResults);
- LLAvatarNameCache::handleAgentError(agent_id);
- }
- }
- LL_DEBUGS("AvNameCache") << "LLAvatarNameResponder::result "
- << LLAvatarNameCache::sCache.size() << " cached names"
- << LL_ENDL;
}
+ catch (std::exception e)
+ {
+ LL_WARNS() << "Caught exception '" << e.what() << "'" << LL_ENDL;
+ }
+ catch (...)
+ {
+ LL_WARNS() << "Caught unknown exception." << LL_ENDL;
+ }
+}
- /*virtual*/ void httpFailure()
- {
- // If there's an error, it might be caused by PeopleApi,
- // or when loading textures on startup and using a very slow
- // network, this query may time out.
- // What we should do depends on whether or not we have a cached name
- LL_WARNS("AvNameCache") << dumpResponse() << LL_ENDL;
-
- // Add dummy records for any agent IDs in this request that we do not have cached already
- std::vector<LLUUID>::const_iterator it = mAgentIDs.begin();
- for ( ; it != mAgentIDs.end(); ++it)
- {
- const LLUUID& agent_id = *it;
- LLAvatarNameCache::handleAgentError(agent_id);
- }
- }
-};
+void LLAvatarNameCache::handleAvNameCacheSuccess(const LLSD &data, const LLSD &httpResult)
+{
+
+ LLSD headers = httpResult["headers"];
+ // Pull expiration out of headers if available
+ F64 expires = LLAvatarNameCache::nameExpirationFromHeaders(headers);
+ F64 now = LLFrameTimer::getTotalSeconds();
+
+ const LLSD& agents = data["agents"];
+ LLSD::array_const_iterator it = agents.beginArray();
+ for (; it != agents.endArray(); ++it)
+ {
+ const LLSD& row = *it;
+ LLUUID agent_id = row["id"].asUUID();
+
+ LLAvatarName av_name;
+ av_name.fromLLSD(row);
+
+ // Use expiration time from header
+ av_name.mExpires = expires;
+
+ LL_DEBUGS("AvNameCache") << "LLAvatarNameResponder::result for " << agent_id << LL_ENDL;
+ av_name.dump();
+
+ // cache it and fire signals
+ LLAvatarNameCache::processName(agent_id, av_name);
+ }
+
+ // Same logic as error response case
+ const LLSD& unresolved_agents = data["bad_ids"];
+ S32 num_unresolved = unresolved_agents.size();
+ if (num_unresolved > 0)
+ {
+ LL_WARNS("AvNameCache") << "LLAvatarNameResponder::result " << num_unresolved << " unresolved ids; "
+ << "expires in " << expires - now << " seconds"
+ << LL_ENDL;
+ it = unresolved_agents.beginArray();
+ for (; it != unresolved_agents.endArray(); ++it)
+ {
+ const LLUUID& agent_id = *it;
+
+ LL_WARNS("AvNameCache") << "LLAvatarNameResponder::result "
+ << "failed id " << agent_id
+ << LL_ENDL;
+
+ LLAvatarNameCache::handleAgentError(agent_id);
+ }
+ }
+ LL_DEBUGS("AvNameCache") << "LLAvatarNameResponder::result "
+ << LLAvatarNameCache::sCache.size() << " cached names"
+ << LL_ENDL;
+}
// Provide some fallback for agents that return errors
void LLAvatarNameCache::handleAgentError(const LLUUID& agent_id)
@@ -353,10 +395,15 @@ void LLAvatarNameCache::requestNamesViaCapability()
}
}
- if (!url.empty())
- {
- LL_INFOS("AvNameCache") << "LLAvatarNameCache::requestNamesViaCapability getting " << ids << " ids" << LL_ENDL;
- LLHTTPClient::get(url, new LLAvatarNameResponder(agent_ids));
+ if (!url.empty())
+ {
+ LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::requestNamesViaCapability requested " << ids << " ids" << LL_ENDL;
+
+ std::string coroname =
+ LLCoros::instance().launch("LLAvatarNameCache::requestAvatarNameCache_",
+ boost::bind(&LLAvatarNameCache::requestAvatarNameCache_, url, agent_ids));
+ LL_DEBUGS("AvNameCache") << coroname << " with url '" << url << "', agent_ids.size()=" << agent_ids.size() << LL_ENDL;
+
}
}
@@ -419,11 +466,20 @@ void LLAvatarNameCache::initClass(bool running, bool usePeopleAPI)
{
sRunning = running;
sUsePeopleAPI = usePeopleAPI;
+
+ sHttpRequest = LLCore::HttpRequest::ptr_t(new LLCore::HttpRequest());
+ sHttpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders());
+ sHttpOptions = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions());
+ sHttpPolicy = LLCore::HttpRequest::DEFAULT_POLICY_ID;
+ sHttpPriority = 0;
}
void LLAvatarNameCache::cleanupClass()
{
- sCache.clear();
+ sHttpRequest.reset();
+ sHttpHeaders.reset();
+ sHttpOptions.reset();
+ sCache.clear();
}
bool LLAvatarNameCache::importFile(std::istream& istr)
@@ -698,6 +754,50 @@ void LLAvatarNameCache::insert(const LLUUID& agent_id, const LLAvatarName& av_na
sCache[agent_id] = av_name;
}
+#if 0
+F64 LLAvatarNameCache::nameExpirationFromHeaders(LLCore::HttpHeaders *headers)
+{
+ F64 expires = 0.0;
+ if (expirationFromCacheControl(headers, &expires))
+ {
+ return expires;
+ }
+ else
+ {
+ // With no expiration info, default to an hour
+ const F64 DEFAULT_EXPIRES = 60.0 * 60.0;
+ F64 now = LLFrameTimer::getTotalSeconds();
+ return now + DEFAULT_EXPIRES;
+ }
+}
+
+bool LLAvatarNameCache::expirationFromCacheControl(LLCore::HttpHeaders *headers, F64 *expires)
+{
+ bool fromCacheControl = false;
+ F64 now = LLFrameTimer::getTotalSeconds();
+
+ // Allow the header to override the default
+ const std::string *cache_control;
+
+ cache_control = headers->find(HTTP_IN_HEADER_CACHE_CONTROL);
+
+ if (cache_control && !cache_control->empty())
+ {
+ S32 max_age = 0;
+ if (max_age_from_cache_control(*cache_control, &max_age))
+ {
+ *expires = now + (F64)max_age;
+ fromCacheControl = true;
+ }
+ }
+ LL_DEBUGS("AvNameCache")
+ << ( fromCacheControl ? "expires based on cache control " : "default expiration " )
+ << "in " << *expires - now << " seconds"
+ << LL_ENDL;
+
+ return fromCacheControl;
+}
+#else
F64 LLAvatarNameCache::nameExpirationFromHeaders(const LLSD& headers)
{
F64 expires = 0.0;
@@ -742,7 +842,7 @@ bool LLAvatarNameCache::expirationFromCacheControl(const LLSD& headers, F64 *exp
return fromCacheControl;
}
-
+#endif
void LLAvatarNameCache::addUseDisplayNamesCallback(const use_display_name_signal_t::slot_type& cb)
{
diff --git a/indra/llmessage/llavatarnamecache.h b/indra/llmessage/llavatarnamecache.h
index 5a10053a69..bd2715e956 100755
--- a/indra/llmessage/llavatarnamecache.h
+++ b/indra/llmessage/llavatarnamecache.h
@@ -29,7 +29,6 @@
#define LLAVATARNAMECACHE_H
#include "llavatarname.h" // for convenience
-
#include <boost/signals2.hpp>
class LLSD;
@@ -49,7 +48,7 @@ namespace LLAvatarNameCache
bool importFile(std::istream& istr);
void exportFile(std::ostream& ostr);
- // On the viewer, usually a simulator capabilitity.
+ // On the viewer, usually a simulator capabilities.
// If empty, name cache will fall back to using legacy name lookup system.
void setNameLookupURL(const std::string& name_lookup_url);
@@ -90,7 +89,7 @@ namespace LLAvatarNameCache
// Compute name expiration time from HTTP Cache-Control header,
// or return default value, in seconds from epoch.
- F64 nameExpirationFromHeaders(const LLSD& headers);
+ F64 nameExpirationFromHeaders(const LLSD& headers);
void addUseDisplayNamesCallback(const use_display_name_signal_t::slot_type& cb);
}
diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp
index daf3e0b4de..66bd85f4e6 100755
--- a/indra/llmessage/llcachename.cpp
+++ b/indra/llmessage/llcachename.cpp
@@ -259,7 +259,7 @@ LLCacheName::~LLCacheName()
}
LLCacheName::Impl::Impl(LLMessageSystem* msg)
- : mMsg(msg), mUpstreamHost(LLHost::invalid)
+ : mMsg(msg), mUpstreamHost(LLHost())
{
mMsg->setHandlerFuncFast(
_PREHASH_UUIDNameRequest, handleUUIDNameRequest, (void**)this);
diff --git a/indra/llmessage/llcorehttputil.cpp b/indra/llmessage/llcorehttputil.cpp
index ee80b0fd94..d342888255 100644
--- a/indra/llmessage/llcorehttputil.cpp
+++ b/indra/llmessage/llcorehttputil.cpp
@@ -28,112 +28,1111 @@
#include "linden_common.h"
#include <sstream>
-
+#include <algorithm>
+#include <iterator>
#include "llcorehttputil.h"
+#include "llhttpconstants.h"
+#include "llsd.h"
+#include "llsdjson.h"
#include "llsdserialize.h"
+#include "reader.h"
+#include "llvfile.h"
+#include "message.h" // for getting the port
using namespace LLCore;
namespace LLCoreHttpUtil
{
+void logMessageSuccess(std::string logAuth, std::string url, std::string message)
+{
+ LL_INFOS() << logAuth << " Success '" << message << "' for " << url << LL_ENDL;
+}
+
+void logMessageFail(std::string logAuth, std::string url, std::string message)
+{
+ LL_WARNS() << logAuth << " Failure '" << message << "' for " << url << LL_ENDL;
+}
+
+//=========================================================================
+/// The HttpRequestPumper is a utility class. When constructed it will poll the
+/// supplied HttpRequest once per frame until it is destroyed.
+///
+class HttpRequestPumper
+{
+public:
+ HttpRequestPumper(const LLCore::HttpRequest::ptr_t &request);
+ ~HttpRequestPumper();
+
+private:
+ bool pollRequest(const LLSD&);
+
+ LLTempBoundListener mBoundListener;
+ LLCore::HttpRequest::ptr_t mHttpRequest;
+};
+
+//=========================================================================
// *TODO: Currently converts only from XML content. A mode
// to convert using fromBinary() might be useful as well. Mesh
// headers could use it.
bool responseToLLSD(HttpResponse * response, bool log, LLSD & out_llsd)
{
- // Convert response to LLSD
- BufferArray * body(response->getBody());
- if (! body || ! body->size())
- {
- return false;
- }
+ // Convert response to LLSD
+ BufferArray * body(response->getBody());
+ if (!body || !body->size())
+ {
+ return false;
+ }
- LLCore::BufferArrayStream bas(body);
- LLSD body_llsd;
- S32 parse_status(LLSDSerialize::fromXML(body_llsd, bas, log));
- if (LLSDParser::PARSE_FAILURE == parse_status){
- return false;
- }
- out_llsd = body_llsd;
- return true;
+ LLCore::BufferArrayStream bas(body);
+ LLSD body_llsd;
+ S32 parse_status(LLSDSerialize::fromXML(body_llsd, bas, log));
+ if (LLSDParser::PARSE_FAILURE == parse_status){
+ return false;
+ }
+ out_llsd = body_llsd;
+ return true;
}
HttpHandle requestPostWithLLSD(HttpRequest * request,
- HttpRequest::policy_t policy_id,
- HttpRequest::priority_t priority,
- const std::string & url,
- const LLSD & body,
- HttpOptions * options,
- HttpHeaders * headers,
- HttpHandler * handler)
+ HttpRequest::policy_t policy_id,
+ HttpRequest::priority_t priority,
+ const std::string & url,
+ const LLSD & body,
+ const HttpOptions::ptr_t &options,
+ const HttpHeaders::ptr_t &headers,
+ HttpHandler * handler)
+{
+ HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
+
+ BufferArray * ba = new BufferArray();
+ BufferArrayStream bas(ba);
+ LLSDSerialize::toXML(body, bas);
+
+ handle = request->requestPost(policy_id,
+ priority,
+ url,
+ ba,
+ options,
+ headers,
+ handler);
+ ba->release();
+ return handle;
+}
+
+
+HttpHandle requestPutWithLLSD(HttpRequest * request,
+ HttpRequest::policy_t policy_id,
+ HttpRequest::priority_t priority,
+ const std::string & url,
+ const LLSD & body,
+ const HttpOptions::ptr_t &options,
+ const HttpHeaders::ptr_t &headers,
+ HttpHandler * handler)
+{
+ HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
+
+ BufferArray * ba = new BufferArray();
+ BufferArrayStream bas(ba);
+ LLSDSerialize::toXML(body, bas);
+
+ handle = request->requestPut(policy_id,
+ priority,
+ url,
+ ba,
+ options,
+ headers,
+ handler);
+ ba->release();
+ return handle;
+}
+
+HttpHandle requestPatchWithLLSD(HttpRequest * request,
+ HttpRequest::policy_t policy_id,
+ HttpRequest::priority_t priority,
+ const std::string & url,
+ const LLSD & body,
+ const HttpOptions::ptr_t &options,
+ const HttpHeaders::ptr_t &headers,
+ HttpHandler * handler)
{
- HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
+ HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
- BufferArray * ba = new BufferArray();
- BufferArrayStream bas(ba);
- LLSDSerialize::toXML(body, bas);
+ BufferArray * ba = new BufferArray();
+ BufferArrayStream bas(ba);
+ LLSDSerialize::toXML(body, bas);
- handle = request->requestPost(policy_id,
- priority,
- url,
- ba,
- options,
- headers,
- handler);
- ba->release();
- return handle;
+ handle = request->requestPatch(policy_id,
+ priority,
+ url,
+ ba,
+ options,
+ headers,
+ handler);
+ ba->release();
+ return handle;
}
std::string responseToString(LLCore::HttpResponse * response)
{
- static const std::string empty("[Empty]");
-
- if (! response)
- {
- return empty;
- }
-
- BufferArray * body(response->getBody());
- if (! body || ! body->size())
- {
- return empty;
- }
-
- // Attempt to parse as LLSD regardless of content-type
- LLSD body_llsd;
- if (responseToLLSD(response, false, body_llsd))
- {
- std::ostringstream tmp;
-
- LLSDSerialize::toPrettyNotation(body_llsd, tmp);
- std::size_t temp_len(tmp.tellp());
-
- if (temp_len)
- {
- return tmp.str().substr(0, std::min(temp_len, std::size_t(1024)));
- }
- }
- else
- {
- // *TODO: More elaborate forms based on Content-Type as needed.
- char content[1024];
-
- size_t len(body->read(0, content, sizeof(content)));
- if (len)
- {
- return std::string(content, 0, len);
- }
- }
-
- // Default
- return empty;
+ static const std::string empty("[Empty]");
+
+ if (!response)
+ {
+ return empty;
+ }
+
+ BufferArray * body(response->getBody());
+ if (!body || !body->size())
+ {
+ return empty;
+ }
+
+ // Attempt to parse as LLSD regardless of content-type
+ LLSD body_llsd;
+ if (responseToLLSD(response, false, body_llsd))
+ {
+ std::ostringstream tmp;
+
+ LLSDSerialize::toPrettyNotation(body_llsd, tmp);
+ std::size_t temp_len(tmp.tellp());
+
+ if (temp_len)
+ {
+ return tmp.str().substr(0, std::min(temp_len, std::size_t(1024)));
+ }
+ }
+ else
+ {
+ // *TODO: More elaborate forms based on Content-Type as needed.
+ char content[1024];
+
+ size_t len(body->read(0, content, sizeof(content)));
+ if (len)
+ {
+ return std::string(content, 0, len);
+ }
+ }
+
+ // Default
+ return empty;
+}
+
+//========================================================================
+
+HttpCoroHandler::HttpCoroHandler(LLEventStream &reply) :
+ mReplyPump(reply)
+{
+}
+
+void HttpCoroHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response)
+{
+ LLSD result;
+
+ LLCore::HttpStatus status = response->getStatus();
+
+ if (status == LLCore::HttpStatus(LLCore::HttpStatus::LLCORE, LLCore::HE_HANDLE_NOT_FOUND))
+ { // A response came in for a canceled request and we have not processed the
+ // cancel yet. Patience!
+ return;
+ }
+
+ if (!status)
+ {
+ result = LLSD::emptyMap();
+ LL_WARNS()
+ << "\n--------------------------------------------------------------------------\n"
+ << " Error[" << status.getType() << "] cannot access url '" << response->getRequestURL()
+ << "' because " << status.toString()
+ << "\n--------------------------------------------------------------------------"
+ << LL_ENDL;
+ }
+ else
+ {
+ result = this->handleSuccess(response, status);
+ }
+
+ buildStatusEntry(response, status, result);
+
+#if 1
+ // commenting out, but keeping since this can be useful for debugging
+ 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);
+
+ LL_WARNS() << "Returned body=" << std::endl << httpStatus["error_body"].asString() << LL_ENDL;
+ }
+#endif
+
+ mReplyPump.post(result);
+}
+
+void HttpCoroHandler::buildStatusEntry(LLCore::HttpResponse *response, LLCore::HttpStatus status, LLSD &result)
+{
+ LLSD httpresults = LLSD::emptyMap();
+
+ writeStatusCodes(status, response->getRequestURL(), httpresults);
+
+ LLSD httpHeaders = LLSD::emptyMap();
+ LLCore::HttpHeaders::ptr_t hdrs = response->getHeaders();
+
+ if (hdrs)
+ {
+ for (LLCore::HttpHeaders::iterator it = hdrs->begin(); it != hdrs->end(); ++it)
+ {
+ if (!(*it).second.empty())
+ {
+ httpHeaders[(*it).first] = (*it).second;
+ }
+ else
+ {
+ httpHeaders[(*it).first] = static_cast<LLSD::Boolean>(true);
+ }
+ }
+ }
+
+ httpresults[HttpCoroutineAdapter::HTTP_RESULTS_HEADERS] = httpHeaders;
+ result[HttpCoroutineAdapter::HTTP_RESULTS] = httpresults;
+}
+
+void HttpCoroHandler::writeStatusCodes(LLCore::HttpStatus status, const std::string &url, LLSD &result)
+{
+ result[HttpCoroutineAdapter::HTTP_RESULTS_SUCCESS] = static_cast<LLSD::Boolean>(status);
+ result[HttpCoroutineAdapter::HTTP_RESULTS_TYPE] = static_cast<LLSD::Integer>(status.getType());
+ result[HttpCoroutineAdapter::HTTP_RESULTS_STATUS] = static_cast<LLSD::Integer>(status.getStatus());
+ result[HttpCoroutineAdapter::HTTP_RESULTS_MESSAGE] = static_cast<LLSD::String>(status.getMessage());
+ result[HttpCoroutineAdapter::HTTP_RESULTS_URL] = static_cast<LLSD::String>(url);
+
+}
+
+//=========================================================================
+/// The HttpCoroLLSDHandler is a specialization of the LLCore::HttpHandler for
+/// interacting with coroutines. When the request is completed the response
+/// will be posted onto the supplied Event Pump.
+///
+/// If the LLSD retrieved from through the HTTP connection is not in the form
+/// of a LLSD::map it will be returned as in an llsd["content"] element.
+///
+/// The LLSD posted back to the coroutine will have the following additions:
+/// llsd["http_result"] -+- ["message"] - An error message returned from the HTTP status
+/// +- ["status"] - The status code associated with the HTTP call
+/// +- ["success"] - Success of failure of the HTTP call and LLSD parsing.
+/// +- ["type"] - The LLCore::HttpStatus type associted with the HTTP call
+/// +- ["url"] - The URL used to make the call.
+/// +- ["headers"] - A map of name name value pairs with the HTTP headers.
+///
+class HttpCoroLLSDHandler : public HttpCoroHandler
+{
+public:
+ HttpCoroLLSDHandler(LLEventStream &reply);
+
+protected:
+ virtual LLSD handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status);
+};
+
+//-------------------------------------------------------------------------
+HttpCoroLLSDHandler::HttpCoroLLSDHandler(LLEventStream &reply):
+ HttpCoroHandler(reply)
+{
+}
+
+
+LLSD HttpCoroLLSDHandler::handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status)
+{
+ LLSD result;
+
+ const bool emit_parse_errors = false;
+
+ bool parsed = !((response->getBodySize() == 0) ||
+ !LLCoreHttpUtil::responseToLLSD(response, emit_parse_errors, result));
+
+ if (!parsed)
+ {
+ // Only emit a warning if we failed to parse when 'content-type' == 'application/llsd+xml'
+ LLCore::HttpHeaders::ptr_t headers(response->getHeaders());
+ const std::string *contentType = (headers) ? headers->find(HTTP_IN_HEADER_CONTENT_TYPE) : NULL;
+
+ if (contentType && (HTTP_CONTENT_LLSD_XML == *contentType))
+ {
+ std::string thebody = LLCoreHttpUtil::responseToString(response);
+ LL_WARNS() << "Failed to deserialize . " << response->getRequestURL() << " [status:" << response->getStatus().toString() << "] "
+ << " body: " << thebody << LL_ENDL;
+
+ // Replace the status with a new one indicating the failure.
+ status = LLCore::HttpStatus(499, "Failed to deserialize LLSD.");
+ }
+ }
+
+ if (result.isUndefined())
+ { // If we've gotten to this point and the result LLSD is still undefined
+ // either there was an issue deserializing the body or the response was
+ // blank. Create an empty map to hold the result either way.
+ result = LLSD::emptyMap();
+ }
+ else if (!result.isMap())
+ { // The results are not themselves a map. Move them down so that
+ // this method can return a map to the caller.
+ // *TODO: Should it always do this?
+ LLSD newResult = LLSD::emptyMap();
+ newResult[HttpCoroutineAdapter::HTTP_RESULTS_CONTENT] = result;
+ result = newResult;
+ }
+
+ return result;
+}
+
+//========================================================================
+/// The HttpCoroRawHandler is a specialization of the LLCore::HttpHandler for
+/// interacting with coroutines.
+///
+/// In addition to the normal "http_results" the returned LLSD will contain
+/// an entry keyed with "raw" containing the unprocessed results of the HTTP
+/// call.
+///
+class HttpCoroRawHandler : public HttpCoroHandler
+{
+public:
+ HttpCoroRawHandler(LLEventStream &reply);
+
+ virtual LLSD handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status);
+};
+
+//-------------------------------------------------------------------------
+HttpCoroRawHandler::HttpCoroRawHandler(LLEventStream &reply):
+ HttpCoroHandler(reply)
+{
+}
+
+LLSD HttpCoroRawHandler::handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status)
+{
+ LLSD result = LLSD::emptyMap();
+
+ BufferArray * body(response->getBody());
+ if (!body || !body->size())
+ {
+ return result;
+ }
+
+ size_t size = body->size();
+
+ LLCore::BufferArrayStream bas(body);
+
+#if 1
+ // This is the slower implementation. It is safe vis-a-vi the const_cast<> and modification
+ // of a LLSD managed array but contains an extra (potentially large) copy.
+ //
+ // *TODO: https://jira.secondlife.com/browse/MAINT-5221
+
+ LLSD::Binary data;
+ data.reserve(size);
+ bas >> std::noskipws;
+ data.assign(std::istream_iterator<U8>(bas), std::istream_iterator<U8>());
+
+ result[HttpCoroutineAdapter::HTTP_RESULTS_RAW] = data;
+
+#else
+ // This is disabled because it's dangerous. See the other case for an
+ // alternate implementation.
+ // We create a new LLSD::Binary object and assign it to the result map.
+ // The LLSD has created it's own copy so we retrieve it asBinary and const cast
+ // the reference so that we can modify it.
+ // *TODO: This is potentially dangerous... but I am trying to avoid a potentially
+ // large copy.
+ result[HttpCoroutineAdapter::HTTP_RESULTS_RAW] = LLSD::Binary();
+ LLSD::Binary &data = const_cast<LLSD::Binary &>( result[HttpCoroutineAdapter::HTTP_RESULTS_RAW].asBinary() );
+
+ data.reserve(size);
+ bas >> std::noskipws;
+ data.assign(std::istream_iterator<U8>(bas), std::istream_iterator<U8>());
+#endif
+
+ return result;
+}
+
+//========================================================================
+/// The HttpCoroJSONHandler is a specialization of the LLCore::HttpHandler for
+/// interacting with coroutines.
+///
+/// In addition to the normal "http_results" the returned LLSD will contain
+/// JSON entries will be converted into an LLSD map. All results are considered
+/// strings
+///
+class HttpCoroJSONHandler : public HttpCoroHandler
+{
+public:
+ HttpCoroJSONHandler(LLEventStream &reply);
+
+ virtual LLSD handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status);
+};
+
+//-------------------------------------------------------------------------
+HttpCoroJSONHandler::HttpCoroJSONHandler(LLEventStream &reply) :
+ HttpCoroHandler(reply)
+{
+}
+
+LLSD HttpCoroJSONHandler::handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status)
+{
+ LLSD result = LLSD::emptyMap();
+
+ BufferArray * body(response->getBody());
+ if (!body || !body->size())
+ {
+ return result;
+ }
+
+ LLCore::BufferArrayStream bas(body);
+ Json::Value jsonRoot;
+
+ try
+ {
+ bas >> jsonRoot;
+ }
+ catch (std::runtime_error e)
+ { // deserialization failed. Record the reason and pass back an empty map for markup.
+ status = LLCore::HttpStatus(499, std::string(e.what()));
+ return result;
+ }
+
+ // Convert the JSON structure to LLSD
+ result = LlsdFromJson(jsonRoot);
+
+ return result;
+}
+
+
+//========================================================================
+HttpRequestPumper::HttpRequestPumper(const LLCore::HttpRequest::ptr_t &request) :
+ mHttpRequest(request)
+{
+ mBoundListener = LLEventPumps::instance().obtain("mainloop").
+ listen(LLEventPump::inventName(), boost::bind(&HttpRequestPumper::pollRequest, this, _1));
+}
+
+HttpRequestPumper::~HttpRequestPumper()
+{
+ if (mBoundListener.connected())
+ {
+ mBoundListener.disconnect();
+ }
+}
+
+bool HttpRequestPumper::pollRequest(const LLSD&)
+{
+ if (mHttpRequest->getStatus() != HttpStatus(HttpStatus::LLCORE, HE_OP_CANCELED))
+ {
+ mHttpRequest->update(0L);
+ }
+ return false;
+}
+
+//========================================================================
+const std::string HttpCoroutineAdapter::HTTP_RESULTS("http_result");
+const std::string HttpCoroutineAdapter::HTTP_RESULTS_SUCCESS("success");
+const std::string HttpCoroutineAdapter::HTTP_RESULTS_TYPE("type");
+const std::string HttpCoroutineAdapter::HTTP_RESULTS_STATUS("status");
+const std::string HttpCoroutineAdapter::HTTP_RESULTS_MESSAGE("message");
+const std::string HttpCoroutineAdapter::HTTP_RESULTS_URL("url");
+const std::string HttpCoroutineAdapter::HTTP_RESULTS_HEADERS("headers");
+const std::string HttpCoroutineAdapter::HTTP_RESULTS_CONTENT("content");
+const std::string HttpCoroutineAdapter::HTTP_RESULTS_RAW("raw");
+
+HttpCoroutineAdapter::HttpCoroutineAdapter(const std::string &name,
+ LLCore::HttpRequest::policy_t policyId, LLCore::HttpRequest::priority_t priority) :
+ mAdapterName(name),
+ mPolicyId(policyId),
+ mPriority(priority),
+ mYieldingHandle(LLCORE_HTTP_HANDLE_INVALID),
+ mWeakRequest(),
+ mWeakHandler()
+{
+}
+
+HttpCoroutineAdapter::~HttpCoroutineAdapter()
+{
+ cancelYieldingOperation();
+}
+
+LLSD HttpCoroutineAdapter::postAndYield(LLCore::HttpRequest::ptr_t request,
+ const std::string & url, const LLSD & body,
+ LLCore::HttpOptions::ptr_t options, LLCore::HttpHeaders::ptr_t headers)
+{
+ LLEventStream replyPump(mAdapterName, true);
+ HttpCoroHandler::ptr_t httpHandler = HttpCoroHandler::ptr_t(new HttpCoroLLSDHandler(replyPump));
+
+ return postAndYield_(request, url, body, options, headers, httpHandler);
+}
+
+LLSD HttpCoroutineAdapter::postAndYield_(LLCore::HttpRequest::ptr_t &request,
+ const std::string & url, const LLSD & body,
+ LLCore::HttpOptions::ptr_t &options, LLCore::HttpHeaders::ptr_t &headers,
+ HttpCoroHandler::ptr_t &handler)
+{
+ HttpRequestPumper pumper(request);
+
+ checkDefaultHeaders(headers);
+
+ // The HTTPCoroHandler does not self delete, so retrieval of a the contained
+ // pointer from the smart pointer is safe in this case.
+ LLCore::HttpHandle hhandle = requestPostWithLLSD(request,
+ mPolicyId, mPriority, url, body, options, headers,
+ handler.get());
+
+ if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
+ {
+ return HttpCoroutineAdapter::buildImmediateErrorResult(request, url);
+ }
+
+ saveState(hhandle, request, handler);
+ LLSD results = llcoro::waitForEventOn(handler->getReplyPump());
+ cleanState();
+
+ return results;
+}
+
+LLSD HttpCoroutineAdapter::postAndYield(LLCore::HttpRequest::ptr_t request,
+ const std::string & url, LLCore::BufferArray::ptr_t rawbody,
+ LLCore::HttpOptions::ptr_t options, LLCore::HttpHeaders::ptr_t headers)
+{
+ LLEventStream replyPump(mAdapterName, true);
+ HttpCoroHandler::ptr_t httpHandler = HttpCoroHandler::ptr_t(new HttpCoroLLSDHandler(replyPump));
+
+ return postAndYield_(request, url, rawbody, options, headers, httpHandler);
+}
+
+LLSD HttpCoroutineAdapter::postRawAndYield(LLCore::HttpRequest::ptr_t request,
+ const std::string & url, LLCore::BufferArray::ptr_t rawbody,
+ LLCore::HttpOptions::ptr_t options, LLCore::HttpHeaders::ptr_t headers)
+{
+ LLEventStream replyPump(mAdapterName, true);
+ HttpCoroHandler::ptr_t httpHandler = HttpCoroHandler::ptr_t(new HttpCoroRawHandler(replyPump));
+
+ return postAndYield_(request, url, rawbody, options, headers, httpHandler);
+}
+
+// *TODO: This functionality could be moved into the LLCore::Http library itself
+// by having the CURL layer read the file directly.
+LLSD HttpCoroutineAdapter::postFileAndYield(LLCore::HttpRequest::ptr_t request,
+ const std::string & url, std::string fileName,
+ LLCore::HttpOptions::ptr_t options, LLCore::HttpHeaders::ptr_t headers)
+{
+ LLCore::BufferArray::ptr_t fileData(new LLCore::BufferArray);
+
+ // scoping for our streams so that they go away when we no longer need them.
+ {
+ LLCore::BufferArrayStream outs(fileData.get());
+ llifstream ins(fileName.c_str(), std::iostream::binary | std::iostream::out);
+
+ if (ins.is_open())
+ {
+
+ ins.seekg(0, std::ios::beg);
+ ins >> std::noskipws;
+
+ std::copy(std::istream_iterator<U8>(ins), std::istream_iterator<U8>(),
+ std::ostream_iterator<U8>(outs));
+
+ ins.close();
+ }
+ }
+
+ return postAndYield(request, url, fileData, options, headers);
+}
+
+// *TODO: This functionality could be moved into the LLCore::Http library itself
+// by having the CURL layer read the file directly.
+LLSD HttpCoroutineAdapter::postFileAndYield(LLCore::HttpRequest::ptr_t request,
+ const std::string & url, LLUUID assetId, LLAssetType::EType assetType,
+ LLCore::HttpOptions::ptr_t options, LLCore::HttpHeaders::ptr_t headers)
+{
+ LLCore::BufferArray::ptr_t fileData(new LLCore::BufferArray);
+
+ // scoping for our streams so that they go away when we no longer need them.
+ {
+ LLCore::BufferArrayStream outs(fileData.get());
+ LLVFile vfile(gVFS, assetId, assetType, LLVFile::READ);
+
+ S32 fileSize = vfile.getSize();
+ U8* fileBuffer;
+ fileBuffer = new U8[fileSize];
+ vfile.read(fileBuffer, fileSize);
+
+ outs.write((char*)fileBuffer, fileSize);
+ delete[] fileBuffer;
+ }
+
+ return postAndYield(request, url, fileData, options, headers);
+}
+
+
+LLSD HttpCoroutineAdapter::postAndYield_(LLCore::HttpRequest::ptr_t &request,
+ const std::string & url, LLCore::BufferArray::ptr_t &rawbody,
+ LLCore::HttpOptions::ptr_t &options, LLCore::HttpHeaders::ptr_t &headers,
+ HttpCoroHandler::ptr_t &handler)
+{
+ HttpRequestPumper pumper(request);
+
+ checkDefaultHeaders(headers);
+
+ // The HTTPCoroHandler does not self delete, so retrieval of a the contained
+ // pointer from the smart pointer is safe in this case.
+ LLCore::HttpHandle hhandle = request->requestPost(mPolicyId, mPriority, url, rawbody.get(),
+ options, headers, handler.get());
+
+ if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
+ {
+ return HttpCoroutineAdapter::buildImmediateErrorResult(request, url);
+ }
+
+ saveState(hhandle, request, handler);
+ LLSD results = llcoro::waitForEventOn(handler->getReplyPump());
+ cleanState();
+
+ return results;
+}
+
+LLSD HttpCoroutineAdapter::putAndYield(LLCore::HttpRequest::ptr_t request,
+ const std::string & url, const LLSD & body,
+ LLCore::HttpOptions::ptr_t options, LLCore::HttpHeaders::ptr_t headers)
+{
+ LLEventStream replyPump(mAdapterName + "Reply", true);
+ HttpCoroHandler::ptr_t httpHandler = HttpCoroHandler::ptr_t(new HttpCoroLLSDHandler(replyPump));
+
+ return putAndYield_(request, url, body, options, headers, httpHandler);
+}
+
+LLSD HttpCoroutineAdapter::putAndYield_(LLCore::HttpRequest::ptr_t &request,
+ const std::string & url, const LLSD & body,
+ LLCore::HttpOptions::ptr_t &options, LLCore::HttpHeaders::ptr_t &headers,
+ HttpCoroHandler::ptr_t &handler)
+{
+ HttpRequestPumper pumper(request);
+
+ checkDefaultHeaders(headers);
+
+ // The HTTPCoroHandler does not self delete, so retrieval of a the contained
+ // pointer from the smart pointer is safe in this case.
+ LLCore::HttpHandle hhandle = requestPutWithLLSD(request,
+ mPolicyId, mPriority, url, body, options, headers,
+ handler.get());
+
+ if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
+ {
+ return HttpCoroutineAdapter::buildImmediateErrorResult(request, url);
+ }
+
+ saveState(hhandle, request, handler);
+ LLSD results = llcoro::waitForEventOn(handler->getReplyPump());
+ cleanState();
+
+ return results;
+}
+
+LLSD HttpCoroutineAdapter::getAndYield(LLCore::HttpRequest::ptr_t request,
+ const std::string & url,
+ LLCore::HttpOptions::ptr_t options, LLCore::HttpHeaders::ptr_t headers)
+{
+ LLEventStream replyPump(mAdapterName + "Reply", true);
+ HttpCoroHandler::ptr_t httpHandler = HttpCoroHandler::ptr_t(new HttpCoroLLSDHandler(replyPump));
+
+ return getAndYield_(request, url, options, headers, httpHandler);
+}
+
+LLSD HttpCoroutineAdapter::getRawAndYield(LLCore::HttpRequest::ptr_t request,
+ const std::string & url,
+ LLCore::HttpOptions::ptr_t options, LLCore::HttpHeaders::ptr_t headers)
+{
+ LLEventStream replyPump(mAdapterName + "Reply", true);
+ HttpCoroHandler::ptr_t httpHandler = HttpCoroHandler::ptr_t(new HttpCoroRawHandler(replyPump));
+
+ return getAndYield_(request, url, options, headers, httpHandler);
+}
+
+LLSD HttpCoroutineAdapter::getJsonAndYield(LLCore::HttpRequest::ptr_t request,
+ const std::string & url, LLCore::HttpOptions::ptr_t options, LLCore::HttpHeaders::ptr_t headers)
+{
+ LLEventStream replyPump(mAdapterName + "Reply", true);
+ HttpCoroHandler::ptr_t httpHandler = HttpCoroHandler::ptr_t(new HttpCoroJSONHandler(replyPump));
+
+ return getAndYield_(request, url, options, headers, httpHandler);
+}
+
+
+LLSD HttpCoroutineAdapter::getAndYield_(LLCore::HttpRequest::ptr_t &request,
+ const std::string & url,
+ LLCore::HttpOptions::ptr_t &options, LLCore::HttpHeaders::ptr_t &headers,
+ HttpCoroHandler::ptr_t &handler)
+{
+ HttpRequestPumper pumper(request);
+ checkDefaultHeaders(headers);
+
+ // The HTTPCoroHandler does not self delete, so retrieval of a the contained
+ // pointer from the smart pointer is safe in this case.
+ LLCore::HttpHandle hhandle = request->requestGet(mPolicyId, mPriority,
+ url, options, headers, handler.get());
+
+ if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
+ {
+ return HttpCoroutineAdapter::buildImmediateErrorResult(request, url);
+ }
+
+ saveState(hhandle, request, handler);
+ LLSD results = llcoro::waitForEventOn(handler->getReplyPump());
+ cleanState();
+
+ return results;
+}
+
+
+LLSD HttpCoroutineAdapter::deleteAndYield(LLCore::HttpRequest::ptr_t request,
+ const std::string & url,
+ LLCore::HttpOptions::ptr_t options, LLCore::HttpHeaders::ptr_t headers)
+{
+ LLEventStream replyPump(mAdapterName + "Reply", true);
+ HttpCoroHandler::ptr_t httpHandler = HttpCoroHandler::ptr_t(new HttpCoroLLSDHandler(replyPump));
+
+ return deleteAndYield_(request, url, options, headers, httpHandler);
+}
+
+LLSD HttpCoroutineAdapter::deleteAndYield_(LLCore::HttpRequest::ptr_t &request,
+ const std::string & url, LLCore::HttpOptions::ptr_t &options,
+ LLCore::HttpHeaders::ptr_t &headers, HttpCoroHandler::ptr_t &handler)
+{
+ HttpRequestPumper pumper(request);
+
+ checkDefaultHeaders(headers);
+ // The HTTPCoroHandler does not self delete, so retrieval of a the contained
+ // pointer from the smart pointer is safe in this case.
+ LLCore::HttpHandle hhandle = request->requestDelete(mPolicyId, mPriority,
+ url, options, headers, handler.get());
+
+ if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
+ {
+ return HttpCoroutineAdapter::buildImmediateErrorResult(request, url);
+ }
+
+ saveState(hhandle, request, handler);
+ LLSD results = llcoro::waitForEventOn(handler->getReplyPump());
+ cleanState();
+
+ return results;
+}
+
+LLSD HttpCoroutineAdapter::patchAndYield(LLCore::HttpRequest::ptr_t request,
+ const std::string & url, const LLSD & body,
+ LLCore::HttpOptions::ptr_t options, LLCore::HttpHeaders::ptr_t headers)
+{
+ LLEventStream replyPump(mAdapterName + "Reply", true);
+ HttpCoroHandler::ptr_t httpHandler = HttpCoroHandler::ptr_t(new HttpCoroLLSDHandler(replyPump));
+
+ return patchAndYield_(request, url, body, options, headers, httpHandler);
+}
+
+
+LLSD HttpCoroutineAdapter::patchAndYield_(LLCore::HttpRequest::ptr_t &request,
+ const std::string & url, const LLSD & body,
+ LLCore::HttpOptions::ptr_t &options, LLCore::HttpHeaders::ptr_t &headers,
+ HttpCoroHandler::ptr_t &handler)
+{
+ HttpRequestPumper pumper(request);
+
+ checkDefaultHeaders(headers);
+
+ // The HTTPCoroHandler does not self delete, so retrieval of a the contained
+ // pointer from the smart pointer is safe in this case.
+ LLCore::HttpHandle hhandle = requestPatchWithLLSD(request,
+ mPolicyId, mPriority, url, body, options, headers,
+ handler.get());
+
+ if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
+ {
+ return HttpCoroutineAdapter::buildImmediateErrorResult(request, url);
+ }
+
+ saveState(hhandle, request, handler);
+ LLSD results = llcoro::waitForEventOn(handler->getReplyPump());
+ cleanState();
+
+ return results;
+}
+
+LLSD HttpCoroutineAdapter::copyAndYield(LLCore::HttpRequest::ptr_t request,
+ const std::string & url, const std::string dest,
+ LLCore::HttpOptions::ptr_t options, LLCore::HttpHeaders::ptr_t headers)
+{
+ LLEventStream replyPump(mAdapterName + "Reply", true);
+ HttpCoroHandler::ptr_t httpHandler = HttpCoroHandler::ptr_t(new HttpCoroLLSDHandler(replyPump));
+
+ if (!headers)
+ headers.reset(new LLCore::HttpHeaders);
+ headers->append(HTTP_OUT_HEADER_DESTINATION, dest);
+
+ return copyAndYield_(request, url, options, headers, httpHandler);
+}
+
+
+LLSD HttpCoroutineAdapter::copyAndYield_(LLCore::HttpRequest::ptr_t &request,
+ const std::string & url,
+ LLCore::HttpOptions::ptr_t &options, LLCore::HttpHeaders::ptr_t &headers,
+ HttpCoroHandler::ptr_t &handler)
+{
+ HttpRequestPumper pumper(request);
+
+ checkDefaultHeaders(headers);
+
+ // The HTTPCoroHandler does not self delete, so retrieval of a the contained
+ // pointer from the smart pointer is safe in this case.
+ //
+ LLCore::HttpHandle hhandle = request->requestCopy(mPolicyId, mPriority, url,
+ options, headers, handler.get());
+
+ if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
+ {
+ return HttpCoroutineAdapter::buildImmediateErrorResult(request, url);
+ }
+
+ saveState(hhandle, request, handler);
+ LLSD results = llcoro::waitForEventOn(handler->getReplyPump());
+ cleanState();
+
+ return results;
+}
+
+LLSD HttpCoroutineAdapter::moveAndYield(LLCore::HttpRequest::ptr_t request,
+ const std::string & url, const std::string dest,
+ LLCore::HttpOptions::ptr_t options, LLCore::HttpHeaders::ptr_t headers)
+{
+ LLEventStream replyPump(mAdapterName + "Reply", true);
+ HttpCoroHandler::ptr_t httpHandler = HttpCoroHandler::ptr_t(new HttpCoroLLSDHandler(replyPump));
+
+ if (!headers)
+ headers.reset(new LLCore::HttpHeaders);
+ headers->append(HTTP_OUT_HEADER_DESTINATION, dest);
+
+ return moveAndYield_(request, url, options, headers, httpHandler);
+}
+
+
+LLSD HttpCoroutineAdapter::moveAndYield_(LLCore::HttpRequest::ptr_t &request,
+ const std::string & url,
+ LLCore::HttpOptions::ptr_t &options, LLCore::HttpHeaders::ptr_t &headers,
+ HttpCoroHandler::ptr_t &handler)
+{
+ HttpRequestPumper pumper(request);
+
+ checkDefaultHeaders(headers);
+
+ // The HTTPCoroHandler does not self delete, so retrieval of a the contained
+ // pointer from the smart pointer is safe in this case.
+ //
+ LLCore::HttpHandle hhandle = request->requestMove(mPolicyId, mPriority, url,
+ options, headers, handler.get());
+
+ if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
+ {
+ return HttpCoroutineAdapter::buildImmediateErrorResult(request, url);
+ }
+
+ saveState(hhandle, request, handler);
+ LLSD results = llcoro::waitForEventOn(handler->getReplyPump());
+ cleanState();
+
+ return results;
+}
+
+
+void HttpCoroutineAdapter::checkDefaultHeaders(LLCore::HttpHeaders::ptr_t &headers)
+{
+ if (!headers)
+ headers.reset(new LLCore::HttpHeaders);
+ if (!headers->find(HTTP_OUT_HEADER_ACCEPT))
+ {
+ headers->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_LLSD_XML);
+ }
+ if (!headers->find(HTTP_OUT_HEADER_CONTENT_TYPE))
+ {
+ headers->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_LLSD_XML);
+ }
+
+ if (!headers->find("X-SecondLife-UDP-Listen-Port") && gMessageSystem)
+ {
+ headers->append("X-SecondLife-UDP-Listen-Port", llformat("%d", gMessageSystem->mPort));
+ }
+}
+
+
+void HttpCoroutineAdapter::cancelYieldingOperation()
+{
+ LLCore::HttpRequest::ptr_t request = mWeakRequest.lock();
+ HttpCoroHandler::ptr_t handler = mWeakHandler.lock();
+ if ((request) && (handler) && (mYieldingHandle != LLCORE_HTTP_HANDLE_INVALID))
+ {
+ cleanState();
+ LL_INFOS() << "Canceling yielding request!" << LL_ENDL;
+ request->requestCancel(mYieldingHandle, handler.get());
+ }
+}
+
+void HttpCoroutineAdapter::saveState(LLCore::HttpHandle yieldingHandle,
+ LLCore::HttpRequest::ptr_t &request, HttpCoroHandler::ptr_t &handler)
+{
+ mWeakRequest = request;
+ mWeakHandler = handler;
+ mYieldingHandle = yieldingHandle;
+}
+
+void HttpCoroutineAdapter::cleanState()
+{
+ mWeakRequest.reset();
+ mWeakHandler.reset();
+ mYieldingHandle = LLCORE_HTTP_HANDLE_INVALID;
+}
+
+/*static*/
+LLSD HttpCoroutineAdapter::buildImmediateErrorResult(const LLCore::HttpRequest::ptr_t &request,
+ const std::string &url)
+{
+ LLCore::HttpStatus status = request->getStatus();
+ LL_WARNS() << "Error posting to " << url << " Status=" << status.getStatus() <<
+ " message = " << status.getMessage() << LL_ENDL;
+
+ // Mimic the status results returned from an http error that we had
+ // to wait on
+ LLSD httpresults = LLSD::emptyMap();
+
+ HttpCoroHandler::writeStatusCodes(status, url, httpresults);
+
+ LLSD errorres = LLSD::emptyMap();
+ errorres["http_result"] = httpresults;
+
+ return errorres;
+}
+
+/*static*/
+LLCore::HttpStatus HttpCoroutineAdapter::getStatusFromLLSD(const LLSD &httpResults)
+{
+ LLCore::HttpStatus::type_enum_t type = static_cast<LLCore::HttpStatus::type_enum_t>(httpResults[HttpCoroutineAdapter::HTTP_RESULTS_TYPE].asInteger());
+ short code = static_cast<short>(httpResults[HttpCoroutineAdapter::HTTP_RESULTS_STATUS].asInteger());
+
+ return LLCore::HttpStatus(type, code);
+}
+
+/*static*/
+void HttpCoroutineAdapter::callbackHttpGet(const std::string &url, LLCore::HttpRequest::policy_t policyId, completionCallback_t success, completionCallback_t failure)
+{
+ LLCoros::instance().launch("HttpCoroutineAdapter::genericGetCoro",
+ boost::bind(&HttpCoroutineAdapter::trivialGetCoro, url, policyId, success, failure));
+}
+
+/*static*/
+void HttpCoroutineAdapter::messageHttpGet(const std::string &url, const std::string &success, const std::string &failure)
+{
+ completionCallback_t cbSuccess = (success.empty()) ? NULL :
+ static_cast<completionCallback_t>(boost::bind(&logMessageSuccess, "HttpCoroutineAdapter", url, success));
+ completionCallback_t cbFailure = (failure.empty()) ? NULL :
+ static_cast<completionCallback_t>(boost::bind(&logMessageFail, "HttpCoroutineAdapter", url, failure));
+ callbackHttpGet(url, cbSuccess, cbFailure);
+}
+
+/*static*/
+void HttpCoroutineAdapter::trivialGetCoro(std::string url, LLCore::HttpRequest::policy_t policyId, completionCallback_t success, completionCallback_t failure)
+{
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+ httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("genericGetCoro", policyId));
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+ LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+
+ httpOpts->setWantHeaders(true);
+
+ LL_INFOS("HttpCoroutineAdapter", "genericGetCoro") << "Generic GET for " << url << LL_ENDL;
+
+ LLSD result = httpAdapter->getAndYield(httpRequest, url, httpOpts);
+
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+ if (!status)
+ {
+ if (failure)
+ {
+ failure(httpResults);
+ }
+ }
+ else
+ {
+ if (success)
+ {
+ success(result);
+ }
+ }
+}
+
+/*static*/
+void HttpCoroutineAdapter::callbackHttpPost(const std::string &url, LLCore::HttpRequest::policy_t policyId, const LLSD &postData, completionCallback_t success, completionCallback_t failure)
+{
+ LLCoros::instance().launch("HttpCoroutineAdapter::genericPostCoro",
+ boost::bind(&HttpCoroutineAdapter::trivialPostCoro, url, policyId, postData, success, failure));
+}
+
+/*static*/
+void HttpCoroutineAdapter::messageHttpPost(const std::string &url, const LLSD &postData, const std::string &success, const std::string &failure)
+{
+ completionCallback_t cbSuccess = (success.empty()) ? NULL :
+ static_cast<completionCallback_t>(boost::bind(&logMessageSuccess, "HttpCoroutineAdapter", url, success));
+ completionCallback_t cbFailure = (failure.empty()) ? NULL :
+ static_cast<completionCallback_t>(boost::bind(&logMessageFail, "HttpCoroutineAdapter", url, failure));
+
+ callbackHttpPost(url, postData, cbSuccess, cbFailure);
}
+/*static*/
+void HttpCoroutineAdapter::trivialPostCoro(std::string url, LLCore::HttpRequest::policy_t policyId, LLSD postData, completionCallback_t success, completionCallback_t failure)
+{
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+ httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("genericPostCoro", policyId));
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+ LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+
+ httpOpts->setWantHeaders(true);
+
+ LL_INFOS("HttpCoroutineAdapter", "genericPostCoro") << "Generic POST for " << url << LL_ENDL;
+
+ LLSD result = httpAdapter->postAndYield(httpRequest, url, postData, httpOpts);
+
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+ if (!status)
+ {
+ // If a failure routine is provided do it.
+ if (failure)
+ {
+ failure(httpResults);
+ }
+ }
+ else
+ {
+ // If a success routine is provided do it.
+ if (success)
+ {
+ success(result);
+ }
+ }
+}
+
+
} // end namespace LLCoreHttpUtil
diff --git a/indra/llmessage/llcorehttputil.h b/indra/llmessage/llcorehttputil.h
index d40172bc7a..31a73bb900 100644
--- a/indra/llmessage/llcorehttputil.h
+++ b/indra/llmessage/llcorehttputil.h
@@ -36,9 +36,15 @@
#include "httpheaders.h"
#include "httpoptions.h"
#include "httphandler.h"
+#include "llhttpconstants.h" // *TODO: move to llcorehttp
#include "bufferarray.h"
#include "bufferstream.h"
#include "llsd.h"
+#include "llevents.h"
+#include "llcoros.h"
+#include "lleventcoro.h"
+#include "llassettype.h"
+#include "lluuid.h"
///
/// The base llcorehttp library implements many HTTP idioms
@@ -101,15 +107,505 @@ std::string responseToString(LLCore::HttpResponse * response);
/// a now-useless HttpHandler object.
///
LLCore::HttpHandle requestPostWithLLSD(LLCore::HttpRequest * request,
- LLCore::HttpRequest::policy_t policy_id,
- LLCore::HttpRequest::priority_t priority,
- const std::string & url,
- const LLSD & body,
- LLCore::HttpOptions * options,
- LLCore::HttpHeaders * headers,
- LLCore::HttpHandler * handler);
+ LLCore::HttpRequest::policy_t policy_id,
+ LLCore::HttpRequest::priority_t priority,
+ const std::string & url,
+ const LLSD & body,
+ const LLCore::HttpOptions::ptr_t &options,
+ const LLCore::HttpHeaders::ptr_t &headers,
+ LLCore::HttpHandler * handler);
-} // end namespace LLCoreHttpUtil
+inline LLCore::HttpHandle requestPostWithLLSD(LLCore::HttpRequest::ptr_t & request,
+ LLCore::HttpRequest::policy_t policy_id,
+ LLCore::HttpRequest::priority_t priority,
+ const std::string & url,
+ const LLSD & body,
+ const LLCore::HttpOptions::ptr_t & options,
+ const LLCore::HttpHeaders::ptr_t & headers,
+ LLCore::HttpHandler * handler)
+{
+ return requestPostWithLLSD(request.get(), policy_id, priority,
+ url, body, options, headers, handler);
+}
+
+inline LLCore::HttpHandle requestPostWithLLSD(LLCore::HttpRequest::ptr_t & request,
+ LLCore::HttpRequest::policy_t policy_id,
+ LLCore::HttpRequest::priority_t priority,
+ const std::string & url,
+ const LLSD & body,
+ LLCore::HttpHandler * handler)
+{
+ LLCore::HttpOptions::ptr_t options;
+ LLCore::HttpHeaders::ptr_t headers;
+
+ return requestPostWithLLSD(request.get(), policy_id, priority,
+ url, body, options, headers, handler);
+}
+
+
+/// Issue a standard HttpRequest::requestPut() call but using
+/// and LLSD object as the request body. Conventions are the
+/// same as with that method. Caller is expected to provide
+/// an HttpHeaders object with a correct 'Content-Type:' header.
+/// One will not be provided by this call.
+///
+/// @return If request is successfully issued, the
+/// HttpHandle representing the request.
+/// On error, LLCORE_HTTP_HANDLE_INVALID
+/// is returned and caller can fetch detailed
+/// status with the getStatus() method on the
+/// request object. In case of error, no
+/// request is queued and caller may need to
+/// perform additional cleanup such as freeing
+/// a now-useless HttpHandler object.
+///
+LLCore::HttpHandle requestPutWithLLSD(LLCore::HttpRequest * request,
+ LLCore::HttpRequest::policy_t policy_id,
+ LLCore::HttpRequest::priority_t priority,
+ const std::string & url,
+ const LLSD & body,
+ const LLCore::HttpOptions::ptr_t &options,
+ const LLCore::HttpHeaders::ptr_t &headers,
+ LLCore::HttpHandler * handler);
+
+inline LLCore::HttpHandle requestPutWithLLSD(LLCore::HttpRequest::ptr_t & request,
+ LLCore::HttpRequest::policy_t policy_id,
+ LLCore::HttpRequest::priority_t priority,
+ const std::string & url,
+ const LLSD & body,
+ const LLCore::HttpOptions::ptr_t & options,
+ const LLCore::HttpHeaders::ptr_t & headers,
+ LLCore::HttpHandler * handler)
+{
+ return requestPutWithLLSD(request.get(), policy_id, priority,
+ url, body, options, headers, handler);
+}
+
+inline LLCore::HttpHandle requestPutWithLLSD(LLCore::HttpRequest::ptr_t & request,
+ LLCore::HttpRequest::policy_t policy_id,
+ LLCore::HttpRequest::priority_t priority,
+ const std::string & url,
+ const LLSD & body,
+ LLCore::HttpHandler * handler)
+{
+ LLCore::HttpOptions::ptr_t options;
+ LLCore::HttpHeaders::ptr_t headers;
+
+ return requestPutWithLLSD(request.get(), policy_id, priority,
+ url, body, options, headers, handler);
+}
+
+/// Issue a standard HttpRequest::requestPatch() call but using
+/// and LLSD object as the request body. Conventions are the
+/// same as with that method. Caller is expected to provide
+/// an HttpHeaders object with a correct 'Content-Type:' header.
+/// One will not be provided by this call.
+///
+/// @return If request is successfully issued, the
+/// HttpHandle representing the request.
+/// On error, LLCORE_HTTP_HANDLE_INVALID
+/// is returned and caller can fetch detailed
+/// status with the getStatus() method on the
+/// request object. In case of error, no
+/// request is queued and caller may need to
+/// perform additional cleanup such as freeing
+/// a now-useless HttpHandler object.
+///
+LLCore::HttpHandle requestPatchWithLLSD(LLCore::HttpRequest * request,
+ LLCore::HttpRequest::policy_t policy_id,
+ LLCore::HttpRequest::priority_t priority,
+ const std::string & url,
+ const LLSD & body,
+ const LLCore::HttpOptions::ptr_t &options,
+ const LLCore::HttpHeaders::ptr_t &headers,
+ LLCore::HttpHandler * handler);
+
+inline LLCore::HttpHandle requestPatchWithLLSD(LLCore::HttpRequest::ptr_t & request,
+ LLCore::HttpRequest::policy_t policy_id,
+ LLCore::HttpRequest::priority_t priority,
+ const std::string & url,
+ const LLSD & body,
+ const LLCore::HttpOptions::ptr_t & options,
+ const LLCore::HttpHeaders::ptr_t & headers,
+ LLCore::HttpHandler * handler)
+{
+ return requestPatchWithLLSD(request.get(), policy_id, priority,
+ url, body, options, headers, handler);
+}
+
+inline LLCore::HttpHandle requestPatchWithLLSD(LLCore::HttpRequest::ptr_t & request,
+ LLCore::HttpRequest::policy_t policy_id,
+ LLCore::HttpRequest::priority_t priority,
+ const std::string & url,
+ const LLSD & body,
+ LLCore::HttpHandler * handler)
+{
+ LLCore::HttpOptions::ptr_t options;
+ LLCore::HttpHeaders::ptr_t headers;
+
+ return requestPatchWithLLSD(request.get(), policy_id, priority,
+ url, body, options, headers, handler);
+}
+
+//=========================================================================
+/// The HttpCoroHandler is a specialization of the LLCore::HttpHandler for
+/// interacting with coroutines. When the request is completed the response
+/// will be posted onto the supplied Event Pump.
+///
+/// The LLSD posted back to the coroutine will have the following additions:
+/// llsd["http_result"] -+- ["message"] - An error message returned from the HTTP status
+/// +- ["status"] - The status code associated with the HTTP call
+/// +- ["success"] - Success of failure of the HTTP call and LLSD parsing.
+/// +- ["type"] - The LLCore::HttpStatus type associted with the HTTP call
+/// +- ["url"] - The URL used to make the call.
+/// +- ["headers"] - A map of name name value pairs with the HTTP headers.
+///
+class HttpCoroHandler : public LLCore::HttpHandler
+{
+public:
+
+ typedef boost::shared_ptr<HttpCoroHandler> ptr_t;
+ typedef boost::weak_ptr<HttpCoroHandler> wptr_t;
+
+ HttpCoroHandler(LLEventStream &reply);
+
+ static void writeStatusCodes(LLCore::HttpStatus status, const std::string &url, LLSD &result);
+ virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response);
+
+ inline LLEventStream &getReplyPump()
+ {
+ return mReplyPump;
+ }
+
+protected:
+ /// this method may modify the status value
+ virtual LLSD handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status) = 0;
+
+private:
+ void buildStatusEntry(LLCore::HttpResponse *response, LLCore::HttpStatus status, LLSD &result);
+
+ LLEventStream &mReplyPump;
+};
+
+//=========================================================================
+/// An adapter to handle some of the boilerplate code surrounding HTTP and coroutine
+/// interaction.
+///
+/// Construct an HttpCoroutineAdapter giving it a name and policy Id. After
+/// any application specific setup call the post, put or get method. The request
+/// will be automatically pumped and the method will return with an LLSD describing
+/// the result of the operation. See HttpCoroHandler for a description of the
+/// decoration done to the returned LLSD.
+///
+/// Posting through the adapter will automatically add the following headers to
+/// the request if they have not been previously specified in a supplied
+/// HttpHeaders object:
+/// "Accept=application/llsd+xml"
+/// "X-SecondLife-UDP-Listen-Port=###"
+///
+class HttpCoroutineAdapter
+{
+public:
+ static const std::string HTTP_RESULTS;
+ static const std::string HTTP_RESULTS_SUCCESS;
+ static const std::string HTTP_RESULTS_TYPE;
+ static const std::string HTTP_RESULTS_STATUS;
+ static const std::string HTTP_RESULTS_MESSAGE;
+ static const std::string HTTP_RESULTS_URL;
+ static const std::string HTTP_RESULTS_HEADERS;
+ static const std::string HTTP_RESULTS_CONTENT;
+ static const std::string HTTP_RESULTS_RAW;
+
+ typedef boost::shared_ptr<HttpCoroutineAdapter> ptr_t;
+ typedef boost::weak_ptr<HttpCoroutineAdapter> wptr_t;
+
+ HttpCoroutineAdapter(const std::string &name, LLCore::HttpRequest::policy_t policyId,
+ LLCore::HttpRequest::priority_t priority = 0L);
+ ~HttpCoroutineAdapter();
+
+ /// Execute a Post transaction on the supplied URL and yield execution of
+ /// the coroutine until a result is available.
+ ///
+ /// @Note: the request's smart pointer is passed by value so that it will
+ /// not be deallocated during the yield.
+ LLSD postAndYield(LLCore::HttpRequest::ptr_t request,
+ const std::string & url, const LLSD & body,
+ LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+ LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders()));
+ LLSD postAndYield(LLCore::HttpRequest::ptr_t request,
+ const std::string & url, LLCore::BufferArray::ptr_t rawbody,
+ LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+ LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders()));
+ LLSD postAndYield(LLCore::HttpRequest::ptr_t &request,
+ const std::string & url, const LLSD & body,
+ LLCore::HttpHeaders::ptr_t &headers)
+ {
+ return postAndYield(request, url, body,
+ LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()), headers);
+ }
+
+ LLSD postAndYield(LLCore::HttpRequest::ptr_t &request,
+ const std::string & url, LLCore::BufferArray::ptr_t &rawbody,
+ LLCore::HttpHeaders::ptr_t &headers)
+ {
+ return postAndYield(request, url, rawbody,
+ LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()), headers);
+ }
+
+ LLSD postRawAndYield(LLCore::HttpRequest::ptr_t request,
+ const std::string & url, LLCore::BufferArray::ptr_t rawbody,
+ LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+ LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders()));
+
+ LLSD postRawAndYield(LLCore::HttpRequest::ptr_t &request,
+ const std::string & url, LLCore::BufferArray::ptr_t &rawbody,
+ LLCore::HttpHeaders::ptr_t &headers)
+ {
+ return postRawAndYield(request, url, rawbody,
+ LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()), headers);
+ }
+
+ LLSD postFileAndYield(LLCore::HttpRequest::ptr_t request,
+ const std::string & url, std::string fileName,
+ LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+ LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders()));
+
+ LLSD postFileAndYield(LLCore::HttpRequest::ptr_t &request,
+ const std::string & url, std::string fileName,
+ LLCore::HttpHeaders::ptr_t &headers)
+ {
+ return postFileAndYield(request, url, fileName,
+ LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()), headers);
+ }
+
+
+ LLSD postFileAndYield(LLCore::HttpRequest::ptr_t request,
+ const std::string & url, LLUUID assetId, LLAssetType::EType assetType,
+ LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+ LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders()));
+
+ LLSD postFileAndYield(LLCore::HttpRequest::ptr_t request,
+ const std::string & url, LLUUID assetId, LLAssetType::EType assetType,
+ LLCore::HttpHeaders::ptr_t &headers)
+ {
+ return postFileAndYield(request, url, assetId, assetType,
+ LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()), headers);
+ }
+
+
+ /// Execute a Put transaction on the supplied URL and yield execution of
+ /// the coroutine until a result is available.
+ ///
+ /// @Note: the request's smart pointer is passed by value so that it will
+ /// not be deallocated during the yield.
+ LLSD putAndYield(LLCore::HttpRequest::ptr_t request,
+ const std::string & url, const LLSD & body,
+ LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+ LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders()));
+
+ /// Execute a Get transaction on the supplied URL and yield execution of
+ /// the coroutine until a result is available.
+ ///
+ /// @Note: the request's smart pointer is passed by value so that it will
+ /// not be deallocated during the yield.
+ LLSD getAndYield(LLCore::HttpRequest::ptr_t request,
+ const std::string & url,
+ LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+ LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders()));
+ LLSD getAndYield(LLCore::HttpRequest::ptr_t &request,
+ const std::string & url, LLCore::HttpHeaders::ptr_t &headers)
+ {
+ return getAndYield(request, url,
+ LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+ headers);
+ }
+
+ LLSD getRawAndYield(LLCore::HttpRequest::ptr_t request,
+ const std::string & url,
+ LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+ LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders()));
+ LLSD getRawAndYield(LLCore::HttpRequest::ptr_t &request,
+ const std::string & url, LLCore::HttpHeaders::ptr_t &headers)
+ {
+ return getRawAndYield(request, url,
+ LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+ headers);
+ }
+
+ LLSD getJsonAndYield(LLCore::HttpRequest::ptr_t request,
+ const std::string & url,
+ LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+ LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders()));
+ LLSD getJsonndYield(LLCore::HttpRequest::ptr_t &request,
+ const std::string & url, LLCore::HttpHeaders::ptr_t &headers)
+ {
+ return getJsonAndYield(request, url,
+ LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+ headers);
+ }
+
+
+ /// Execute a DELETE transaction on the supplied URL and yield execution of
+ /// the coroutine until a result is available.
+ ///
+ /// @Note: the request's smart pointer is passed by value so that it will
+ /// not be deallocated during the yield.
+ LLSD deleteAndYield(LLCore::HttpRequest::ptr_t request,
+ const std::string & url,
+ LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+ LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders()));
+
+
+ /// Execute a PATCH transaction on the supplied URL and yield execution of
+ /// the coroutine until a result is available.
+ ///
+ /// @Note: the request's smart pointer is passed by value so that it will
+ /// not be deallocated during the yield.
+ LLSD patchAndYield(LLCore::HttpRequest::ptr_t request,
+ const std::string & url, const LLSD & body,
+ LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+ LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders()));
+ LLSD patchAndYield(LLCore::HttpRequest::ptr_t &request,
+ const std::string & url, const LLSD & body,
+ LLCore::HttpHeaders::ptr_t &headers)
+ {
+ return patchAndYield(request, url, body,
+ LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()), headers);
+ }
+
+ /// Execute a COPY transaction on the supplied URL and yield execution of
+ /// the coroutine until a result is available.
+ ///
+ /// @Note: The destination is passed through the HTTP pipe as a header
+ /// The header used is defined as: HTTP_OUT_HEADER_DESTINATION("Destination");
+ ///
+ /// @Note: the request's smart pointer is passed by value so that it will
+ /// not be deallocated during the yield.
+ LLSD copyAndYield(LLCore::HttpRequest::ptr_t request,
+ const std::string & url, const std::string dest,
+ LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+ LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders()));
+ LLSD copyAndYield(LLCore::HttpRequest::ptr_t &request,
+ const std::string & url, const std::string & dest,
+ LLCore::HttpHeaders::ptr_t &headers)
+ {
+ return copyAndYield(request, url, dest,
+ LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()), headers);
+ }
+
+ /// Execute a MOVE transaction on the supplied URL and yield execution of
+ /// the coroutine until a result is available.
+ ///
+ /// @Note: The destination is passed through the HTTP pipe in the headers.
+ /// The header used is defined as: HTTP_OUT_HEADER_DESTINATION("Destination");
+ ///
+ /// @Note: the request's smart pointer is passed by value so that it will
+ /// not be deallocated during the yield.
+ LLSD moveAndYield(LLCore::HttpRequest::ptr_t request,
+ const std::string & url, const std::string dest,
+ LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+ LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders()));
+ LLSD moveAndYield(LLCore::HttpRequest::ptr_t &request,
+ const std::string & url, const std::string & dest,
+ LLCore::HttpHeaders::ptr_t &headers)
+ {
+ return moveAndYield(request, url, dest,
+ LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()), headers);
+ }
+
+ ///
+ void cancelYieldingOperation();
+
+ static LLCore::HttpStatus getStatusFromLLSD(const LLSD &httpResults);
+
+ /// The convenience routines below can be provided with callback functors
+ /// which will be invoked in the case of success or failure. These callbacks
+ /// should match this form.
+ /// @sa callbackHttpGet
+ /// @sa callbackHttpPost
+ typedef boost::function<void(const LLSD &)> completionCallback_t;
+
+ static void callbackHttpGet(const std::string &url, LLCore::HttpRequest::policy_t policyId, completionCallback_t success = NULL, completionCallback_t failure = NULL);
+ static void callbackHttpGet(const std::string &url, completionCallback_t success = NULL, completionCallback_t failure = NULL)
+ {
+ callbackHttpGet(url, LLCore::HttpRequest::DEFAULT_POLICY_ID, success, failure);
+ }
+ static void callbackHttpPost(const std::string &url, LLCore::HttpRequest::policy_t policyId, const LLSD &postData, completionCallback_t success = NULL, completionCallback_t failure = NULL);
+ static void callbackHttpPost(const std::string &url, const LLSD &postData, completionCallback_t success = NULL, completionCallback_t failure = NULL)
+ {
+ callbackHttpPost(url, LLCore::HttpRequest::DEFAULT_POLICY_ID, postData, success, failure);
+ }
+
+ /// Generic Get and post routines for HTTP via coroutines.
+ /// These static methods do all required setup for the GET or POST operation.
+ /// When the operation completes successfully they will put the success message in the log at INFO level,
+ /// If the operation fails the failure message is written to the log at WARN level.
+ ///
+ static void messageHttpGet(const std::string &url, const std::string &success = std::string(), const std::string &failure = std::string());
+ static void messageHttpPost(const std::string &url, const LLSD &postData, const std::string &success, const std::string &failure);
+
+
+private:
+ static LLSD buildImmediateErrorResult(const LLCore::HttpRequest::ptr_t &request, const std::string &url);
+
+ void saveState(LLCore::HttpHandle yieldingHandle, LLCore::HttpRequest::ptr_t &request,
+ HttpCoroHandler::ptr_t &handler);
+ void cleanState();
+
+ LLSD postAndYield_(LLCore::HttpRequest::ptr_t &request,
+ const std::string & url, const LLSD & body,
+ LLCore::HttpOptions::ptr_t &options, LLCore::HttpHeaders::ptr_t &headers,
+ HttpCoroHandler::ptr_t &handler);
+
+ LLSD postAndYield_(LLCore::HttpRequest::ptr_t &request,
+ const std::string & url, LLCore::BufferArray::ptr_t &rawbody,
+ LLCore::HttpOptions::ptr_t &options, LLCore::HttpHeaders::ptr_t &headers,
+ HttpCoroHandler::ptr_t &handler);
+
+ LLSD putAndYield_(LLCore::HttpRequest::ptr_t &request,
+ const std::string & url, const LLSD & body,
+ LLCore::HttpOptions::ptr_t &options, LLCore::HttpHeaders::ptr_t &headers,
+ HttpCoroHandler::ptr_t &handler);
+
+ LLSD getAndYield_(LLCore::HttpRequest::ptr_t &request,
+ const std::string & url, LLCore::HttpOptions::ptr_t &options,
+ LLCore::HttpHeaders::ptr_t &headers, HttpCoroHandler::ptr_t &handler);
+
+ LLSD deleteAndYield_(LLCore::HttpRequest::ptr_t &request,
+ const std::string & url, LLCore::HttpOptions::ptr_t &options,
+ LLCore::HttpHeaders::ptr_t &headers, HttpCoroHandler::ptr_t &handler);
+
+ LLSD patchAndYield_(LLCore::HttpRequest::ptr_t &request,
+ const std::string & url, const LLSD & body,
+ LLCore::HttpOptions::ptr_t &options, LLCore::HttpHeaders::ptr_t &headers,
+ HttpCoroHandler::ptr_t &handler);
+
+ LLSD copyAndYield_(LLCore::HttpRequest::ptr_t &request,
+ const std::string & url,
+ LLCore::HttpOptions::ptr_t &options, LLCore::HttpHeaders::ptr_t &headers,
+ HttpCoroHandler::ptr_t &handler);
+
+ LLSD moveAndYield_(LLCore::HttpRequest::ptr_t &request,
+ const std::string & url,
+ LLCore::HttpOptions::ptr_t &options, LLCore::HttpHeaders::ptr_t &headers,
+ HttpCoroHandler::ptr_t &handler);
+
+ static void trivialGetCoro(std::string url, LLCore::HttpRequest::policy_t policyId, completionCallback_t success, completionCallback_t failure);
+ static void trivialPostCoro(std::string url, LLCore::HttpRequest::policy_t policyId, LLSD postData, completionCallback_t success, completionCallback_t failure);
+
+ void checkDefaultHeaders(LLCore::HttpHeaders::ptr_t &headers);
+
+ std::string mAdapterName;
+ LLCore::HttpRequest::priority_t mPriority;
+ LLCore::HttpRequest::policy_t mPolicyId;
+
+ LLCore::HttpHandle mYieldingHandle;
+ LLCore::HttpRequest::wptr_t mWeakRequest;
+ HttpCoroHandler::wptr_t mWeakHandler;
+};
+
+
+} // end namespace LLCoreHttpUtil
#endif // LL_LLCOREHTTPUTIL_H
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 73df47b933..ef28a4d211 100755
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -69,13 +69,15 @@
do this.
*/
+// *TODO: TSN remove the commented code from this file
//////////////////////////////////////////////////////////////////////////////
static const U32 EASY_HANDLE_POOL_SIZE = 5;
static const S32 MULTI_PERFORM_CALL_REPEAT = 5;
static const S32 CURL_REQUEST_TIMEOUT = 120; // seconds per operation
static const S32 CURL_CONNECT_TIMEOUT = 30; //seconds to wait for a connection
-static const S32 MAX_ACTIVE_REQUEST_COUNT = 100;
+
+//static const S32 MAX_ACTIVE_REQUEST_COUNT = 100;
// DEBUG //
S32 gCurlEasyCount = 0;
@@ -676,6 +678,7 @@ void LLCurl::Easy::prepRequest(const std::string& url,
}
////////////////////////////////////////////////////////////////////////////
+#if 1
LLCurl::Multi::Multi(F32 idle_time_out)
: mQueued(0),
mErrorCount(0),
@@ -1056,6 +1059,7 @@ void LLCurl::Multi::removeEasy(Easy* easy)
easyFree(easy);
}
+#endif
//------------------------------------------------------------
//LLCurlThread
LLCurlThread::CurlRequest::CurlRequest(handle_t handle, LLCurl::Multi* multi, LLCurlThread* curl_thread) :
@@ -1176,428 +1180,428 @@ std::string LLCurl::strerror(CURLcode errorcode)
// For generating a simple request for data
// using one multi and one easy per request
-LLCurlRequest::LLCurlRequest() :
- mActiveMulti(NULL),
- mActiveRequestCount(0)
-{
- mProcessing = FALSE;
-}
-
-LLCurlRequest::~LLCurlRequest()
-{
- //stop all Multi handle background threads
- for (curlmulti_set_t::iterator iter = mMultiSet.begin(); iter != mMultiSet.end(); ++iter)
- {
- LLCurl::getCurlThread()->killMulti(*iter) ;
- }
- mMultiSet.clear() ;
-}
-
-void LLCurlRequest::addMulti()
-{
- LLCurl::Multi* multi = new LLCurl::Multi();
- if(!multi->isValid())
- {
- LLCurl::getCurlThread()->killMulti(multi) ;
- mActiveMulti = NULL ;
- mActiveRequestCount = 0 ;
- return;
- }
-
- mMultiSet.insert(multi);
- mActiveMulti = multi;
- mActiveRequestCount = 0;
-}
-
-LLCurl::Easy* LLCurlRequest::allocEasy()
-{
- if (!mActiveMulti ||
- mActiveRequestCount >= MAX_ACTIVE_REQUEST_COUNT ||
- mActiveMulti->mErrorCount > 0)
- {
- addMulti();
- }
- if(!mActiveMulti)
- {
- return NULL ;
- }
-
- //llassert_always(mActiveMulti);
- ++mActiveRequestCount;
- LLCurl::Easy* easy = mActiveMulti->allocEasy();
- return easy;
-}
-
-bool LLCurlRequest::addEasy(LLCurl::Easy* easy)
-{
- llassert_always(mActiveMulti);
-
- if (mProcessing)
- {
- LL_ERRS() << "Posting to a LLCurlRequest instance from within a responder is not allowed (causes DNS timeouts)." << LL_ENDL;
- }
- bool res = mActiveMulti->addEasy(easy);
- return res;
-}
-
-void LLCurlRequest::get(const std::string& url, LLCurl::ResponderPtr responder)
-{
- getByteRange(url, headers_t(), 0, -1, responder);
-}
-
-// Note: (length==0) is interpreted as "the rest of the file", i.e. the whole file if (offset==0) or
-// the remainder of the file if not.
-bool LLCurlRequest::getByteRange(const std::string& url,
- const headers_t& headers,
- S32 offset, S32 length,
- LLCurl::ResponderPtr responder)
-{
- llassert(LLCurl::sNotQuitting);
- LLCurl::Easy* easy = allocEasy();
- if (!easy)
- {
- return false;
- }
- easy->prepRequest(url, headers, responder);
- easy->setopt(CURLOPT_HTTPGET, 1);
- if (length > 0)
- {
- std::string range = llformat("bytes=%d-%d", offset,offset+length-1);
- easy->slist_append(HTTP_OUT_HEADER_RANGE, range);
- }
- else if (offset > 0)
- {
- std::string range = llformat("bytes=%d-", offset);
- easy->slist_append(HTTP_OUT_HEADER_RANGE, range);
- }
- easy->setHeaders();
- bool res = addEasy(easy);
- return res;
-}
-
-bool LLCurlRequest::post(const std::string& url,
- const headers_t& headers,
- const LLSD& data,
- LLCurl::ResponderPtr responder, S32 time_out)
-{
- llassert(LLCurl::sNotQuitting);
- LLCurl::Easy* easy = allocEasy();
- if (!easy)
- {
- return false;
- }
- easy->prepRequest(url, headers, responder, time_out);
-
- LLSDSerialize::toXML(data, easy->getInput());
- S32 bytes = easy->getInput().str().length();
-
- easy->setopt(CURLOPT_POST, 1);
- easy->setopt(CURLOPT_POSTFIELDS, (void*)NULL);
- easy->setopt(CURLOPT_POSTFIELDSIZE, bytes);
-
- easy->slist_append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_LLSD_XML);
- easy->setHeaders();
-
- LL_DEBUGS() << "POSTING: " << bytes << " bytes." << LL_ENDL;
- bool res = addEasy(easy);
- return res;
-}
-
-bool LLCurlRequest::post(const std::string& url,
- const headers_t& headers,
- const std::string& data,
- LLCurl::ResponderPtr responder, S32 time_out)
-{
- llassert(LLCurl::sNotQuitting);
- LLCurl::Easy* easy = allocEasy();
- if (!easy)
- {
- return false;
- }
- easy->prepRequest(url, headers, responder, time_out);
-
- easy->getInput().write(data.data(), data.size());
- S32 bytes = easy->getInput().str().length();
-
- easy->setopt(CURLOPT_POST, 1);
- easy->setopt(CURLOPT_POSTFIELDS, (void*)NULL);
- easy->setopt(CURLOPT_POSTFIELDSIZE, bytes);
-
- easy->slist_append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_OCTET_STREAM);
- easy->setHeaders();
-
- LL_DEBUGS() << "POSTING: " << bytes << " bytes." << LL_ENDL;
- bool res = addEasy(easy);
- return res;
-}
-
-// Note: call once per frame
-S32 LLCurlRequest::process()
-{
- S32 res = 0;
-
- mProcessing = TRUE;
- 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 ;
- }
- 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);
- }
- }
- mProcessing = FALSE;
- return res;
-}
-
-S32 LLCurlRequest::getQueued()
-{
- 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)
- {
- ++queued;
- }
- }
- return queued;
-}
-
-LLCurlTextureRequest::LLCurlTextureRequest(S32 concurrency) :
- LLCurlRequest(),
- mConcurrency(concurrency),
- mInQueue(0),
- mMutex(NULL),
- mHandleCounter(1),
- mTotalIssuedRequests(0),
- mTotalReceivedBits(0)
-{
- mGlobalTimer.reset();
-}
-
-LLCurlTextureRequest::~LLCurlTextureRequest()
-{
- mRequestMap.clear();
-
- for(req_queue_t::iterator iter = mCachedRequests.begin(); iter != mCachedRequests.end(); ++iter)
- {
- delete *iter;
- }
- mCachedRequests.clear();
-}
-
-//return 0: success
-// > 0: cached handle
-U32 LLCurlTextureRequest::getByteRange(const std::string& url,
- const headers_t& headers,
- S32 offset, S32 length, U32 pri,
- LLCurl::ResponderPtr responder, F32 delay_time)
-{
- U32 ret_val = 0;
- bool success = false;
-
- if(mInQueue < mConcurrency && delay_time < 0.f)
- {
- success = LLCurlRequest::getByteRange(url, headers, offset, length, responder);
- }
-
- LLMutexLock lock(&mMutex);
-
- if(success)
- {
- mInQueue++;
- mTotalIssuedRequests++;
- }
- else
- {
- request_t* request = new request_t(mHandleCounter, url, headers, offset, length, pri, responder);
- if(delay_time > 0.f)
- {
- request->mStartTime = mGlobalTimer.getElapsedTimeF32() + delay_time;
- }
-
- mCachedRequests.insert(request);
- mRequestMap[mHandleCounter] = request;
- ret_val = mHandleCounter;
- mHandleCounter++;
-
- if(!mHandleCounter)
- {
- mHandleCounter = 1;
- }
- }
-
- return ret_val;
-}
-
-void LLCurlTextureRequest::completeRequest(S32 received_bytes)
-{
- LLMutexLock lock(&mMutex);
-
- llassert_always(mInQueue > 0);
-
- mInQueue--;
- mTotalReceivedBits += received_bytes * 8;
-}
-
-void LLCurlTextureRequest::nextRequests()
-{
- if(mCachedRequests.empty() || mInQueue >= mConcurrency)
- {
- return;
- }
-
- F32 cur_time = mGlobalTimer.getElapsedTimeF32();
-
- req_queue_t::iterator iter;
- {
- LLMutexLock lock(&mMutex);
- iter = mCachedRequests.begin();
- }
- while(1)
- {
- request_t* request = *iter;
- if(request->mStartTime < cur_time)
- {
- if(!LLCurlRequest::getByteRange(request->mUrl, request->mHeaders, request->mOffset, request->mLength, request->mResponder))
- {
- break;
- }
-
- LLMutexLock lock(&mMutex);
- ++iter;
- mInQueue++;
- mTotalIssuedRequests++;
- mCachedRequests.erase(request);
- mRequestMap.erase(request->mHandle);
- delete request;
-
- if(iter == mCachedRequests.end() || mInQueue >= mConcurrency)
- {
- break;
- }
- }
- else
- {
- LLMutexLock lock(&mMutex);
- ++iter;
- if(iter == mCachedRequests.end() || mInQueue >= mConcurrency)
- {
- break;
- }
- }
- }
-
- return;
-}
-
-void LLCurlTextureRequest::updatePriority(U32 handle, U32 pri)
-{
- if(!handle)
- {
- return;
- }
-
- LLMutexLock lock(&mMutex);
-
- std::map<S32, request_t*>::iterator iter = mRequestMap.find(handle);
- if(iter != mRequestMap.end())
- {
- request_t* req = iter->second;
-
- if(req->mPriority != pri)
- {
- mCachedRequests.erase(req);
- req->mPriority = pri;
- mCachedRequests.insert(req);
- }
- }
-}
-
-void LLCurlTextureRequest::removeRequest(U32 handle)
-{
- if(!handle)
- {
- return;
- }
-
- LLMutexLock lock(&mMutex);
-
- std::map<S32, request_t*>::iterator iter = mRequestMap.find(handle);
- if(iter != mRequestMap.end())
- {
- request_t* req = iter->second;
- mRequestMap.erase(iter);
- mCachedRequests.erase(req);
- delete req;
- }
-}
-
-bool LLCurlTextureRequest::isWaiting(U32 handle)
-{
- if(!handle)
- {
- return false;
- }
-
- LLMutexLock lock(&mMutex);
- return mRequestMap.find(handle) != mRequestMap.end();
-}
-
-U32 LLCurlTextureRequest::getTotalReceivedBits()
-{
- LLMutexLock lock(&mMutex);
-
- U32 bits = mTotalReceivedBits;
- mTotalReceivedBits = 0;
- return bits;
-}
-
-U32 LLCurlTextureRequest::getTotalIssuedRequests()
-{
- LLMutexLock lock(&mMutex);
- return mTotalIssuedRequests;
-}
-
-S32 LLCurlTextureRequest::getNumRequests()
-{
- LLMutexLock lock(&mMutex);
- return mInQueue;
-}
+// LLCurlRequest::LLCurlRequest() :
+// mActiveMulti(NULL),
+// mActiveRequestCount(0)
+// {
+// mProcessing = FALSE;
+// }
+//
+// LLCurlRequest::~LLCurlRequest()
+// {
+// //stop all Multi handle background threads
+// for (curlmulti_set_t::iterator iter = mMultiSet.begin(); iter != mMultiSet.end(); ++iter)
+// {
+// LLCurl::getCurlThread()->killMulti(*iter) ;
+// }
+// mMultiSet.clear() ;
+// }
+//
+// void LLCurlRequest::addMulti()
+// {
+// LLCurl::Multi* multi = new LLCurl::Multi();
+// if(!multi->isValid())
+// {
+// LLCurl::getCurlThread()->killMulti(multi) ;
+// mActiveMulti = NULL ;
+// mActiveRequestCount = 0 ;
+// return;
+// }
+//
+// mMultiSet.insert(multi);
+// mActiveMulti = multi;
+// mActiveRequestCount = 0;
+// }
+//
+// LLCurl::Easy* LLCurlRequest::allocEasy()
+// {
+// if (!mActiveMulti ||
+// mActiveRequestCount >= MAX_ACTIVE_REQUEST_COUNT ||
+// mActiveMulti->mErrorCount > 0)
+// {
+// addMulti();
+// }
+// if(!mActiveMulti)
+// {
+// return NULL ;
+// }
+//
+// //llassert_always(mActiveMulti);
+// ++mActiveRequestCount;
+// LLCurl::Easy* easy = mActiveMulti->allocEasy();
+// return easy;
+// }
+//
+// bool LLCurlRequest::addEasy(LLCurl::Easy* easy)
+// {
+// llassert_always(mActiveMulti);
+//
+// if (mProcessing)
+// {
+// LL_ERRS() << "Posting to a LLCurlRequest instance from within a responder is not allowed (causes DNS timeouts)." << LL_ENDL;
+// }
+// bool res = mActiveMulti->addEasy(easy);
+// return res;
+// }
+//
+// void LLCurlRequest::get(const std::string& url, LLCurl::ResponderPtr responder)
+// {
+// getByteRange(url, headers_t(), 0, -1, responder);
+// }
+//
+// // Note: (length==0) is interpreted as "the rest of the file", i.e. the whole file if (offset==0) or
+// // the remainder of the file if not.
+// bool LLCurlRequest::getByteRange(const std::string& url,
+// const headers_t& headers,
+// S32 offset, S32 length,
+// LLCurl::ResponderPtr responder)
+// {
+// llassert(LLCurl::sNotQuitting);
+// LLCurl::Easy* easy = allocEasy();
+// if (!easy)
+// {
+// return false;
+// }
+// easy->prepRequest(url, headers, responder);
+// easy->setopt(CURLOPT_HTTPGET, 1);
+// if (length > 0)
+// {
+// std::string range = llformat("bytes=%d-%d", offset,offset+length-1);
+// easy->slist_append(HTTP_OUT_HEADER_RANGE, range);
+// }
+// else if (offset > 0)
+// {
+// std::string range = llformat("bytes=%d-", offset);
+// easy->slist_append(HTTP_OUT_HEADER_RANGE, range);
+// }
+// easy->setHeaders();
+// bool res = addEasy(easy);
+// return res;
+// }
+//
+// bool LLCurlRequest::post(const std::string& url,
+// const headers_t& headers,
+// const LLSD& data,
+// LLCurl::ResponderPtr responder, S32 time_out)
+// {
+// llassert(LLCurl::sNotQuitting);
+// LLCurl::Easy* easy = allocEasy();
+// if (!easy)
+// {
+// return false;
+// }
+// easy->prepRequest(url, headers, responder, time_out);
+//
+// LLSDSerialize::toXML(data, easy->getInput());
+// S32 bytes = easy->getInput().str().length();
+//
+// easy->setopt(CURLOPT_POST, 1);
+// easy->setopt(CURLOPT_POSTFIELDS, (void*)NULL);
+// easy->setopt(CURLOPT_POSTFIELDSIZE, bytes);
+//
+// easy->slist_append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_LLSD_XML);
+// easy->setHeaders();
+//
+// LL_DEBUGS() << "POSTING: " << bytes << " bytes." << LL_ENDL;
+// bool res = addEasy(easy);
+// return res;
+// }
+//
+// bool LLCurlRequest::post(const std::string& url,
+// const headers_t& headers,
+// const std::string& data,
+// LLCurl::ResponderPtr responder, S32 time_out)
+// {
+// llassert(LLCurl::sNotQuitting);
+// LLCurl::Easy* easy = allocEasy();
+// if (!easy)
+// {
+// return false;
+// }
+// easy->prepRequest(url, headers, responder, time_out);
+//
+// easy->getInput().write(data.data(), data.size());
+// S32 bytes = easy->getInput().str().length();
+//
+// easy->setopt(CURLOPT_POST, 1);
+// easy->setopt(CURLOPT_POSTFIELDS, (void*)NULL);
+// easy->setopt(CURLOPT_POSTFIELDSIZE, bytes);
+//
+// easy->slist_append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_OCTET_STREAM);
+// easy->setHeaders();
+//
+// LL_DEBUGS() << "POSTING: " << bytes << " bytes." << LL_ENDL;
+// bool res = addEasy(easy);
+// return res;
+// }
+//
+// // Note: call once per frame
+// S32 LLCurlRequest::process()
+// {
+// S32 res = 0;
+//
+// mProcessing = TRUE;
+// 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 ;
+// }
+// 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);
+// }
+// }
+// mProcessing = FALSE;
+// return res;
+// }
+//
+// S32 LLCurlRequest::getQueued()
+// {
+// 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)
+// {
+// ++queued;
+// }
+// }
+// return queued;
+// }
+
+// LLCurlTextureRequest::LLCurlTextureRequest(S32 concurrency) :
+// LLCurlRequest(),
+// mConcurrency(concurrency),
+// mInQueue(0),
+// mMutex(NULL),
+// mHandleCounter(1),
+// mTotalIssuedRequests(0),
+// mTotalReceivedBits(0)
+// {
+// mGlobalTimer.reset();
+// }
+//
+// LLCurlTextureRequest::~LLCurlTextureRequest()
+// {
+// mRequestMap.clear();
+//
+// for(req_queue_t::iterator iter = mCachedRequests.begin(); iter != mCachedRequests.end(); ++iter)
+// {
+// delete *iter;
+// }
+// mCachedRequests.clear();
+// }
+//
+// //return 0: success
+// // > 0: cached handle
+// U32 LLCurlTextureRequest::getByteRange(const std::string& url,
+// const headers_t& headers,
+// S32 offset, S32 length, U32 pri,
+// LLCurl::ResponderPtr responder, F32 delay_time)
+// {
+// U32 ret_val = 0;
+// bool success = false;
+//
+// if(mInQueue < mConcurrency && delay_time < 0.f)
+// {
+// success = LLCurlRequest::getByteRange(url, headers, offset, length, responder);
+// }
+//
+// LLMutexLock lock(&mMutex);
+//
+// if(success)
+// {
+// mInQueue++;
+// mTotalIssuedRequests++;
+// }
+// else
+// {
+// request_t* request = new request_t(mHandleCounter, url, headers, offset, length, pri, responder);
+// if(delay_time > 0.f)
+// {
+// request->mStartTime = mGlobalTimer.getElapsedTimeF32() + delay_time;
+// }
+//
+// mCachedRequests.insert(request);
+// mRequestMap[mHandleCounter] = request;
+// ret_val = mHandleCounter;
+// mHandleCounter++;
+//
+// if(!mHandleCounter)
+// {
+// mHandleCounter = 1;
+// }
+// }
+//
+// return ret_val;
+// }
+//
+// void LLCurlTextureRequest::completeRequest(S32 received_bytes)
+// {
+// LLMutexLock lock(&mMutex);
+//
+// llassert_always(mInQueue > 0);
+//
+// mInQueue--;
+// mTotalReceivedBits += received_bytes * 8;
+// }
+//
+// void LLCurlTextureRequest::nextRequests()
+// {
+// if(mCachedRequests.empty() || mInQueue >= mConcurrency)
+// {
+// return;
+// }
+//
+// F32 cur_time = mGlobalTimer.getElapsedTimeF32();
+//
+// req_queue_t::iterator iter;
+// {
+// LLMutexLock lock(&mMutex);
+// iter = mCachedRequests.begin();
+// }
+// while(1)
+// {
+// request_t* request = *iter;
+// if(request->mStartTime < cur_time)
+// {
+// if(!LLCurlRequest::getByteRange(request->mUrl, request->mHeaders, request->mOffset, request->mLength, request->mResponder))
+// {
+// break;
+// }
+//
+// LLMutexLock lock(&mMutex);
+// ++iter;
+// mInQueue++;
+// mTotalIssuedRequests++;
+// mCachedRequests.erase(request);
+// mRequestMap.erase(request->mHandle);
+// delete request;
+//
+// if(iter == mCachedRequests.end() || mInQueue >= mConcurrency)
+// {
+// break;
+// }
+// }
+// else
+// {
+// LLMutexLock lock(&mMutex);
+// ++iter;
+// if(iter == mCachedRequests.end() || mInQueue >= mConcurrency)
+// {
+// break;
+// }
+// }
+// }
+//
+// return;
+// }
+//
+// void LLCurlTextureRequest::updatePriority(U32 handle, U32 pri)
+// {
+// if(!handle)
+// {
+// return;
+// }
+//
+// LLMutexLock lock(&mMutex);
+//
+// std::map<S32, request_t*>::iterator iter = mRequestMap.find(handle);
+// if(iter != mRequestMap.end())
+// {
+// request_t* req = iter->second;
+//
+// if(req->mPriority != pri)
+// {
+// mCachedRequests.erase(req);
+// req->mPriority = pri;
+// mCachedRequests.insert(req);
+// }
+// }
+// }
+//
+// void LLCurlTextureRequest::removeRequest(U32 handle)
+// {
+// if(!handle)
+// {
+// return;
+// }
+//
+// LLMutexLock lock(&mMutex);
+//
+// std::map<S32, request_t*>::iterator iter = mRequestMap.find(handle);
+// if(iter != mRequestMap.end())
+// {
+// request_t* req = iter->second;
+// mRequestMap.erase(iter);
+// mCachedRequests.erase(req);
+// delete req;
+// }
+// }
+//
+// bool LLCurlTextureRequest::isWaiting(U32 handle)
+// {
+// if(!handle)
+// {
+// return false;
+// }
+//
+// LLMutexLock lock(&mMutex);
+// return mRequestMap.find(handle) != mRequestMap.end();
+// }
+//
+// U32 LLCurlTextureRequest::getTotalReceivedBits()
+// {
+// LLMutexLock lock(&mMutex);
+//
+// U32 bits = mTotalReceivedBits;
+// mTotalReceivedBits = 0;
+// return bits;
+// }
+//
+// U32 LLCurlTextureRequest::getTotalIssuedRequests()
+// {
+// LLMutexLock lock(&mMutex);
+// return mTotalIssuedRequests;
+// }
+//
+// S32 LLCurlTextureRequest::getNumRequests()
+// {
+// LLMutexLock lock(&mMutex);
+// return mInQueue;
+// }
////////////////////////////////////////////////////////////////////////////
// For generating one easy request
@@ -1988,10 +1992,10 @@ void LLCurlFF::check_easy_code(CURLcode code)
{
check_curl_code(code);
}
-void LLCurlFF::check_multi_code(CURLMcode code)
-{
- check_curl_multi_code(code);
-}
+// void LLCurlFF::check_multi_code(CURLMcode code)
+// {
+// check_curl_multi_code(code);
+// }
// Static
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h
index 385d9fffa8..06b3ce45e1 100755
--- a/indra/llmessage/llcurl.h
+++ b/indra/llmessage/llcurl.h
@@ -418,100 +418,6 @@ private:
} ;
-class LLCurlRequest
-{
-public:
- typedef std::vector<std::string> headers_t;
-
- LLCurlRequest();
- ~LLCurlRequest();
-
- 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, 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();
-
-private:
- void addMulti();
- LLCurl::Easy* allocEasy();
- bool addEasy(LLCurl::Easy* easy);
-
-private:
- typedef std::set<LLCurl::Multi*> curlmulti_set_t;
- curlmulti_set_t mMultiSet;
- LLCurl::Multi* mActiveMulti;
- S32 mActiveRequestCount;
- BOOL mProcessing;
-};
-
-//for texture fetch only
-class LLCurlTextureRequest : public LLCurlRequest
-{
-public:
- LLCurlTextureRequest(S32 concurrency);
- ~LLCurlTextureRequest();
-
- U32 getByteRange(const std::string& url, const headers_t& headers, S32 offset, S32 length, U32 pri, LLCurl::ResponderPtr responder, F32 delay_time = -1.f);
- void nextRequests();
- void completeRequest(S32 received_bytes);
-
- void updatePriority(U32 handle, U32 pri);
- void removeRequest(U32 handle);
-
- U32 getTotalReceivedBits();
- U32 getTotalIssuedRequests();
- S32 getNumRequests();
- bool isWaiting(U32 handle);
-
-private:
- LLMutex mMutex;
- S32 mConcurrency;
- S32 mInQueue; //request currently in queue.
- U32 mHandleCounter;
- U32 mTotalIssuedRequests;
- U32 mTotalReceivedBits;
-
- typedef struct _request_t
- {
- _request_t(U32 handle, const std::string& url, const headers_t& headers, S32 offset, S32 length, U32 pri, LLCurl::ResponderPtr responder) :
- mHandle(handle), mUrl(url), mHeaders(headers), mOffset(offset), mLength(length), mPriority(pri), mResponder(responder), mStartTime(0.f)
- {}
-
- U32 mHandle;
- std::string mUrl;
- LLCurlRequest::headers_t mHeaders;
- S32 mOffset;
- S32 mLength;
- LLCurl::ResponderPtr mResponder;
- U32 mPriority;
- F32 mStartTime; //start time to issue this request
- } request_t;
-
- struct request_compare
- {
- bool operator()(const request_t* lhs, const request_t* rhs) const
- {
- if(lhs->mPriority != rhs->mPriority)
- {
- return lhs->mPriority > rhs->mPriority; // higher priority in front of queue (set)
- }
- else
- {
- return (U32)lhs < (U32)rhs;
- }
- }
- };
-
- typedef std::set<request_t*, request_compare> req_queue_t;
- req_queue_t mCachedRequests;
- std::map<S32, request_t*> mRequestMap;
-
- LLFrameTimer mGlobalTimer;
-};
-
class LLCurlEasyRequest
{
public:
@@ -550,7 +456,7 @@ private:
namespace LLCurlFF
{
void check_easy_code(CURLcode code);
- void check_multi_code(CURLMcode code);
+ //void check_multi_code(CURLMcode code);
}
#endif // LL_LLCURL_H
diff --git a/indra/llmessage/llhost.cpp b/indra/llmessage/llhost.cpp
index 63c15f0d5e..ae5c2ecf69 100755
--- a/indra/llmessage/llhost.cpp
+++ b/indra/llmessage/llhost.cpp
@@ -41,8 +41,6 @@
#include <arpa/inet.h>
#endif
-LLHost LLHost::invalid(INVALID_PORT,INVALID_HOST_IP_ADDRESS);
-
LLHost::LLHost(const std::string& ip_and_port)
{
std::string::size_type colon_index = ip_and_port.find(":");
diff --git a/indra/llmessage/llhost.h b/indra/llmessage/llhost.h
index 0cf52a4151..79cad4b123 100755
--- a/indra/llmessage/llhost.h
+++ b/indra/llmessage/llhost.h
@@ -40,9 +40,8 @@ class LLHost {
protected:
U32 mPort;
U32 mIP;
+ std::string mUntrustedSimCap;
public:
-
- static LLHost invalid;
// CREATORS
LLHost()
@@ -89,13 +88,17 @@ public:
// READERS
U32 getAddress() const { return mIP; }
U32 getPort() const { return mPort; }
- BOOL isOk() const { return (mIP != INVALID_HOST_IP_ADDRESS) && (mPort != INVALID_PORT); }
+ bool isOk() const { return (mIP != INVALID_HOST_IP_ADDRESS) && (mPort != INVALID_PORT); }
+ bool isInvalid() { return (mIP == INVALID_HOST_IP_ADDRESS) || (mPort == INVALID_PORT); }
size_t hash() const { return (mIP << 16) | (mPort & 0xffff); }
std::string getString() const;
std::string getIPString() const;
std::string getHostName() const;
std::string getIPandPort() const;
+ std::string getUntrustedSimulatorCap() const { return mUntrustedSimCap; }
+ void setUntrustedSimulatorCap(const std::string &capurl) { mUntrustedSimCap = capurl; }
+
friend std::ostream& operator<< (std::ostream& os, const LLHost &hh);
// This operator is not well defined. does it expect a
diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp
index 60f17e6870..b149d24c4b 100755
--- a/indra/llmessage/llhttpclient.cpp
+++ b/indra/llmessage/llhttpclient.cpp
@@ -38,6 +38,10 @@
#include "lluri.h"
#include "message.h"
+#include "httpcommon.h"
+#include "httprequest.h"
+#include "httpoptions.h"
+
#include <curl/curl.h>
diff --git a/indra/llmessage/llhttpclientadapter.cpp b/indra/llmessage/llhttpclientadapter.cpp
deleted file mode 100755
index b56a804f94..0000000000
--- a/indra/llmessage/llhttpclientadapter.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-/**
- * @file llhttpclientadapter.cpp
- * @brief
- *
- * $LicenseInfo:firstyear=2009&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "llhttpclientadapter.h"
-#include "llhttpclient.h"
-
-LLHTTPClientAdapter::~LLHTTPClientAdapter()
-{
-}
-
-void LLHTTPClientAdapter::get(const std::string& url, LLCurl::ResponderPtr responder)
-{
- LLSD empty_pragma_header;
- // Pragma is required to stop curl adding "no-cache"
- // Space is required to stop llurlrequest from turning off proxying
- empty_pragma_header[HTTP_OUT_HEADER_PRAGMA] = " ";
- LLHTTPClient::get(url, responder, empty_pragma_header);
-}
-
-void LLHTTPClientAdapter::get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers)
-{
- LLSD empty_pragma_header = headers;
- if (!empty_pragma_header.has(HTTP_OUT_HEADER_PRAGMA))
- {
- // as above
- empty_pragma_header[HTTP_OUT_HEADER_PRAGMA] = " ";
- }
- LLHTTPClient::get(url, responder, empty_pragma_header);
-}
-
-void LLHTTPClientAdapter::put(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder)
-{
- LLHTTPClient::put(url, body, responder);
-}
-
-void LLHTTPClientAdapter::put(
- const std::string& url,
- const LLSD& body,
- LLCurl::ResponderPtr responder,
- const LLSD& headers)
-{
- LLHTTPClient::put(url, body, responder, headers);
-}
-
-void LLHTTPClientAdapter::del(
- const std::string& url,
- LLCurl::ResponderPtr responder)
-{
- LLHTTPClient::del(url, responder);
-}
diff --git a/indra/llmessage/llhttpclientadapter.h b/indra/llmessage/llhttpclientadapter.h
deleted file mode 100755
index 270282c66f..0000000000
--- a/indra/llmessage/llhttpclientadapter.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/**
- * @file llhttpclientadepter.h
- * @brief
- *
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_HTTPCLIENTADAPTER_H
-#define LL_HTTPCLIENTADAPTER_H
-
-#include "llhttpclientinterface.h"
-#include "llsingleton.h" // LLSingleton<>
-
-class LLHTTPClientAdapter : public LLHTTPClientInterface, public LLSingleton<LLHTTPClientAdapter>
-{
-public:
- virtual ~LLHTTPClientAdapter();
- virtual void get(const std::string& url, LLCurl::ResponderPtr responder);
- virtual void get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers);
- virtual void put(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder);
- virtual void put(
- const std::string& url,
- const LLSD& body,
- LLCurl::ResponderPtr responder,
- const LLSD& headers);
- virtual void del(
- const std::string& url,
- LLCurl::ResponderPtr responder);
-};
-
-#endif
-
diff --git a/indra/llmessage/llhttpclientinterface.h b/indra/llmessage/llhttpclientinterface.h
index 12a3857a61..9c1c8e7c11 100755
--- a/indra/llmessage/llhttpclientinterface.h
+++ b/indra/llmessage/llhttpclientinterface.h
@@ -32,14 +32,14 @@
#include <string>
-class LLHTTPClientInterface
-{
-public:
- virtual ~LLHTTPClientInterface() {}
- virtual void get(const std::string& url, LLCurl::ResponderPtr responder) = 0;
- virtual void get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers) = 0;
- virtual void put(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder) = 0;
-};
+// class LLHTTPClientInterface
+// {
+// public:
+// virtual ~LLHTTPClientInterface() {}
+// virtual void get(const std::string& url, LLCurl::ResponderPtr responder) = 0;
+// virtual void get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers) = 0;
+// virtual void put(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder) = 0;
+// };
#endif // LL_LLHTTPCLIENTINTERFACE_H
diff --git a/indra/llmessage/llhttpsdhandler.cpp b/indra/llmessage/llhttpsdhandler.cpp
new file mode 100644
index 0000000000..d99bdd3f66
--- /dev/null
+++ b/indra/llmessage/llhttpsdhandler.cpp
@@ -0,0 +1,105 @@
+/**
+* @file llhttpsdhandler.h
+* @brief Public-facing declarations for the HttpHandler class
+*
+* $LicenseInfo:firstyear=2012&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2012, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+* $/LicenseInfo$
+*/
+
+#include "linden_common.h"
+#include "llhttpconstants.h"
+
+#include "llhttpsdhandler.h"
+#include "httpresponse.h"
+#include "httpheaders.h"
+#include "llsd.h"
+#include "llsdserialize.h"
+#include "bufferstream.h"
+#include "llcorehttputil.h"
+
+//========================================================================
+LLHttpSDHandler::LLHttpSDHandler(bool selfDelete):
+ mSelfDelete(selfDelete)
+{
+}
+
+void LLHttpSDHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response)
+{
+ LLCore::HttpStatus status = response->getStatus();
+
+ if (!status)
+ {
+ this->onFailure(response, status);
+ }
+ else
+ {
+ LLSD resplsd;
+ const bool emit_parse_errors = false;
+
+ bool parsed = !((response->getBodySize() == 0) ||
+ !LLCoreHttpUtil::responseToLLSD(response, emit_parse_errors, resplsd));
+
+ if (!parsed)
+ {
+ // Only emit a warning if we failed to parse when 'content-type' == 'application/llsd+xml'
+ LLCore::HttpHeaders::ptr_t headers(response->getHeaders());
+ const std::string *contentType = (headers) ? headers->find(HTTP_IN_HEADER_CONTENT_TYPE) : NULL;
+
+ if (contentType && (HTTP_CONTENT_LLSD_XML == *contentType))
+ {
+ std::string thebody = LLCoreHttpUtil::responseToString(response);
+
+ LL_WARNS() << "Failed to deserialize . " << response->getRequestURL() << " [status:" << response->getStatus().toString() << "] "
+ << " body: " << thebody << LL_ENDL;
+ }
+ }
+
+ this->onSuccess(response, resplsd);
+ }
+
+ // The handler must destroy itself when it is done.
+ // *TODO: I'm not fond of this pattern. A class shooting itself in the head
+ // outside of a smart pointer always makes me nervous.
+ if (mSelfDelete)
+ delete this;
+}
+
+//========================================================================
+LLHttpSDGenericHandler::LLHttpSDGenericHandler(const std::string &name, bool selfDelete):
+ LLHttpSDHandler(selfDelete),
+ mName(name)
+{
+}
+
+void LLHttpSDGenericHandler::onSuccess(LLCore::HttpResponse * response, const LLSD &content)
+{
+ LL_DEBUGS() << mName << " Success." << LL_ENDL;
+}
+
+void LLHttpSDGenericHandler::onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status)
+{
+ LL_WARNS()
+ << "\n--------------------------------------------------------------------------\n"
+ << mName << " Error[" << status.toULong() << "] cannot access cap with url '"
+ << response->getRequestURL() << "' because " << status.toString()
+ << "\n--------------------------------------------------------------------------"
+ << LL_ENDL;
+}
diff --git a/indra/llmessage/llhttpsdhandler.h b/indra/llmessage/llhttpsdhandler.h
new file mode 100644
index 0000000000..3b81dc66b9
--- /dev/null
+++ b/indra/llmessage/llhttpsdhandler.h
@@ -0,0 +1,72 @@
+/**
+* @file llhttpsdhandler.h
+* @brief Public-facing declarations for the HttpHandler class
+*
+* $LicenseInfo:firstyear=2012&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2012, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+* $/LicenseInfo$
+*/
+
+#ifndef _LLHTTPSDHANDLER_H_
+#define _LLHTTPSDHANDLER_H_
+#include "httpcommon.h"
+#include "httphandler.h"
+#include "lluri.h"
+
+/// Handler class LLCore's HTTP library. Splitting with separate success and
+/// failure routines and parsing the result body into LLSD on success. It
+/// is intended to be subclassed for specific capability handling.
+///
+// *TODO: This class self deletes at the end of onCompleted method. This is
+// less than ideal and should be revisited.
+class LLHttpSDHandler : public LLCore::HttpHandler //,
+// public std::enable_shared_from_this<LLHttpSDHandler>
+{
+public:
+
+ virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response);
+
+protected:
+ LLHttpSDHandler(bool selfDelete = true);
+
+ virtual void onSuccess(LLCore::HttpResponse * response, const LLSD &content) = 0;
+ virtual void onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status) = 0;
+
+private:
+ bool mSelfDelete;
+
+};
+
+/// A trivial implementation of LLHttpSDHandler. This success and failure
+/// methods log the action taken, the URI accessed and the status code returned
+/// in the response.
+class LLHttpSDGenericHandler : public LLHttpSDHandler
+{
+public:
+ LLHttpSDGenericHandler(const std::string &name, bool selfDelete = true);
+
+protected:
+ virtual void onSuccess(LLCore::HttpResponse * response, const LLSD &content);
+ virtual void onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status);
+
+private:
+ std::string mName;
+};
+#endif
diff --git a/indra/llmessage/llhttpsender.cpp b/indra/llmessage/llhttpsender.cpp
deleted file mode 100755
index 5363088d79..0000000000
--- a/indra/llmessage/llhttpsender.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-/**
- * @file llhttpsender.cpp
- * @brief Abstracts details of sending messages via HTTP.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llhttpsender.h"
-
-#include <map>
-#include <sstream>
-
-#include "llhost.h"
-#include "llsd.h"
-
-namespace
-{
- typedef std::map<LLHost, LLHTTPSender*> SenderMap;
- static SenderMap senderMap;
- static LLPointer<LLHTTPSender> defaultSender(new LLHTTPSender());
-}
-
-//virtual
-LLHTTPSender::~LLHTTPSender()
-{
-}
-
-//virtual
-void LLHTTPSender::send(const LLHost& host, const std::string& name,
- const LLSD& body,
- LLHTTPClient::ResponderPtr response) const
-{
- // Default implementation inserts sender, message and sends HTTP POST
- std::ostringstream stream;
- stream << "http://" << host << "/trusted-message/" << name;
- LL_INFOS() << "LLHTTPSender::send: POST to " << stream.str() << LL_ENDL;
- LLHTTPClient::post(stream.str(), body, response);
-}
-
-//static
-void LLHTTPSender::setSender(const LLHost& host, LLHTTPSender* sender)
-{
- LL_INFOS() << "LLHTTPSender::setSender " << host << LL_ENDL;
- senderMap[host] = sender;
-}
-
-//static
-const LLHTTPSender& LLHTTPSender::getSender(const LLHost& host)
-{
- SenderMap::const_iterator iter = senderMap.find(host);
- if(iter == senderMap.end())
- {
- return *defaultSender;
- }
- return *(iter->second);
-}
-
-//static
-void LLHTTPSender::clearSender(const LLHost& host)
-{
- SenderMap::iterator iter = senderMap.find(host);
- if(iter != senderMap.end())
- {
- delete iter->second;
- senderMap.erase(iter);
- }
-}
-
-//static
-void LLHTTPSender::setDefaultSender(LLHTTPSender* sender)
-{
- defaultSender = sender;
-}
diff --git a/indra/llmessage/llhttpsender.h b/indra/llmessage/llhttpsender.h
deleted file mode 100755
index ff8fa2f95b..0000000000
--- a/indra/llmessage/llhttpsender.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/**
- * @file llhttpsender.h
- * @brief Abstracts details of sending messages via HTTP.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_HTTP_SENDER_H
-#define LL_HTTP_SENDER_H
-
-#include "llhttpclient.h"
-
-class LLHost;
-class LLSD;
-
-class LLHTTPSender : public LLThreadSafeRefCount
-{
- public:
-
- virtual ~LLHTTPSender();
-
- /** @brief Send message to host with body, call response when done */
- virtual void send(const LLHost& host,
- const std::string& message, const LLSD& body,
- LLHTTPClient::ResponderPtr response) const;
-
- /** @brief Set sender for host, takes ownership of sender. */
- static void setSender(const LLHost& host, LLHTTPSender* sender);
-
- /** @brief Get sender for host, retains ownership of returned sender. */
- static const LLHTTPSender& getSender(const LLHost& host);
-
- /** @brief Clear sender for host. */
- static void clearSender(const LLHost& host);
-
- /** @brief Set default sender, takes ownership of sender. */
- static void setDefaultSender(LLHTTPSender* sender);
-};
-
-#endif // LL_HTTP_SENDER_H
diff --git a/indra/llmessage/llsdmessage.cpp b/indra/llmessage/llsdmessage.cpp
deleted file mode 100755
index 61fcc5dd2f..0000000000
--- a/indra/llmessage/llsdmessage.cpp
+++ /dev/null
@@ -1,168 +0,0 @@
-/**
- * @file llsdmessage.cpp
- * @author Nat Goodspeed
- * @date 2008-10-31
- * @brief Implementation for llsdmessage.
- *
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#if LL_WINDOWS
-#pragma warning (disable : 4675) // "resolved by ADL" -- just as I want!
-#endif
-
-// Precompiled header
-#include "linden_common.h"
-// associated header
-#include "llsdmessage.h"
-// STL headers
-// std headers
-// external library headers
-// other Linden headers
-#include "llevents.h"
-#include "llsdserialize.h"
-#include "llhttpclient.h"
-#include "llmessageconfig.h"
-#include "llhost.h"
-#include "message.h"
-#include "llsdutil.h"
-
-// Declare a static LLSDMessage instance to ensure that we have a listener as
-// soon as someone tries to post on our canonical LLEventPump name.
-static LLSDMessage httpListener;
-
-LLSDMessage::LLSDMessage():
- // Instantiating our own local LLEventPump with a string name the
- // constructor is NOT allowed to tweak is a way of ensuring Singleton
- // semantics: attempting to instantiate a second LLSDMessage object would
- // throw LLEventPump::DupPumpName.
- mEventPump("LLHTTPClient")
-{
- mEventPump.listen("self", boost::bind(&LLSDMessage::httpListener, this, _1));
-}
-
-bool LLSDMessage::httpListener(const LLSD& request)
-{
- // Extract what we want from the request object. We do it all up front
- // partly to document what we expect.
- LLSD::String url(request["url"]);
- LLSD payload(request["payload"]);
- LLSD::String reply(request["reply"]);
- LLSD::String error(request["error"]);
- LLSD::Real timeout(request["timeout"]);
- // If the LLSD doesn't even have a "url" key, we doubt it was intended for
- // this listener.
- if (url.empty())
- {
- std::ostringstream out;
- out << "request event without 'url' key to '" << mEventPump.getName() << "'";
- throw ArgError(out.str());
- }
- // Establish default timeout. This test relies on LLSD::asReal() returning
- // exactly 0.0 for an undef value.
- if (! timeout)
- {
- timeout = HTTP_REQUEST_EXPIRY_SECS;
- }
- LLHTTPClient::post(url, payload,
- new LLSDMessage::EventResponder(LLEventPumps::instance(),
- request,
- url, "POST", reply, error),
- LLSD(), // headers
- (F32)timeout);
- return false;
-}
-
-void LLSDMessage::EventResponder::httpSuccess()
-{
- // If our caller passed an empty replyPump name, they're not
- // listening: this is a fire-and-forget message. Don't bother posting
- // to the pump whose name is "".
- if (! mReplyPump.empty())
- {
- LLSD response(getContent());
- mReqID.stamp(response);
- mPumps.obtain(mReplyPump).post(response);
- }
- else // default success handling
- {
- LL_INFOS("LLSDMessage::EventResponder")
- << "'" << mMessage << "' to '" << mTarget << "' succeeded"
- << LL_ENDL;
- }
-}
-
-void LLSDMessage::EventResponder::httpFailure()
-{
- // If our caller passed an empty errorPump name, they're not
- // listening: "default error handling is acceptable." Only post to an
- // explicit pump name.
- if (! mErrorPump.empty())
- {
- LLSD info(mReqID.makeResponse());
- info["target"] = mTarget;
- info["message"] = mMessage;
- info["status"] = getStatus();
- info["reason"] = getReason();
- info["content"] = getContent();
- mPumps.obtain(mErrorPump).post(info);
- }
- else // default error handling
- {
- // convention seems to be to use LL_INFOS(), but that seems a bit casual?
- LL_WARNS("LLSDMessage::EventResponder")
- << "'" << mMessage << "' to '" << mTarget
- << "' failed " << dumpResponse() << LL_ENDL;
- }
-}
-
-LLSDMessage::ResponderAdapter::ResponderAdapter(LLHTTPClient::ResponderPtr responder,
- const std::string& name):
- mResponder(responder),
- mReplyPump(name + ".reply", true), // tweak name for uniqueness
- mErrorPump(name + ".error", true)
-{
- mReplyPump.listen("self", boost::bind(&ResponderAdapter::listener, this, _1, true));
- mErrorPump.listen("self", boost::bind(&ResponderAdapter::listener, this, _1, false));
-}
-
-bool LLSDMessage::ResponderAdapter::listener(const LLSD& payload, bool success)
-{
- if (success)
- {
- mResponder->successResult(payload);
- }
- else
- {
- mResponder->failureResult(payload["status"].asInteger(), payload["reason"], payload["content"]);
- }
-
- /*---------------- MUST BE LAST STATEMENT BEFORE RETURN ----------------*/
- delete this;
- // Destruction of mResponder will usually implicitly free its referent as well
- /*------------------------- NOTHING AFTER THIS -------------------------*/
- return false;
-}
-
-void LLSDMessage::link()
-{
-}
diff --git a/indra/llmessage/llsdmessage.h b/indra/llmessage/llsdmessage.h
deleted file mode 100755
index e5d532d6a4..0000000000
--- a/indra/llmessage/llsdmessage.h
+++ /dev/null
@@ -1,168 +0,0 @@
-/**
- * @file llsdmessage.h
- * @author Nat Goodspeed
- * @date 2008-10-30
- * @brief API intended to unify sending capability, UDP and TCP messages:
- * https://wiki.lindenlab.com/wiki/Viewer:Messaging/Messaging_Notes
- *
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#if ! defined(LL_LLSDMESSAGE_H)
-#define LL_LLSDMESSAGE_H
-
-#include "llerror.h" // LOG_CLASS()
-#include "llevents.h" // LLEventPumps
-#include "llhttpclient.h"
-#include <string>
-#include <stdexcept>
-
-class LLSD;
-
-/**
- * Class managing the messaging API described in
- * https://wiki.lindenlab.com/wiki/Viewer:Messaging/Messaging_Notes
- */
-class LLSDMessage
-{
- LOG_CLASS(LLSDMessage);
-
-public:
- LLSDMessage();
-
- /// Exception if you specify arguments badly
- struct ArgError: public std::runtime_error
- {
- ArgError(const std::string& what):
- std::runtime_error(std::string("ArgError: ") + what) {}
- };
-
- /**
- * The response idiom used by LLSDMessage -- LLEventPump names on which to
- * post reply or error -- is designed for the case in which your
- * reply/error handlers are methods on the same class as the method
- * sending the message. Any state available to the sending method that
- * must be visible to the reply/error methods can conveniently be stored
- * on that class itself, if it's not already.
- *
- * The LLHTTPClient::Responder idiom requires a separate instance of a
- * separate class so that it can dispatch to the code of interest by
- * calling canonical virtual methods. Interesting state must be copied
- * into that new object.
- *
- * With some trepidation, because existing response code is packaged in
- * LLHTTPClient::Responder subclasses, we provide this adapter class
- * <i>for transitional purposes only.</i> Instantiate a new heap
- * ResponderAdapter with your new LLHTTPClient::ResponderPtr. Pass
- * ResponderAdapter::getReplyName() and/or getErrorName() in your
- * LLSDMessage (or LLViewerRegion::getCapAPI()) request event. The
- * ResponderAdapter will call the appropriate Responder method, then
- * @c delete itself.
- */
- class ResponderAdapter
- {
- public:
- /**
- * Bind the new LLHTTPClient::Responder subclass instance.
- *
- * Passing the constructor a name other than the default is only
- * interesting if you suspect some usage will lead to an exception or
- * log message.
- */
- ResponderAdapter(LLHTTPClient::ResponderPtr responder,
- const std::string& name="ResponderAdapter");
-
- /// EventPump name on which LLSDMessage should post reply event
- std::string getReplyName() const { return mReplyPump.getName(); }
- /// EventPump name on which LLSDMessage should post error event
- std::string getErrorName() const { return mErrorPump.getName(); }
-
- private:
- // We have two different LLEventStreams, though we route them both to
- // the same listener, so that we can bind an extra flag identifying
- // which case (reply or error) reached that listener.
- bool listener(const LLSD&, bool success);
-
- LLHTTPClient::ResponderPtr mResponder;
- LLEventStream mReplyPump, mErrorPump;
- };
-
- /**
- * Force our implementation file to be linked with caller. The .cpp file
- * contains a static instance of this class, which must be linked into the
- * executable to support the canonical listener. But since the primary
- * interface to that static instance is via a named LLEventPump rather
- * than by direct reference, the linker doesn't necessarily perceive the
- * necessity to bring in the translation unit. Referencing this dummy
- * method forces the issue.
- */
- static void link();
-
-private:
- friend class LLCapabilityListener;
- /// Responder used for internal purposes by LLSDMessage and
- /// LLCapabilityListener. Others should use higher-level APIs.
- class EventResponder: public LLHTTPClient::Responder
- {
- LOG_CLASS(EventResponder);
- public:
- /**
- * LLHTTPClient::Responder that dispatches via named LLEventPump instances.
- * We bind LLEventPumps, even though it's an LLSingleton, for testability.
- * We bind the string names of the desired LLEventPump instances rather
- * than actually obtain()ing them so we only obtain() the one we're going
- * to use. If the caller doesn't bother to listen() on it, the other pump
- * may never materialize at all.
- * @a target and @a message are only to clarify error processing.
- * For a capability message, @a target should be the region description,
- * @a message should be the capability name.
- * For a service with a visible URL, pass the URL as @a target and the HTTP verb
- * (e.g. "POST") as @a message.
- */
- EventResponder(LLEventPumps& pumps,
- const LLSD& request,
- const std::string& target, const std::string& message,
- const std::string& replyPump, const std::string& errorPump):
- mPumps(pumps),
- mReqID(request),
- mTarget(target),
- mMessage(message),
- mReplyPump(replyPump),
- mErrorPump(errorPump)
- {}
-
- protected:
- virtual void httpSuccess();
- virtual void httpFailure();
-
- private:
- LLEventPumps& mPumps;
- LLReqID mReqID;
- const std::string mTarget, mMessage, mReplyPump, mErrorPump;
- };
-
-private:
- bool httpListener(const LLSD&);
- LLEventStream mEventPump;
-};
-
-#endif /* ! defined(LL_LLSDMESSAGE_H) */
diff --git a/indra/llmessage/llsdrpcclient.h b/indra/llmessage/llsdrpcclient.h
index c4e0333ca3..d097ecdff7 100755
--- a/indra/llmessage/llsdrpcclient.h
+++ b/indra/llmessage/llsdrpcclient.h
@@ -37,7 +37,9 @@
#include "llchainio.h"
#include "llfiltersd2xmlrpc.h"
#include "lliopipe.h"
-#include "llurlrequest.h"
+#if 0
+//#include "llurlrequest.h"
+#endif
/**
* @class LLSDRPCClientResponse
@@ -218,6 +220,7 @@ protected:
LLIOPipe::ptr_t mResponse;
};
+#if 0
/**
* @class LLSDRPCClientFactory
* @brief Basic implementation for making an SD RPC client factory
@@ -267,7 +270,9 @@ public:
protected:
std::string mURL;
};
+#endif
+#if 0
/**
* @class LLXMLSDRPCClientFactory
* @brief Basic implementation for making an XMLRPC to SD RPC client factory
@@ -319,5 +324,6 @@ public:
protected:
std::string mURL;
};
+#endif
#endif // LL_LLSDRPCCLIENT_H
diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp
index e9ce94ab3b..10dbbef046 100755
--- a/indra/llmessage/message.cpp
+++ b/indra/llmessage/message.cpp
@@ -52,7 +52,6 @@
#include "llfasttimer.h"
#include "llhttpclient.h"
#include "llhttpnodeadapter.h"
-#include "llhttpsender.h"
#include "llmd5.h"
#include "llmessagebuilder.h"
#include "llmessageconfig.h"
@@ -77,6 +76,7 @@
#include "v3math.h"
#include "v4math.h"
#include "lltransfertargetvfile.h"
+#include "llcorehttputil.h"
// Constants
//const char* MESSAGE_LOG_FILENAME = "message.log";
@@ -97,45 +97,6 @@ public:
apr_pollfd_t mPollFD;
};
-namespace
-{
- class LLFnPtrResponder : public LLHTTPClient::Responder
- {
- LOG_CLASS(LLFnPtrResponder);
- public:
- LLFnPtrResponder(void (*callback)(void **,S32), void **callbackData, const std::string& name) :
- mCallback(callback),
- mCallbackData(callbackData),
- mMessageName(name)
- {
- }
-
- protected:
- virtual void httpFailure()
- {
- // don't spam when agent communication disconnected already
- if (HTTP_GONE != getStatus())
- {
- LL_WARNS("Messaging") << "error for message " << mMessageName
- << " " << dumpResponse() << LL_ENDL;
- }
- // TODO: Map status in to useful error code.
- if(NULL != mCallback) mCallback(mCallbackData, LL_ERR_TCP_TIMEOUT);
- }
-
- virtual void httpSuccess()
- {
- if(NULL != mCallback) mCallback(mCallbackData, LL_ERR_NOERR);
- }
-
- private:
-
- void (*mCallback)(void **,S32);
- void **mCallbackData;
- std::string mMessageName;
- };
-}
-
class LLMessageHandlerBridge : public LLHTTPNode
{
virtual bool validate(const std::string& name, LLSD& context) const
@@ -1129,29 +1090,6 @@ S32 LLMessageSystem::flushReliable(const LLHost &host)
return send_bytes;
}
-LLHTTPClient::ResponderPtr LLMessageSystem::createResponder(const std::string& name)
-{
- if(mSendReliable)
- {
- return new LLFnPtrResponder(
- mReliablePacketParams.mCallback,
- mReliablePacketParams.mCallbackData,
- name);
- }
- else
- {
- // These messages aren't really unreliable, they just weren't
- // explicitly sent as reliable, so they don't have a callback
-// LL_WARNS("Messaging") << "LLMessageSystem::sendMessage: Sending unreliable "
-// << mMessageBuilder->getMessageName() << " message via HTTP"
-// << LL_ENDL;
- return new LLFnPtrResponder(
- NULL,
- NULL,
- name);
- }
-}
-
// This can be called from signal handlers,
// so should should not use LL_INFOS().
S32 LLMessageSystem::sendMessage(const LLHost &host)
@@ -1216,13 +1154,17 @@ S32 LLMessageSystem::sendMessage(const LLHost &host)
if(mMessageBuilder == mLLSDMessageBuilder)
{
LLSD message = mLLSDMessageBuilder->getMessage();
-
- const LLHTTPSender& sender = LLHTTPSender::getSender(host);
- sender.send(
- host,
- mLLSDMessageBuilder->getMessageName(),
- message,
- createResponder(mLLSDMessageBuilder->getMessageName()));
+
+ UntrustedCallback_t cb = NULL;
+ if ((mSendReliable) && (mReliablePacketParams.mCallback))
+ {
+ cb = boost::bind(mReliablePacketParams.mCallback, mReliablePacketParams.mCallbackData, _1);
+ }
+
+ LLCoros::instance().launch("LLMessageSystem::sendUntrustedSimulatorMessageCoro",
+ boost::bind(&LLMessageSystem::sendUntrustedSimulatorMessageCoro, this,
+ host.getUntrustedSimulatorCap(),
+ mLLSDMessageBuilder->getMessageName(), message, cb));
mSendReliable = FALSE;
mReliablePacketParams.clear();
@@ -1410,9 +1352,16 @@ S32 LLMessageSystem::sendMessage(
return 0;
}
- const LLHTTPSender& sender = LLHTTPSender::getSender(host);
- sender.send(host, name, message, createResponder(name));
- return 1;
+ UntrustedCallback_t cb = NULL;
+ if ((mSendReliable) && (mReliablePacketParams.mCallback))
+ {
+ cb = boost::bind(mReliablePacketParams.mCallback, mReliablePacketParams.mCallbackData, _1);
+ }
+
+ LLCoros::instance().launch("LLMessageSystem::sendUntrustedSimulatorMessageCoro",
+ boost::bind(&LLMessageSystem::sendUntrustedSimulatorMessageCoro, this,
+ host.getUntrustedSimulatorCap(), name, message, cb));
+ return 1;
}
void LLMessageSystem::logTrustedMsgFromUntrustedCircuit( const LLHost& host )
@@ -1725,7 +1674,7 @@ LLHost LLMessageSystem::findHost(const U32 circuit_code)
}
else
{
- return LLHost::invalid;
+ return LLHost();
}
}
@@ -4055,6 +4004,36 @@ const LLHost& LLMessageSystem::getSender() const
return mLastSender;
}
+void LLMessageSystem::sendUntrustedSimulatorMessageCoro(std::string url, std::string message, LLSD body, UntrustedCallback_t callback)
+{
+ LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+ httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("groupMembersRequest", httpPolicy));
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+ LLCore::HttpOptions::ptr_t httpOpts = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions);
+
+
+ if (url.empty())
+ {
+ LL_WARNS() << "sendUntrustedSimulatorMessageCoro called with empty capability!" << LL_ENDL;
+ return;
+ }
+
+ LL_INFOS() << "sendUntrustedSimulatorMessageCoro: message " << message << " to cap " << url << LL_ENDL;
+ LLSD postData;
+ postData["message"] = message;
+ postData["body"] = body;
+
+ LLSD result = httpAdapter->postAndYield(httpRequest, url, postData, httpOpts);
+
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+ if ((callback) && (!callback.empty()))
+ callback((status) ? LL_ERR_NOERR : LL_ERR_TCP_TIMEOUT);
+}
+
+
LLHTTPRegistration<LLHTTPNodeAdapter<LLTrustedMessageService> >
gHTTPRegistrationTrustedMessageWildcard("/trusted-message/<message-name>");
diff --git a/indra/llmessage/message.h b/indra/llmessage/message.h
index 348b09b992..fc391da633 100755
--- a/indra/llmessage/message.h
+++ b/indra/llmessage/message.h
@@ -60,6 +60,7 @@
#include "llmessagesenderinterface.h"
#include "llstoredmessage.h"
+#include "boost/function.hpp"
const U32 MESSAGE_MAX_STRINGS_LENGTH = 64;
const U32 MESSAGE_NUMBER_OF_HASH_BUCKETS = 8192;
@@ -489,7 +490,6 @@ public:
void (*callback)(void **,S32),
void ** callback_data);
- LLCurl::ResponderPtr createResponder(const std::string& name);
S32 sendMessage(const LLHost &host);
S32 sendMessage(const U32 circuit);
private:
@@ -740,6 +740,9 @@ public:
void receivedMessageFromTrustedSender();
private:
+ typedef boost::function<void(S32)> UntrustedCallback_t;
+ void sendUntrustedSimulatorMessageCoro(std::string url, std::string message, LLSD body, UntrustedCallback_t callback);
+
bool mLastMessageFromTrustedMessageService;
diff --git a/indra/llmessage/tests/llhttpclientadapter_test.cpp b/indra/llmessage/tests/llhttpclientadapter_test.cpp
deleted file mode 100755
index e9ce116bb3..0000000000
--- a/indra/llmessage/tests/llhttpclientadapter_test.cpp
+++ /dev/null
@@ -1,221 +0,0 @@
-/**
- * @file llhttpclientadapter_test.cpp
- * @brief Tests for LLHTTPClientAdapter
- *
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "llhttpclientadapter.h"
-
-#include "../test/lltut.h"
-#include "llhttpclient.h"
-#include "llcurl_stub.cpp"
-
-float const HTTP_REQUEST_EXPIRY_SECS = 1.0F;
-
-std::vector<std::string> get_urls;
-std::vector< LLCurl::ResponderPtr > get_responders;
-void LLHTTPClient::get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers, const F32 timeout, bool follow_redirects)
-{
- get_urls.push_back(url);
- get_responders.push_back(responder);
-}
-
-std::vector<std::string> put_urls;
-std::vector<LLSD> put_body;
-std::vector<LLSD> put_headers;
-std::vector<LLCurl::ResponderPtr> put_responders;
-
-void LLHTTPClient::put(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder, const LLSD& headers, const F32 timeout)
-{
- put_urls.push_back(url);
- put_responders.push_back(responder);
- put_body.push_back(body);
- put_headers.push_back(headers);
-
-}
-
-std::vector<std::string> delete_urls;
-std::vector<LLCurl::ResponderPtr> delete_responders;
-
-void LLHTTPClient::del(
- const std::string& url,
- LLCurl::ResponderPtr responder,
- const LLSD& headers,
- const F32 timeout)
-{
- delete_urls.push_back(url);
- delete_responders.push_back(responder);
-}
-
-namespace tut
-{
- struct LLHTTPClientAdapterData
- {
- LLHTTPClientAdapterData()
- {
- get_urls.clear();
- get_responders.clear();
- put_urls.clear();
- put_responders.clear();
- put_body.clear();
- put_headers.clear();
- delete_urls.clear();
- delete_responders.clear();
- }
- };
-
- typedef test_group<LLHTTPClientAdapterData> factory;
- typedef factory::object object;
-}
-
-namespace
-{
- tut::factory tf("LLHTTPClientAdapterData");
-}
-
-namespace tut
-{
- // Ensure we can create the object
- template<> template<>
- void object::test<1>()
- {
- LLHTTPClientAdapter adapter;
- }
-
- // Does the get pass the appropriate arguments to the LLHTTPClient
- template<> template<>
- void object::test<2>()
- {
- LLHTTPClientAdapter adapter;
-
- LLCurl::ResponderPtr responder = new LLCurl::Responder();
-
- adapter.get("Made up URL", responder);
- ensure_equals(get_urls.size(), 1);
- ensure_equals(get_urls[0], "Made up URL");
- }
-
- // Ensure the responder matches the one passed to get
- template<> template<>
- void object::test<3>()
- {
- LLHTTPClientAdapter adapter;
- LLCurl::ResponderPtr responder = new LLCurl::Responder();
-
- adapter.get("Made up URL", responder);
-
- ensure_equals(get_responders.size(), 1);
- ensure_equals(get_responders[0].get(), responder.get());
- }
-
- // Ensure the correct url is used in the put
- template<> template<>
- void object::test<4>()
- {
- LLHTTPClientAdapter adapter;
-
- LLCurl::ResponderPtr responder = new LLCurl::Responder();
-
- LLSD body;
- body["TestBody"] = "Foobar";
-
- adapter.put("Made up URL", body, responder);
- ensure_equals(put_urls.size(), 1);
- ensure_equals(put_urls[0], "Made up URL");
- }
-
- // Ensure the correct responder is used by put
- template<> template<>
- void object::test<5>()
- {
- LLHTTPClientAdapter adapter;
-
- LLCurl::ResponderPtr responder = new LLCurl::Responder();
-
- LLSD body;
- body["TestBody"] = "Foobar";
-
- adapter.put("Made up URL", body, responder);
-
- ensure_equals(put_responders.size(), 1);
- ensure_equals(put_responders[0].get(), responder.get());
- }
-
- // Ensure the message body is passed through the put properly
- template<> template<>
- void object::test<6>()
- {
- LLHTTPClientAdapter adapter;
-
- LLCurl::ResponderPtr responder = new LLCurl::Responder();
-
- LLSD body;
- body["TestBody"] = "Foobar";
-
- adapter.put("Made up URL", body, responder);
-
- ensure_equals(put_body.size(), 1);
- ensure_equals(put_body[0]["TestBody"].asString(), "Foobar");
- }
-
- // Ensure that headers are passed through put properly
- template<> template<>
- void object::test<7>()
- {
- LLHTTPClientAdapter adapter;
-
- LLCurl::ResponderPtr responder = new LLCurl::Responder();
-
- LLSD body = LLSD::emptyMap();
- body["TestBody"] = "Foobar";
-
- LLSD headers = LLSD::emptyMap();
- headers["booger"] = "omg";
-
- adapter.put("Made up URL", body, responder, headers);
-
- ensure_equals("Header count", put_headers.size(), 1);
- ensure_equals(
- "First header",
- put_headers[0]["booger"].asString(),
- "omg");
- }
-
- // Ensure that del() passes appropriate arguments to the LLHTTPClient
- template<> template<>
- void object::test<8>()
- {
- LLHTTPClientAdapter adapter;
-
- LLCurl::ResponderPtr responder = new LLCurl::Responder();
-
- adapter.del("Made up URL", responder);
-
- ensure_equals("URL count", delete_urls.size(), 1);
- ensure_equals("Received URL", delete_urls[0], "Made up URL");
-
- ensure_equals("Responder count", delete_responders.size(), 1);
- //ensure_equals("Responder", delete_responders[0], responder);
- }
-}
-
diff --git a/indra/llmessage/tests/llsdmessage_test.cpp b/indra/llmessage/tests/llsdmessage_test.cpp
deleted file mode 100755
index 44b024a83f..0000000000
--- a/indra/llmessage/tests/llsdmessage_test.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-/**
- * @file llsdmessage_test.cpp
- * @author Nat Goodspeed
- * @date 2008-12-22
- * @brief Test of llsdmessage.h
- *
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#if LL_WINDOWS
-#pragma warning (disable : 4675) // "resolved by ADL" -- just as I want!
-#endif
-
-// Precompiled header
-#include "linden_common.h"
-// associated header
-#include "llsdmessage.h"
-// STL headers
-#include <iostream>
-// std headers
-#include <stdexcept>
-#include <typeinfo>
-// external library headers
-// other Linden headers
-#include "../test/lltut.h"
-#include "../test/catch_and_store_what_in.h"
-#include "llsdserialize.h"
-#include "llevents.h"
-#include "stringize.h"
-#include "llhost.h"
-#include "tests/networkio.h"
-#include "tests/commtest.h"
-
-/*****************************************************************************
-* TUT
-*****************************************************************************/
-namespace tut
-{
- struct llsdmessage_data: public commtest_data
- {
- LLEventPump& httpPump;
-
- llsdmessage_data():
- httpPump(pumps.obtain("LLHTTPClient"))
- {
- LLCurl::initClass();
- LLSDMessage::link();
- }
- };
- typedef test_group<llsdmessage_data> llsdmessage_group;
- typedef llsdmessage_group::object llsdmessage_object;
- llsdmessage_group llsdmgr("llsdmessage");
-
- template<> template<>
- void llsdmessage_object::test<1>()
- {
- std::string threw;
- // This should fail...
- try
- {
- LLSDMessage localListener;
- }
- CATCH_AND_STORE_WHAT_IN(threw, LLEventPump::DupPumpName)
- ensure("second LLSDMessage should throw", ! threw.empty());
- }
-
- template<> template<>
- void llsdmessage_object::test<2>()
- {
- LLSD request, body;
- body["data"] = "yes";
- request["payload"] = body;
- request["reply"] = replyPump.getName();
- request["error"] = errorPump.getName();
- bool threw = false;
- try
- {
- httpPump.post(request);
- }
- catch (const LLSDMessage::ArgError&)
- {
- threw = true;
- }
- ensure("missing URL", threw);
- }
-
- template<> template<>
- void llsdmessage_object::test<3>()
- {
- LLSD request, body;
- body["data"] = "yes";
- request["url"] = server + "got-message";
- request["payload"] = body;
- request["reply"] = replyPump.getName();
- request["error"] = errorPump.getName();
- httpPump.post(request);
- ensure("got response", netio.pump());
- ensure("success response", success);
- ensure_equals(result["reply"].asString(), "success");
-
- body["status"] = 499;
- body["reason"] = "custom error message";
- request["url"] = server + "fail";
- request["payload"] = body;
- httpPump.post(request);
- ensure("got response", netio.pump());
- ensure("failure response", ! success);
- ensure_equals(result["status"].asInteger(), body["status"].asInteger());
- ensure_equals(result["reason"].asString(), body["reason"].asString());
- }
-} // namespace tut
diff --git a/indra/llmessage/tests/lltesthttpclientadapter.cpp b/indra/llmessage/tests/lltesthttpclientadapter.cpp
deleted file mode 100755
index 4539e4a540..0000000000
--- a/indra/llmessage/tests/lltesthttpclientadapter.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-/**
- * @file
- * @brief
- *
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-#include "lltesthttpclientadapter.h"
-
-LLTestHTTPClientAdapter::LLTestHTTPClientAdapter()
-{
-}
-
-LLTestHTTPClientAdapter::~LLTestHTTPClientAdapter()
-{
-}
-
-void LLTestHTTPClientAdapter::get(const std::string& url, LLCurl::ResponderPtr responder)
-{
- mGetUrl.push_back(url);
- mGetResponder.push_back(responder);
-}
-
-void LLTestHTTPClientAdapter::put(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder)
-{
- mPutUrl.push_back(url);
- mPutBody.push_back(body);
- mPutResponder.push_back(responder);
-}
-
-U32 LLTestHTTPClientAdapter::putCalls() const
-{
- return mPutUrl.size();
-}
-
-void LLTestHTTPClientAdapter::get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers)
-{
- mGetUrl.push_back(url);
- mGetHeaders.push_back(headers);
- mGetResponder.push_back(responder);
-}
-
-
diff --git a/indra/llmessage/tests/lltesthttpclientadapter.h b/indra/llmessage/tests/lltesthttpclientadapter.h
deleted file mode 100755
index c29cbb3a2a..0000000000
--- a/indra/llmessage/tests/lltesthttpclientadapter.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
- * @file
- * @brief
- *
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-/* Macro Definitions */
-#ifndef LL_LLTESTHTTPCLIENTADAPTER_H
-#define LL_LLTESTHTTPCLIENTADAPTER_H
-
-
-#include "linden_common.h"
-#include "llhttpclientinterface.h"
-
-class LLTestHTTPClientAdapter : public LLHTTPClientInterface
-{
-public:
- LLTestHTTPClientAdapter();
- virtual ~LLTestHTTPClientAdapter();
- virtual void get(const std::string& url, LLCurl::ResponderPtr responder);
- virtual void get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers);
-
- virtual void put(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder);
- U32 putCalls() const;
-
- std::vector<LLSD> mPutBody;
- std::vector<LLSD> mGetHeaders;
- std::vector<std::string> mPutUrl;
- std::vector<std::string> mGetUrl;
- std::vector<LLCurl::ResponderPtr> mPutResponder;
- std::vector<LLCurl::ResponderPtr> mGetResponder;
-};
-
-
-
-#endif //LL_LLSIMULATORPRESENCESENDER_H
-