diff options
Diffstat (limited to 'indra')
136 files changed, 2537 insertions, 2027 deletions
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 5cce8ff2c4..31fac7caab 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -176,7 +176,6 @@ set(llcommon_HEADER_FILES llhandle.h llhash.h llheartbeat.h - llhttpstatuscodes.h llindexedqueue.h llinitparam.h llinstancetracker.h diff --git a/indra/llcommon/llhttpstatuscodes.h b/indra/llcommon/llhttpstatuscodes.h deleted file mode 100644 index 0173461dad..0000000000 --- a/indra/llcommon/llhttpstatuscodes.h +++ /dev/null @@ -1,89 +0,0 @@ -/** - * @file llhttpstatuscodes.h - * @brief Constants for HTTP status codes - * - * $LicenseInfo:firstyear=2001&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_STATUS_CODES_H -#define LL_HTTP_STATUS_CODES_H - -#include "stdtypes.h" - -// Standard errors from HTTP spec: -// http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1 -const S32 HTTP_CONTINUE = 100; -const S32 HTTP_SWITCHING_PROTOCOLS = 101; - -// Success -const S32 HTTP_OK = 200; -const S32 HTTP_CREATED = 201; -const S32 HTTP_ACCEPTED = 202; -const S32 HTTP_NON_AUTHORITATIVE_INFORMATION = 203; -const S32 HTTP_NO_CONTENT = 204; -const S32 HTTP_RESET_CONTENT = 205; -const S32 HTTP_PARTIAL_CONTENT = 206; - -// Redirection -const S32 HTTP_MULTIPLE_CHOICES = 300; -const S32 HTTP_MOVED_PERMANENTLY = 301; -const S32 HTTP_FOUND = 302; -const S32 HTTP_SEE_OTHER = 303; -const S32 HTTP_NOT_MODIFIED = 304; -const S32 HTTP_USE_PROXY = 305; -const S32 HTTP_TEMPORARY_REDIRECT = 307; - -// Client Error -const S32 HTTP_BAD_REQUEST = 400; -const S32 HTTP_UNAUTHORIZED = 401; -const S32 HTTP_PAYMENT_REQUIRED = 402; -const S32 HTTP_FORBIDDEN = 403; -const S32 HTTP_NOT_FOUND = 404; -const S32 HTTP_METHOD_NOT_ALLOWED = 405; -const S32 HTTP_NOT_ACCEPTABLE = 406; -const S32 HTTP_PROXY_AUTHENTICATION_REQUIRED = 407; -const S32 HTTP_REQUEST_TIME_OUT = 408; -const S32 HTTP_CONFLICT = 409; -const S32 HTTP_GONE = 410; -const S32 HTTP_LENGTH_REQUIRED = 411; -const S32 HTTP_PRECONDITION_FAILED = 412; -const S32 HTTP_REQUEST_ENTITY_TOO_LARGE = 413; -const S32 HTTP_REQUEST_URI_TOO_LARGE = 414; -const S32 HTTP_UNSUPPORTED_MEDIA_TYPE = 415; -const S32 HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416; -const S32 HTTP_EXPECTATION_FAILED = 417; - -// Server Error -const S32 HTTP_INTERNAL_SERVER_ERROR = 500; -const S32 HTTP_NOT_IMPLEMENTED = 501; -const S32 HTTP_BAD_GATEWAY = 502; -const S32 HTTP_SERVICE_UNAVAILABLE = 503; -const S32 HTTP_GATEWAY_TIME_OUT = 504; -const S32 HTTP_VERSION_NOT_SUPPORTED = 505; - -// We combine internal process errors with status codes -// These status codes should not be sent over the wire -// and indicate something went wrong internally. -// If you get these they are not normal. -const S32 HTTP_INTERNAL_ERROR = 499; - -#endif diff --git a/indra/llcommon/llsd.cpp b/indra/llcommon/llsd.cpp index 8276ec836a..9e4b92227e 100644 --- a/indra/llcommon/llsd.cpp +++ b/indra/llcommon/llsd.cpp @@ -126,7 +126,9 @@ public: virtual UUID asUUID() const { return LLUUID(); } virtual Date asDate() const { return LLDate(); } virtual URI asURI() const { return LLURI(); } - virtual Binary asBinary() const { return std::vector<U8>(); } + virtual const Binary& asBinary() const { static const std::vector<U8> empty; return empty; } + + virtual const String& asStringRef() const { static const std::string empty; return empty; } virtual bool has(const String&) const { return false; } virtual LLSD get(const String&) const { return LLSD(); } @@ -270,6 +272,7 @@ namespace virtual LLSD::Date asDate() const { return LLDate(mValue); } virtual LLSD::URI asURI() const { return LLURI(mValue); } virtual int size() const { return mValue.size(); } + virtual const LLSD::String& asStringRef() const { return mValue; } }; LLSD::Integer ImplString::asInteger() const @@ -348,7 +351,7 @@ namespace public: ImplBinary(const LLSD::Binary& v) : Base(v) { } - virtual LLSD::Binary asBinary() const{ return mValue; } + virtual const LLSD::Binary& asBinary() const{ return mValue; } }; @@ -838,7 +841,9 @@ LLSD::String LLSD::asString() const { return safe(impl).asString(); } LLSD::UUID LLSD::asUUID() const { return safe(impl).asUUID(); } LLSD::Date LLSD::asDate() const { return safe(impl).asDate(); } LLSD::URI LLSD::asURI() const { return safe(impl).asURI(); } -LLSD::Binary LLSD::asBinary() const { return safe(impl).asBinary(); } +const LLSD::Binary& LLSD::asBinary() const { return safe(impl).asBinary(); } + +const LLSD::String& LLSD::asStringRef() const { return safe(impl).asStringRef(); } // const char * helpers LLSD::LLSD(const char* v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); } diff --git a/indra/llcommon/llsd.h b/indra/llcommon/llsd.h index 5eb69059ac..b9f490718c 100644 --- a/indra/llcommon/llsd.h +++ b/indra/llcommon/llsd.h @@ -249,7 +249,10 @@ public: UUID asUUID() const; Date asDate() const; URI asURI() const; - Binary asBinary() const; + const Binary& asBinary() const; + + // asStringRef on any non-string type will return a ref to an empty string. + const String& asStringRef() const; operator Boolean() const { return asBoolean(); } operator Integer() const { return asInteger(); } diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp index ad4fce6f35..774d827762 100644 --- a/indra/llcommon/llsdserialize.cpp +++ b/indra/llcommon/llsdserialize.cpp @@ -873,7 +873,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const { /** * Undefined: '!'<br> - * Boolean: 't' for true 'f' for false<br> + * Boolean: '1' for true '0' for false<br> * Integer: 'i' + 4 bytes network byte order<br> * Real: 'r' + 8 bytes IEEE double<br> * UUID: 'u' + 16 byte unsigned integer<br> @@ -1261,12 +1261,37 @@ std::string LLSDNotationFormatter::escapeString(const std::string& in) // virtual S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 options) const { + S32 rv = format_impl(data, ostr, options, 0); + return rv; +} + +S32 LLSDNotationFormatter::format_impl(const LLSD& data, std::ostream& ostr, U32 options, U32 level) const +{ S32 format_count = 1; + std::string pre; + std::string post; + + if (options & LLSDFormatter::OPTIONS_PRETTY) + { + for (U32 i = 0; i < level; i++) + { + pre += " "; + } + post = "\n"; + } + switch(data.type()) { case LLSD::TypeMap: { + if (0 != level) ostr << post << pre; ostr << "{"; + std::string inner_pre; + if (options & LLSDFormatter::OPTIONS_PRETTY) + { + inner_pre = pre + " "; + } + bool need_comma = false; LLSD::map_const_iterator iter = data.beginMap(); LLSD::map_const_iterator end = data.endMap(); @@ -1274,18 +1299,18 @@ S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 opti { if(need_comma) ostr << ","; need_comma = true; - ostr << '\''; + ostr << post << inner_pre << '\''; serialize_string((*iter).first, ostr); ostr << "':"; - format_count += format((*iter).second, ostr); + format_count += format_impl((*iter).second, ostr, options, level + 2); } - ostr << "}"; + ostr << post << pre << "}"; break; } case LLSD::TypeArray: { - ostr << "["; + ostr << post << pre << "["; bool need_comma = false; LLSD::array_const_iterator iter = data.beginArray(); LLSD::array_const_iterator end = data.endArray(); @@ -1293,7 +1318,7 @@ S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 opti { if(need_comma) ostr << ","; need_comma = true; - format_count += format(*iter, ostr); + format_count += format_impl(*iter, ostr, options, level + 1); } ostr << "]"; break; @@ -1343,7 +1368,7 @@ S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 opti case LLSD::TypeString: ostr << '\''; - serialize_string(data.asString(), ostr); + serialize_string(data.asStringRef(), ostr); ostr << '\''; break; @@ -1360,9 +1385,26 @@ S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 opti case LLSD::TypeBinary: { // *FIX: memory inefficient. - std::vector<U8> buffer = data.asBinary(); + const std::vector<U8>& buffer = data.asBinary(); ostr << "b(" << buffer.size() << ")\""; - if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size()); + if(buffer.size()) + { + if (options & LLSDFormatter::OPTIONS_PRETTY_BINARY) + { + std::ios_base::fmtflags old_flags = ostr.flags(); + ostr.setf( std::ios::hex, std::ios::basefield ); + ostr << "0x"; + for (int i = 0; i < buffer.size(); i++) + { + ostr << (int) buffer[i]; + } + ostr.flags(old_flags); + } + else + { + ostr.write((const char*)&buffer[0], buffer.size()); + } + } ostr << "\""; break; } @@ -1460,7 +1502,7 @@ S32 LLSDBinaryFormatter::format(const LLSD& data, std::ostream& ostr, U32 option case LLSD::TypeString: ostr.put('s'); - formatString(data.asString(), ostr); + formatString(data.asStringRef(), ostr); break; case LLSD::TypeDate: @@ -1478,9 +1520,8 @@ S32 LLSDBinaryFormatter::format(const LLSD& data, std::ostream& ostr, U32 option case LLSD::TypeBinary: { - // *FIX: memory inefficient. ostr.put('b'); - std::vector<U8> buffer = data.asBinary(); + const std::vector<U8>& buffer = data.asBinary(); U32 size_nbo = htonl(buffer.size()); ostr.write((const char*)(&size_nbo), sizeof(U32)); if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size()); diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h index e7a5507385..23a0c8cfb1 100644 --- a/indra/llcommon/llsdserialize.h +++ b/indra/llcommon/llsdserialize.h @@ -416,7 +416,8 @@ public: typedef enum e_formatter_options_type { OPTIONS_NONE = 0, - OPTIONS_PRETTY = 1 + OPTIONS_PRETTY = 1, + OPTIONS_PRETTY_BINARY = 2 } EFormatterOptions; /** @@ -507,6 +508,17 @@ public: * @return Returns The number of LLSD objects fomatted out */ virtual S32 format(const LLSD& data, std::ostream& ostr, U32 options = LLSDFormatter::OPTIONS_NONE) const; + +protected: + + /** + * @brief Implementation to format the data. This is called recursively. + * + * @param data The data to write. + * @param ostr The destination stream for the data. + * @return Returns The number of LLSD objects fomatted out + */ + S32 format_impl(const LLSD& data, std::ostream& ostr, U32 options, U32 level) const; }; @@ -634,7 +646,7 @@ protected: * </code> * * *NOTE - formerly this class inherited from its template parameter Formatter, - * but all insnatiations passed in LLRefCount subclasses. This conflicted with + * but all instantiations passed in LLRefCount subclasses. This conflicted with * the auto allocation intended for this class template (demonstrated in the * example above). -brad */ @@ -720,6 +732,18 @@ public: LLPointer<LLSDNotationFormatter> f = new LLSDNotationFormatter; return f->format(sd, str, LLSDFormatter::OPTIONS_NONE); } + static S32 toPrettyNotation(const LLSD& sd, std::ostream& str) + { + LLPointer<LLSDNotationFormatter> f = new LLSDNotationFormatter; + return f->format(sd, str, LLSDFormatter::OPTIONS_PRETTY); + } + static S32 toPrettyBinaryNotation(const LLSD& sd, std::ostream& str) + { + LLPointer<LLSDNotationFormatter> f = new LLSDNotationFormatter; + return f->format(sd, str, + LLSDFormatter::OPTIONS_PRETTY | + LLSDFormatter::OPTIONS_PRETTY_BINARY); + } static S32 fromNotation(LLSD& sd, std::istream& str, S32 max_bytes) { LLPointer<LLSDNotationParser> p = new LLSDNotationParser; diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp index cef743a7be..3ef7a7e4c1 100644 --- a/indra/llcommon/llsdserialize_xml.cpp +++ b/indra/llcommon/llsdserialize_xml.cpp @@ -168,8 +168,8 @@ S32 LLSDXMLFormatter::format_impl(const LLSD& data, std::ostream& ostr, U32 opti break; case LLSD::TypeString: - if(data.asString().empty()) ostr << pre << "<string />" << post; - else ostr << pre << "<string>" << escapeString(data.asString()) <<"</string>" << post; + if(data.asStringRef().empty()) ostr << pre << "<string />" << post; + else ostr << pre << "<string>" << escapeString(data.asStringRef()) <<"</string>" << post; break; case LLSD::TypeDate: @@ -182,7 +182,7 @@ S32 LLSDXMLFormatter::format_impl(const LLSD& data, std::ostream& ostr, U32 opti case LLSD::TypeBinary: { - LLSD::Binary buffer = data.asBinary(); + const LLSD::Binary& buffer = data.asBinary(); if(buffer.empty()) { ostr << pre << "<binary />" << post; @@ -375,13 +375,10 @@ S32 LLSDXMLParser::Impl::parse(std::istream& input, LLSD& data) { break; } + count = get_till_eol(input, (char *)buffer, BUFFER_SIZE); + if (!count) { - - count = get_till_eol(input, (char *)buffer, BUFFER_SIZE); - if (!count) - { - break; - } + break; } status = XML_ParseBuffer(mParser, count, false); diff --git a/indra/llcorehttp/_httplibcurl.cpp b/indra/llcorehttp/_httplibcurl.cpp index 6fe0bfc7d1..9ea831a771 100644 --- a/indra/llcorehttp/_httplibcurl.cpp +++ b/indra/llcorehttp/_httplibcurl.cpp @@ -31,7 +31,7 @@ #include "_httpoprequest.h" #include "_httppolicy.h" -#include "llhttpstatuscodes.h" +#include "llhttpconstants.h" namespace LLCore diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp index 7db19b1841..5e703cd183 100644 --- a/indra/llcorehttp/_httpoprequest.cpp +++ b/indra/llcorehttp/_httpoprequest.cpp @@ -44,7 +44,7 @@ #include "_httplibcurl.h" #include "_httpinternal.h" -#include "llhttpstatuscodes.h" +#include "llhttpconstants.h" #include "llproxy.h" namespace @@ -479,6 +479,7 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service) curl_easy_setopt(mCurlHandle, CURLOPT_INFILESIZE, data_size); curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDS, (void *) NULL); mCurlHeaders = curl_slist_append(mCurlHeaders, "Expect:"); + // *TODO: Should this be 'Keep-Alive' ? mCurlHeaders = curl_slist_append(mCurlHeaders, "Connection: keep-alive"); mCurlHeaders = curl_slist_append(mCurlHeaders, "Keep-alive: 300"); } diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp index fb2d43e3b0..b86e73c690 100644 --- a/indra/llcrashlogger/llcrashlogger.cpp +++ b/indra/llcrashlogger/llcrashlogger.cpp @@ -50,18 +50,21 @@ BOOL gSent = false; class LLCrashLoggerResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLCrashLoggerResponder); public: LLCrashLoggerResponder() { } - virtual void error(U32 status, const std::string& reason) +protected: + virtual void httpFailure() { + llwarns << dumpResponse() << llendl; gBreak = true; } - virtual void result(const LLSD& content) - { + virtual void httpSuccess() + { gBreak = true; gSent = true; } diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt index 1a90c32fe4..181718f465 100644 --- a/indra/llmessage/CMakeLists.txt +++ b/indra/llmessage/CMakeLists.txt @@ -43,6 +43,7 @@ set(llmessage_SOURCE_FILES llhttpassetstorage.cpp llhttpclient.cpp llhttpclientadapter.cpp + llhttpconstants.cpp llhttpnode.cpp llhttpsender.cpp llinstantmessage.cpp @@ -67,7 +68,6 @@ set(llmessage_SOURCE_FILES llpartdata.cpp llproxy.cpp llpumpio.cpp - llregionpresenceverifier.cpp llsdappservices.cpp llsdhttpserver.cpp llsdmessage.cpp @@ -135,6 +135,7 @@ set(llmessage_HEADER_FILES llhttpclient.h llhttpclientinterface.h llhttpclientadapter.h + llhttpconstants.h llhttpnode.h llhttpnodeadapter.h llhttpsender.h @@ -166,7 +167,6 @@ set(llmessage_HEADER_FILES llqueryflags.h llregionflags.h llregionhandle.h - llregionpresenceverifier.h llsdappservices.h llsdhttpserver.h llsdmessage.h @@ -230,17 +230,15 @@ target_link_libraries( # tests if (LL_TESTS) SET(llmessage_TEST_SOURCE_FILES - # llhttpclientadapter.cpp - llmime.cpp llnamevalue.cpp lltrustedmessageservice.cpp lltemplatemessagedispatcher.cpp - llregionpresenceverifier.cpp ) 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} @@ -267,6 +265,8 @@ if (LL_TESTS) 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(llmime "" "${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/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp index f9e3ad26f7..87c4b5952c 100644 --- a/indra/llmessage/llavatarnamecache.cpp +++ b/indra/llmessage/llavatarnamecache.cpp @@ -126,7 +126,7 @@ namespace LLAvatarNameCache // Erase expired names from cache void eraseUnrefreshed(); - bool expirationFromCacheControl(LLSD headers, F64 *expires); + bool expirationFromCacheControl(const LLSD& headers, F64 *expires); } /* Sample response: @@ -170,33 +170,31 @@ namespace LLAvatarNameCache class LLAvatarNameResponder : public LLHTTPClient::Responder { + 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; - // Need the headers to look up Expires: and Retry-After: - LLSD mHeaders; - public: LLAvatarNameResponder(const std::vector<LLUUID>& agent_ids) - : mAgentIDs(agent_ids), - mHeaders() + : mAgentIDs(agent_ids) { } - /*virtual*/ void completedHeader(U32 status, const std::string& reason, - const LLSD& headers) - { - mHeaders = headers; - } - - /*virtual*/ void result(const LLSD& content) +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(mHeaders); + F64 expires = LLAvatarNameCache::nameExpirationFromHeaders(getResponseHeaders()); F64 now = LLFrameTimer::getTotalSeconds(); - LLSD agents = content["agents"]; + const LLSD& agents = content["agents"]; LLSD::array_const_iterator it = agents.beginArray(); for ( ; it != agents.endArray(); ++it) { @@ -226,7 +224,7 @@ public: } // Same logic as error response case - LLSD unresolved_agents = content["bad_ids"]; + const LLSD& unresolved_agents = content["bad_ids"]; S32 num_unresolved = unresolved_agents.size(); if (num_unresolved > 0) { @@ -250,14 +248,13 @@ public: << LL_ENDL; } - /*virtual*/ void error(U32 status, const std::string& reason) + /*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") << "LLAvatarNameResponder::error " << status << " " << reason - << LL_ENDL; + 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(); @@ -748,7 +745,7 @@ void LLAvatarNameCache::insert(const LLUUID& agent_id, const LLAvatarName& av_na sCache[agent_id] = av_name; } -F64 LLAvatarNameCache::nameExpirationFromHeaders(LLSD headers) +F64 LLAvatarNameCache::nameExpirationFromHeaders(const LLSD& headers) { F64 expires = 0.0; if (expirationFromCacheControl(headers, &expires)) @@ -764,17 +761,25 @@ F64 LLAvatarNameCache::nameExpirationFromHeaders(LLSD headers) } } -bool LLAvatarNameCache::expirationFromCacheControl(LLSD headers, F64 *expires) +bool LLAvatarNameCache::expirationFromCacheControl(const LLSD& headers, F64 *expires) { bool fromCacheControl = false; F64 now = LLFrameTimer::getTotalSeconds(); // Allow the header to override the default - LLSD cache_control_header = headers["cache-control"]; - if (cache_control_header.isDefined()) + std::string cache_control; + if (headers.has(HTTP_HEADER_CACHE_CONTROL)) + { + cache_control = headers[HTTP_HEADER_CACHE_CONTROL].asString(); + } + else if (headers.has(HTTP_HEADER_LOWER_CACHE_CONTROL)) + { + cache_control = headers[HTTP_HEADER_LOWER_CACHE_CONTROL].asString(); + } + + if (!cache_control.empty()) { S32 max_age = 0; - std::string cache_control = cache_control_header.asString(); if (max_age_from_cache_control(cache_control, &max_age)) { *expires = now + (F64)max_age; diff --git a/indra/llmessage/llavatarnamecache.h b/indra/llmessage/llavatarnamecache.h index 79f170f7c8..42c76fe058 100644 --- a/indra/llmessage/llavatarnamecache.h +++ b/indra/llmessage/llavatarnamecache.h @@ -90,7 +90,7 @@ namespace LLAvatarNameCache // Compute name expiration time from HTTP Cache-Control header, // or return default value, in seconds from epoch. - F64 nameExpirationFromHeaders(LLSD headers); + F64 nameExpirationFromHeaders(const LLSD& headers); void addUseDisplayNamesCallback(const use_display_name_signal_t::slot_type& cb); } diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 47041a2880..1269b6bc5d 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -49,6 +49,7 @@ #include "llproxy.h" #include "llsdserialize.h" #include "llstl.h" +#include "llstring.h" #include "llthread.h" #include "lltimer.h" @@ -98,7 +99,7 @@ void check_curl_code(CURLcode code) { // linux appears to throw a curl error once per session for a bad initialization // at a pretty random time (when enabling cookies). - llinfos << "curl error detected: " << curl_easy_strerror(code) << llendl; + LL_WARNS("curl") << "curl error detected: " << curl_easy_strerror(code) << LL_ENDL; } } @@ -108,7 +109,7 @@ void check_curl_multi_code(CURLMcode code) { // linux appears to throw a curl error once per session for a bad initialization // at a pretty random time (when enabling cookies). - llinfos << "curl multi error detected: " << curl_multi_strerror(code) << llendl; + LL_WARNS("curl") << "curl multi error detected: " << curl_multi_strerror(code) << LL_ENDL; } } @@ -133,6 +134,7 @@ std::string LLCurl::getVersionString() ////////////////////////////////////////////////////////////////////////////// LLCurl::Responder::Responder() + : mHTTPMethod(HTTP_INVALID), mStatus(HTTP_INTERNAL_ERROR) { } @@ -142,22 +144,30 @@ LLCurl::Responder::~Responder() } // virtual -void LLCurl::Responder::errorWithContent( - U32 status, - const std::string& reason, - const LLSD&) +void LLCurl::Responder::httpFailure() { - error(status, reason); + LL_WARNS("curl") << dumpResponse() << LL_ENDL; } -// virtual -void LLCurl::Responder::error(U32 status, const std::string& reason) +std::string LLCurl::Responder::dumpResponse() const { - llinfos << mURL << " [" << status << "]: " << reason << llendl; + std::ostringstream s; + s << "[" << httpMethodAsVerb(mHTTPMethod) << ":" << mURL << "] " + << "[status:" << mStatus << "] " + << "[reason:" << mReason << "] "; + + if (mResponseHeaders.has(HTTP_HEADER_CONTENT_TYPE)) + { + s << "[content-type:" << mResponseHeaders[HTTP_HEADER_CONTENT_TYPE] << "] "; + } + + s << "[content:" << mContent << "]"; + + return s.str(); } // virtual -void LLCurl::Responder::result(const LLSD& content) +void LLCurl::Responder::httpSuccess() { } @@ -166,44 +176,124 @@ void LLCurl::Responder::setURL(const std::string& url) mURL = url; } +void LLCurl::Responder::successResult(const LLSD& content) +{ + setResult(HTTP_OK, "", content); + httpSuccess(); +} + +void LLCurl::Responder::failureResult(S32 status, const std::string& reason, const LLSD& content /* = LLSD() */) +{ + setResult(status, reason, content); + httpFailure(); +} + +void LLCurl::Responder::completeResult(S32 status, const std::string& reason, const LLSD& content /* = LLSD() */) +{ + setResult(status, reason, content); + httpCompleted(); +} + +void LLCurl::Responder::setResult(S32 status, const std::string& reason, const LLSD& content /* = LLSD() */) +{ + mStatus = status; + mReason = reason; + mContent = content; +} + +void LLCurl::Responder::setHTTPMethod(EHTTPMethod method) +{ + mHTTPMethod = method; +} + +void LLCurl::Responder::setResponseHeader(const std::string& header, const std::string& value) +{ + mResponseHeaders[header] = value; +} + +const std::string& LLCurl::Responder::getResponseHeader(const std::string& header, bool check_lower) const +{ + if (mResponseHeaders.has(header)) + { + return mResponseHeaders[header].asStringRef(); + } + if (check_lower) + { + std::string header_lower(header); + LLStringUtil::toLower(header_lower); + if (mResponseHeaders.has(header_lower)) + { + return mResponseHeaders[header_lower].asStringRef(); + } + } + static const std::string empty; + return empty; +} + +bool LLCurl::Responder::hasResponseHeader(const std::string& header, bool check_lower) const +{ + if (mResponseHeaders.has(header)) return true; + if (check_lower) + { + std::string header_lower(header); + LLStringUtil::toLower(header_lower); + return mResponseHeaders.has(header_lower); + } + return false; +} + // virtual void LLCurl::Responder::completedRaw( - U32 status, - const std::string& reason, const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer) { - LLSD content; LLBufferStream istr(channels, buffer.get()); - const bool emit_errors = false; - if (LLSDParser::PARSE_FAILURE == LLSDSerialize::fromXML(content, istr, emit_errors)) + const bool emit_parse_errors = false; + + std::string debug_body("(empty)"); + bool parsed=true; + if (EOF == istr.peek()) + { + parsed=false; + } + // Try to parse body as llsd, no matter what 'Content-Type' says. + else if (LLSDParser::PARSE_FAILURE == LLSDSerialize::fromXML(mContent, istr, emit_parse_errors)) + { + parsed=false; + char body[1025]; + body[1024] = '\0'; + istr.seekg(0, std::ios::beg); + istr.get(body,1024); + if (strlen(body) > 0) + { + mContent = body; + debug_body = body; + } + } + + // Only emit an warning if we failed to parse when 'Content-Type' == 'application/llsd+xml' + if (!parsed && (HTTP_CONTENT_LLSD_XML == getResponseHeader(HTTP_HEADER_CONTENT_TYPE))) { - llinfos << "Failed to deserialize LLSD. " << mURL << " [" << status << "]: " << reason << llendl; - content["reason"] = reason; + llwarns << "Failed to deserialize . " << mURL << " [status:" << mStatus << "] " + << "(" << mReason << ") body: " << debug_body << llendl; } - completed(status, reason, content); + httpCompleted(); } // virtual -void LLCurl::Responder::completed(U32 status, const std::string& reason, const LLSD& content) +void LLCurl::Responder::httpCompleted() { - if (isGoodStatus(status)) + if (isGoodStatus()) { - result(content); + httpSuccess(); } else { - errorWithContent(status, reason, content); + httpFailure(); } } -//virtual -void LLCurl::Responder::completedHeader(U32 status, const std::string& reason, const LLSD& content) -{ - -} - ////////////////////////////////////////////////////////////////////////////// std::set<CURL*> LLCurl::Easy::sFreeHandles; @@ -287,7 +377,8 @@ LLCurl::Easy* LLCurl::Easy::getEasy() if (!easy->mCurlEasyHandle) { // this can happen if we have too many open files (fails in c-ares/ares_init.c) - llwarns << "allocEasyHandle() returned NULL! Easy handles: " << gCurlEasyCount << " Multi handles: " << gCurlMultiCount << llendl; + LL_WARNS("curl") << "allocEasyHandle() returned NULL! Easy handles: " + << gCurlEasyCount << " Multi handles: " << gCurlMultiCount << LL_ENDL; delete easy; return NULL; } @@ -312,10 +403,14 @@ LLCurl::Easy::~Easy() for_each(mStrings.begin(), mStrings.end(), DeletePointerArray()); LL_CHECK_MEMORY if (mResponder && LLCurl::sNotQuitting) //aborted - { - std::string reason("Request timeout, aborted.") ; - mResponder->completedRaw(408, //HTTP_REQUEST_TIME_OUT, timeout, abort - reason, mChannels, mOutput); + { + // HTTP_REQUEST_TIME_OUT, timeout, abort + // *TODO: This looks like improper use of the 408 status code. + // See: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.9 + // This status code should be returned by the *server* when: + // "The client did not produce a request within the time that the server was prepared to wait." + mResponder->setResult(HTTP_REQUEST_TIME_OUT, "Request timeout, aborted."); + mResponder->completedRaw(mChannels, mOutput); LL_CHECK_MEMORY } mResponder = NULL; @@ -379,9 +474,9 @@ void LLCurl::Easy::getTransferInfo(LLCurl::TransferInfo* info) check_curl_code(curl_easy_getinfo(mCurlEasyHandle, CURLINFO_SPEED_DOWNLOAD, &info->mSpeedDownload)); } -U32 LLCurl::Easy::report(CURLcode code) +S32 LLCurl::Easy::report(CURLcode code) { - U32 responseCode = 0; + S32 responseCode = 0; std::string responseReason; if (code == CURLE_OK) @@ -391,14 +486,15 @@ U32 LLCurl::Easy::report(CURLcode code) } else { - responseCode = 499; + responseCode = HTTP_INTERNAL_ERROR; responseReason = strerror(code) + " : " + mErrorBuffer; setopt(CURLOPT_FRESH_CONNECT, TRUE); } if (mResponder) { - mResponder->completedRaw(responseCode, responseReason, mChannels, mOutput); + mResponder->setResult(responseCode, responseReason); + mResponder->completedRaw(mChannels, mOutput); mResponder = NULL; } @@ -435,9 +531,31 @@ void LLCurl::Easy::setoptString(CURLoption option, const std::string& value) check_curl_code(result); } +void LLCurl::Easy::slist_append(const std::string& header, const std::string& value) +{ + std::string pair(header); + if (value.empty()) + { + pair += ":"; + } + else + { + pair += ": "; + pair += value; + } + slist_append(pair.c_str()); +} + void LLCurl::Easy::slist_append(const char* str) { - mHeaders = curl_slist_append(mHeaders, str); + if (str) + { + mHeaders = curl_slist_append(mHeaders, str); + if (!mHeaders) + { + llwarns << "curl_slist_append() call returned NULL appending " << str << llendl; + } + } } size_t curlReadCallback(char* data, size_t size, size_t nmemb, void* user_data) @@ -524,8 +642,9 @@ void LLCurl::Easy::prepRequest(const std::string& url, if (!post) { - slist_append("Connection: keep-alive"); - slist_append("Keep-alive: 300"); + // *TODO: Should this be set to 'Keep-Alive' ? + slist_append(HTTP_HEADER_CONNECTION, "keep-alive"); + slist_append(HTTP_HEADER_KEEP_ALIVE, "300"); // Accept and other headers for (std::vector<std::string>::const_iterator iter = headers.begin(); iter != headers.end(); ++iter) @@ -804,7 +923,7 @@ S32 LLCurl::Multi::process() ++processed; if (msg->msg == CURLMSG_DONE) { - U32 response = 0; + S32 response = 0; Easy* easy = NULL ; { @@ -823,7 +942,7 @@ S32 LLCurl::Multi::process() } else { - response = 499; + response = HTTP_INTERNAL_ERROR; //*TODO: change to llwarns llerrs << "cleaned up curl request completed!" << llendl; } @@ -1122,13 +1241,13 @@ bool LLCurlRequest::getByteRange(const std::string& url, easy->setopt(CURLOPT_HTTPGET, 1); if (length > 0) { - std::string range = llformat("Range: bytes=%d-%d", offset,offset+length-1); - easy->slist_append(range.c_str()); + std::string range = llformat("bytes=%d-%d", offset,offset+length-1); + easy->slist_append(HTTP_HEADER_RANGE, range); } else if (offset > 0) { - std::string range = llformat("Range: bytes=%d-", offset); - easy->slist_append(range.c_str()); + std::string range = llformat("bytes=%d-", offset); + easy->slist_append(HTTP_HEADER_RANGE, range); } easy->setHeaders(); bool res = addEasy(easy); @@ -1155,7 +1274,7 @@ bool LLCurlRequest::post(const std::string& url, easy->setopt(CURLOPT_POSTFIELDS, (void*)NULL); easy->setopt(CURLOPT_POSTFIELDSIZE, bytes); - easy->slist_append("Content-Type: application/llsd+xml"); + easy->slist_append(HTTP_HEADER_CONTENT_TYPE, HTTP_CONTENT_LLSD_XML); easy->setHeaders(); lldebugs << "POSTING: " << bytes << " bytes." << llendl; @@ -1183,7 +1302,7 @@ bool LLCurlRequest::post(const std::string& url, easy->setopt(CURLOPT_POSTFIELDS, (void*)NULL); easy->setopt(CURLOPT_POSTFIELDSIZE, bytes); - easy->slist_append("Content-Type: application/octet-stream"); + easy->slist_append(HTTP_HEADER_CONTENT_TYPE, HTTP_CONTENT_OCTET_STREAM); easy->setHeaders(); lldebugs << "POSTING: " << bytes << " bytes." << llendl; @@ -1555,6 +1674,14 @@ void LLCurlEasyRequest::setSSLCtxCallback(curl_ssl_ctx_callback callback, void* } } +void LLCurlEasyRequest::slist_append(const std::string& header, const std::string& value) +{ + if (isValid() && mEasy) + { + mEasy->slist_append(header, value); + } +} + void LLCurlEasyRequest::slist_append(const char* str) { if (isValid() && mEasy) diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h index 7bcf61e233..c72e1e493a 100644 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -39,6 +39,7 @@ #include <curl/curl.h> // TODO: remove dependency #include "llbuffer.h" +#include "llhttpconstants.h" #include "lliopipe.h" #include "llsd.h" #include "llthread.h" @@ -77,59 +78,92 @@ public: Responder(); virtual ~Responder(); - /** - * @brief return true if the status code indicates success. - */ - static bool isGoodStatus(U32 status) + virtual bool followRedir() { - return((200 <= status) && (status < 300)); + return false; } - - virtual void errorWithContent( - U32 status, - const std::string& reason, - const LLSD& content); - //< called by completed() on bad status - - virtual void error(U32 status, const std::string& reason); - //< called by default error(status, reason, content) - - virtual void result(const LLSD& content); - //< called by completed for good status codes. + /** + * @brief return true if the status code indicates success. + */ + bool isGoodStatus() const { return isHttpGoodStatus(mStatus); } + + S32 getStatus() const { return mStatus; } + const std::string& getReason() const { return mReason; } + const LLSD& getContent() const { return mContent; } + bool hasResponseHeader(const std::string& header, bool check_lower=false) const; + const std::string& getResponseHeader(const std::string& header, bool check_lower=true) const; + const LLSD& getResponseHeaders() const { return mResponseHeaders; } + const std::string& getURL() const { return mURL; } + EHTTPMethod getHTTPMethod() const { return mHTTPMethod; } + + // This formats response information for use in log spam. Includes content spam. + std::string dumpResponse() const; + + // Allows direct triggering of success/error with different results. + void completeResult(S32 status, const std::string& reason, const LLSD& content = LLSD()); + void successResult(const LLSD& content); + void failureResult(S32 status, const std::string& reason, const LLSD& content = LLSD()); + + // The default implementation will try to parse body content as an LLSD, however + // it should not spam about parsing failures unless the server sent a + // Content-Type: application/llsd+xml header. virtual void completedRaw( - U32 status, - const std::string& reason, const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer); /**< Override point for clients that may want to use this class when the response is some other format besides LLSD */ + - virtual void completed( - U32 status, - const std::string& reason, - const LLSD& content); - /**< The default implemetnation calls + // The http* methods are not public since these should be triggered internally + // after status, reason, content, etc have been set. + // If you need to trigger a completion method, use the *Result methods, above. + protected: + // These methods are the preferred way to process final results. + // By default, when one of these is called the following information will be resolved: + // * HTTP status code - getStatus() + // * Reason string - getReason() + // * Content - getContent() + // * Response Headers - getResponseHeaders() + + // By default, httpSuccess is triggered whenever httpCompleted is called with a 2xx status code. + virtual void httpSuccess(); + //< called by completed for good status codes. + + // By default, httpFailure is triggered whenever httpCompleted is called with a non-2xx status code. + virtual void httpFailure(); + //< called by httpCompleted() on bad status + + // httpCompleted does not generally need to be overridden, unless + // you don't care about the status code (which determine httpFailure or httpSuccess) + // or if you want to re-interpret what a 'good' vs' bad' status code is. + virtual void httpCompleted(); + /**< The default implementation calls either: - * result(), or - * error() + * httpSuccess(), or + * httpFailure() */ - - // Override to handle parsing of the header only. Note: this is the only place where the contents - // of the header can be parsed. In the ::completed call above only the body is contained in the LLSD. - virtual void completedHeader(U32 status, const std::string& reason, const LLSD& content); - - // Used internally to set the url for debugging later. - void setURL(const std::string& url); - virtual bool followRedir() - { - return false; - } + public: + void setHTTPMethod(EHTTPMethod method); + void setURL(const std::string& url); + void setResult(S32 status, const std::string& reason, const LLSD& content = LLSD()); + void setResponseHeader(const std::string& header, const std::string& value); private: + // These can be accessed by the get* methods. Treated as 'read-only' during completion handlers. + EHTTPMethod mHTTPMethod; std::string mURL; + LLSD mResponseHeaders; + + protected: + // These should also generally be treated as 'read-only' during completion handlers + // and should be accessed by the get* methods. The exception to this rule would + // be when overriding the completedRaw method in preparation for calling httpCompleted(). + S32 mStatus; + std::string mReason; + LLSD mContent; }; typedef LLPointer<Responder> ResponderPtr; @@ -225,10 +259,11 @@ public: // Copies the string so that it is guaranteed to stick around void setoptString(CURLoption option, const std::string& value); + void slist_append(const std::string& header, const std::string& value); void slist_append(const char* str); void setHeaders(); - U32 report(CURLcode); + S32 report(CURLcode); void getTransferInfo(LLCurl::TransferInfo* info); void prepRequest(const std::string& url, const std::vector<std::string>& headers, LLCurl::ResponderPtr, S32 time_out = 0, bool post = false); @@ -484,6 +519,7 @@ public: void setWriteCallback(curl_write_callback callback, void* userdata); void setReadCallback(curl_read_callback callback, void* userdata); void setSSLCtxCallback(curl_ssl_ctx_callback callback, void* userdata); + void slist_append(const std::string& header, const std::string& value); void slist_append(const char* str); void sendRequest(const std::string& url); void requestComplete(); diff --git a/indra/llmessage/llhttpassetstorage.cpp b/indra/llmessage/llhttpassetstorage.cpp index 7dcf160c9b..e841c8e3ed 100644 --- a/indra/llmessage/llhttpassetstorage.cpp +++ b/indra/llmessage/llhttpassetstorage.cpp @@ -51,13 +51,6 @@ const F32 GET_URL_TO_FILE_TIMEOUT = 1800.0f; const S32 COMPRESSED_INPUT_BUFFER_SIZE = 4096; -const S32 HTTP_OK = 200; -const S32 HTTP_PUT_OK = 201; -const S32 HTTP_NO_CONTENT = 204; -const S32 HTTP_MISSING = 404; -const S32 HTTP_SERVER_BAD_GATEWAY = 502; -const S32 HTTP_SERVER_TEMP_UNAVAILABLE = 503; - ///////////////////////////////////////////////////////////////////////////////// // LLTempAssetData // An asset not stored on central asset store, but on a simulator node somewhere. @@ -952,7 +945,7 @@ void LLHTTPAssetStorage::checkForTimeouts() { if (curl_msg->data.result == CURLE_OK && ( curl_result == HTTP_OK - || curl_result == HTTP_PUT_OK + || curl_result == HTTP_CREATED || curl_result == HTTP_NO_CONTENT)) { llinfos << "Success uploading " << req->getUUID() << " to " << req->mURLBuffer << llendl; @@ -963,8 +956,8 @@ void LLHTTPAssetStorage::checkForTimeouts() } else if (curl_msg->data.result == CURLE_COULDNT_CONNECT || curl_msg->data.result == CURLE_OPERATION_TIMEOUTED || - curl_result == HTTP_SERVER_BAD_GATEWAY || - curl_result == HTTP_SERVER_TEMP_UNAVAILABLE) + curl_result == HTTP_BAD_GATEWAY || + curl_result == HTTP_SERVICE_UNAVAILABLE) { llwarns << "Re-requesting upload for " << req->getUUID() << ". Received upload error to " << req->mURLBuffer << " with result " << curl_easy_strerror(curl_msg->data.result) << ", http result " << curl_result << llendl; @@ -985,8 +978,8 @@ void LLHTTPAssetStorage::checkForTimeouts() if (!(curl_msg->data.result == CURLE_COULDNT_CONNECT || curl_msg->data.result == CURLE_OPERATION_TIMEOUTED || - curl_result == HTTP_SERVER_BAD_GATEWAY || - curl_result == HTTP_SERVER_TEMP_UNAVAILABLE)) + curl_result == HTTP_BAD_GATEWAY || + curl_result == HTTP_SERVICE_UNAVAILABLE)) { // shared upload finished callback // in the base class, this is called from processUploadComplete @@ -1018,7 +1011,7 @@ void LLHTTPAssetStorage::checkForTimeouts() llwarns << "Failure downloading " << req->mURLBuffer << " with result " << curl_easy_strerror(curl_msg->data.result) << ", http result " << curl_result << llendl; - xfer_result = (curl_result == HTTP_MISSING) ? LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE : LL_ERR_ASSET_REQUEST_FAILED; + xfer_result = (curl_result == HTTP_NOT_FOUND) ? LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE : LL_ERR_ASSET_REQUEST_FAILED; if (req->mVFile) { @@ -1240,7 +1233,7 @@ S32 LLHTTPAssetStorage::getURLToFile(const LLUUID& uuid, LLAssetType::EType asse } else { - xfer_result = curl_result == HTTP_MISSING ? LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE : LL_ERR_ASSET_REQUEST_FAILED; + xfer_result = curl_result == HTTP_NOT_FOUND ? LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE : LL_ERR_ASSET_REQUEST_FAILED; llinfos << "Failure downloading " << req.mURLBuffer << " with result " << curl_easy_strerror(curl_msg->data.result) << ", http result " << curl_result << llendl; } diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp index 0c325a68aa..a4a1f02cd3 100644 --- a/indra/llmessage/llhttpclient.cpp +++ b/indra/llmessage/llhttpclient.cpp @@ -54,7 +54,7 @@ namespace { public: LLHTTPClientURLAdaptor(LLCurl::ResponderPtr responder) - : LLURLRequestComplete(), mResponder(responder), mStatus(499), + : LLURLRequestComplete(), mResponder(responder), mStatus(HTTP_INTERNAL_ERROR), mReason("LLURLRequest complete w/no status") { } @@ -63,7 +63,7 @@ namespace { } - virtual void httpStatus(U32 status, const std::string& reason) + virtual void httpStatus(S32 status, const std::string& reason) { LLURLRequestComplete::httpStatus(status,reason); @@ -74,30 +74,33 @@ namespace virtual void complete(const LLChannelDescriptors& channels, const buffer_ptr_t& buffer) { + // *TODO: Re-interpret mRequestStatus codes? + // Would like to detect curl errors, such as + // connection errors, write erros, etc. if (mResponder.get()) { - // Allow clients to parse headers before we attempt to parse - // the body and provide completed/result/error calls. - mResponder->completedHeader(mStatus, mReason, mHeaderOutput); - mResponder->completedRaw(mStatus, mReason, channels, buffer); + mResponder->setResult(mStatus, mReason); + mResponder->completedRaw(channels, buffer); } } virtual void header(const std::string& header, const std::string& value) { - mHeaderOutput[header] = value; + if (mResponder.get()) + { + mResponder->setResponseHeader(header, value); + } } private: LLCurl::ResponderPtr mResponder; - U32 mStatus; + S32 mStatus; std::string mReason; - LLSD mHeaderOutput; }; class Injector : public LLIOPipe { public: - virtual const char* contentType() = 0; + virtual const std::string& contentType() = 0; }; class LLSDInjector : public Injector @@ -106,7 +109,7 @@ namespace LLSDInjector(const LLSD& sd) : mSD(sd) {} virtual ~LLSDInjector() {} - const char* contentType() { return "application/llsd+xml"; } + const std::string& contentType() { return HTTP_CONTENT_LLSD_XML; } virtual EStatus process_impl(const LLChannelDescriptors& channels, buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump) @@ -126,7 +129,7 @@ namespace RawInjector(const U8* data, S32 size) : mData(data), mSize(size) {} virtual ~RawInjector() {delete mData;} - const char* contentType() { return "application/octet-stream"; } + const std::string& contentType() { return HTTP_CONTENT_OCTET_STREAM; } virtual EStatus process_impl(const LLChannelDescriptors& channels, buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump) @@ -147,7 +150,7 @@ namespace FileInjector(const std::string& filename) : mFilename(filename) {} virtual ~FileInjector() {} - const char* contentType() { return "application/octet-stream"; } + const std::string& contentType() { return HTTP_CONTENT_OCTET_STREAM; } virtual EStatus process_impl(const LLChannelDescriptors& channels, buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump) @@ -180,7 +183,7 @@ namespace VFileInjector(const LLUUID& uuid, LLAssetType::EType asset_type) : mUUID(uuid), mAssetType(asset_type) {} virtual ~VFileInjector() {} - const char* contentType() { return "application/octet-stream"; } + const std::string& contentType() { return HTTP_CONTENT_OCTET_STREAM; } virtual EStatus process_impl(const LLChannelDescriptors& channels, buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump) @@ -213,7 +216,7 @@ void LLHTTPClient::setCertVerifyCallback(LLURLRequest::SSLCertVerifyCallback cal static void request( const std::string& url, - LLURLRequest::ERequestAction method, + EHTTPMethod method, Injector* body_injector, LLCurl::ResponderPtr responder, const F32 timeout = HTTP_REQUEST_EXPIRY_SECS, @@ -222,7 +225,11 @@ static void request( { if (!LLHTTPClient::hasPump()) { - responder->completed(U32_MAX, "No pump", LLSD()); + if (responder) + { + responder->completeResult(HTTP_INTERNAL_ERROR, "No pump"); + } + delete body_injector; return; } LLPumpIO::chain_t chain; @@ -230,20 +237,24 @@ static void request( LLURLRequest* req = new LLURLRequest(method, url); if(!req->isValid())//failed { - delete req ; - return ; + if (responder) + { + responder->completeResult(HTTP_INTERNAL_CURL_ERROR, "Internal Error - curl failure"); + } + delete req; + delete body_injector; + return; } req->setSSLVerifyCallback(LLHTTPClient::getCertVerifyCallback(), (void *)req); - lldebugs << LLURLRequest::actionAsVerb(method) << " " << url << " " - << headers << llendl; + LL_DEBUGS("LLHTTPClient") << httpMethodAsVerb(method) << " " << url << " " << headers << LL_ENDL; // Insert custom headers if the caller sent any if (headers.isMap()) { - if (headers.has("Cookie")) + if (headers.has(HTTP_HEADER_COOKIE)) { req->allowCookies(); } @@ -253,62 +264,56 @@ static void request( for (; iter != end; ++iter) { - std::ostringstream header; //if the header is "Pragma" with no value //the caller intends to force libcurl to drop //the Pragma header it so gratuitously inserts //Before inserting the header, force libcurl //to not use the proxy (read: llurlrequest.cpp) - static const std::string PRAGMA("Pragma"); - if ((iter->first == PRAGMA) && (iter->second.asString().empty())) + if ((iter->first == HTTP_HEADER_PRAGMA) && (iter->second.asString().empty())) { req->useProxy(false); } - header << iter->first << ": " << iter->second.asString() ; - lldebugs << "header = " << header.str() << llendl; - req->addHeader(header.str().c_str()); + LL_DEBUGS("LLHTTPClient") << "header = " << iter->first + << ": " << iter->second.asString() << LL_ENDL; + req->addHeader(iter->first, iter->second.asString()); } } // Check to see if we have already set Accept or not. If no one // set it, set it to application/llsd+xml since that's what we // almost always want. - if( method != LLURLRequest::HTTP_PUT && method != LLURLRequest::HTTP_POST ) + if( method != HTTP_PUT && method != HTTP_POST ) { - static const std::string ACCEPT("Accept"); - if(!headers.has(ACCEPT)) + if(!headers.has(HTTP_HEADER_ACCEPT)) { - req->addHeader("Accept: application/llsd+xml"); + req->addHeader(HTTP_HEADER_ACCEPT, HTTP_CONTENT_LLSD_XML); } } if (responder) { responder->setURL(url); + responder->setHTTPMethod(method); } req->setCallback(new LLHTTPClientURLAdaptor(responder)); - if (method == LLURLRequest::HTTP_POST && gMessageSystem) + if (method == HTTP_POST && gMessageSystem) { - req->addHeader(llformat("X-SecondLife-UDP-Listen-Port: %d", - gMessageSystem->mPort).c_str()); + req->addHeader("X-SecondLife-UDP-Listen-Port", llformat("%d", + gMessageSystem->mPort)); } - if (method == LLURLRequest::HTTP_PUT || method == LLURLRequest::HTTP_POST) + if (method == HTTP_PUT || method == HTTP_POST) { - static const std::string CONTENT_TYPE("Content-Type"); - if(!headers.has(CONTENT_TYPE)) + if(!headers.has(HTTP_HEADER_CONTENT_TYPE)) { // If the Content-Type header was passed in, it has // already been added as a header through req->addHeader // in the loop above. We defer to the caller's wisdom, but // if they did not specify a Content-Type, then ask the // injector. - req->addHeader( - llformat( - "Content-Type: %s", - body_injector->contentType()).c_str()); + req->addHeader(HTTP_HEADER_CONTENT_TYPE, body_injector->contentType()); } chain.push_back(LLIOPipe::ptr_t(body_injector)); } @@ -331,9 +336,9 @@ void LLHTTPClient::getByteRange( if(offset > 0 || bytes > 0) { std::string range = llformat("bytes=%d-%d", offset, offset+bytes-1); - headers["Range"] = range; + headers[HTTP_HEADER_RANGE] = range; } - request(url,LLURLRequest::HTTP_GET, NULL, responder, timeout, headers); + request(url,HTTP_GET, NULL, responder, timeout, headers); } void LLHTTPClient::head( @@ -342,16 +347,16 @@ void LLHTTPClient::head( const LLSD& headers, const F32 timeout) { - request(url, LLURLRequest::HTTP_HEAD, NULL, responder, timeout, headers); + request(url, HTTP_HEAD, NULL, responder, timeout, headers); } void LLHTTPClient::get(const std::string& url, ResponderPtr responder, const LLSD& headers, const F32 timeout) { - request(url, LLURLRequest::HTTP_GET, NULL, responder, timeout, headers); + request(url, HTTP_GET, NULL, responder, timeout, headers); } void LLHTTPClient::getHeaderOnly(const std::string& url, ResponderPtr responder, const LLSD& headers, const F32 timeout) { - request(url, LLURLRequest::HTTP_HEAD, NULL, responder, timeout, headers); + request(url, HTTP_HEAD, NULL, responder, timeout, headers); } void LLHTTPClient::getHeaderOnly(const std::string& url, ResponderPtr responder, const F32 timeout) { @@ -392,7 +397,7 @@ public: return content; } - std::string asString() + const std::string& asString() { return mBuffer; } @@ -421,7 +426,7 @@ private: */ static LLSD blocking_request( const std::string& url, - LLURLRequest::ERequestAction method, + EHTTPMethod method, const LLSD& body, const LLSD& headers = LLSD(), const F32 timeout = 5 @@ -464,11 +469,11 @@ static LLSD blocking_request( } // * Setup specific method / "verb" for the URI (currently only GET and POST supported + poppy) - if (method == LLURLRequest::HTTP_GET) + if (method == HTTP_GET) { curl_easy_setopt(curlp, CURLOPT_HTTPGET, 1); } - else if (method == LLURLRequest::HTTP_POST) + else if (method == HTTP_POST) { curl_easy_setopt(curlp, CURLOPT_POST, 1); //serialize to ostr then copy to str - need to because ostr ptr is unstable :( @@ -477,18 +482,20 @@ static LLSD blocking_request( body_str = ostr.str(); curl_easy_setopt(curlp, CURLOPT_POSTFIELDS, body_str.c_str()); //copied from PHP libs, correct? - headers_list = curl_slist_append(headers_list, "Content-Type: application/llsd+xml"); + headers_list = curl_slist_append(headers_list, + llformat("%s: %s", HTTP_HEADER_CONTENT_TYPE.c_str(), HTTP_CONTENT_LLSD_XML.c_str()).c_str()); // copied from llurlrequest.cpp // it appears that apache2.2.3 or django in etch is busted. If // we do not clear the expect header, we get a 500. May be // limited to django/mod_wsgi. - headers_list = curl_slist_append(headers_list, "Expect:"); + headers_list = curl_slist_append(headers_list, llformat("%s:", HTTP_HEADER_EXPECT.c_str()).c_str()); } // * Do the action using curl, handle results lldebugs << "HTTP body: " << body_str << llendl; - headers_list = curl_slist_append(headers_list, "Accept: application/llsd+xml"); + headers_list = curl_slist_append(headers_list, + llformat("%s: %s", HTTP_HEADER_ACCEPT.c_str(), HTTP_CONTENT_LLSD_XML.c_str()).c_str()); CURLcode curl_result = curl_easy_setopt(curlp, CURLOPT_HTTPHEADER, headers_list); if ( curl_result != CURLE_OK ) { @@ -497,11 +504,11 @@ static LLSD blocking_request( LLSD response = LLSD::emptyMap(); S32 curl_success = curl_easy_perform(curlp); - S32 http_status = 499; + S32 http_status = HTTP_INTERNAL_ERROR; curl_easy_getinfo(curlp, CURLINFO_RESPONSE_CODE, &http_status); response["status"] = http_status; // if we get a non-404 and it's not a 200 OR maybe it is but you have error bits, - if ( http_status != 404 && (http_status != 200 || curl_success != 0) ) + if ( http_status != HTTP_NOT_FOUND && (http_status != HTTP_OK || curl_success != 0) ) { // We expect 404s, don't spam for them. llwarns << "CURL REQ URL: " << url << llendl; @@ -531,12 +538,12 @@ static LLSD blocking_request( LLSD LLHTTPClient::blockingGet(const std::string& url) { - return blocking_request(url, LLURLRequest::HTTP_GET, LLSD()); + return blocking_request(url, HTTP_GET, LLSD()); } LLSD LLHTTPClient::blockingPost(const std::string& url, const LLSD& body) { - return blocking_request(url, LLURLRequest::HTTP_POST, body); + return blocking_request(url, HTTP_POST, body); } void LLHTTPClient::put( @@ -546,7 +553,7 @@ void LLHTTPClient::put( const LLSD& headers, const F32 timeout) { - request(url, LLURLRequest::HTTP_PUT, new LLSDInjector(body), responder, timeout, headers); + request(url, HTTP_PUT, new LLSDInjector(body), responder, timeout, headers); } void LLHTTPClient::post( @@ -556,7 +563,7 @@ void LLHTTPClient::post( const LLSD& headers, const F32 timeout) { - request(url, LLURLRequest::HTTP_POST, new LLSDInjector(body), responder, timeout, headers); + request(url, HTTP_POST, new LLSDInjector(body), responder, timeout, headers); } void LLHTTPClient::postRaw( @@ -567,7 +574,7 @@ void LLHTTPClient::postRaw( const LLSD& headers, const F32 timeout) { - request(url, LLURLRequest::HTTP_POST, new RawInjector(data, size), responder, timeout, headers); + request(url, HTTP_POST, new RawInjector(data, size), responder, timeout, headers); } void LLHTTPClient::postFile( @@ -577,7 +584,7 @@ void LLHTTPClient::postFile( const LLSD& headers, const F32 timeout) { - request(url, LLURLRequest::HTTP_POST, new FileInjector(filename), responder, timeout, headers); + request(url, HTTP_POST, new FileInjector(filename), responder, timeout, headers); } void LLHTTPClient::postFile( @@ -588,7 +595,7 @@ void LLHTTPClient::postFile( const LLSD& headers, const F32 timeout) { - request(url, LLURLRequest::HTTP_POST, new VFileInjector(uuid, asset_type), responder, timeout, headers); + request(url, HTTP_POST, new VFileInjector(uuid, asset_type), responder, timeout, headers); } // static @@ -598,7 +605,7 @@ void LLHTTPClient::del( const LLSD& headers, const F32 timeout) { - request(url, LLURLRequest::HTTP_DELETE, NULL, responder, timeout, headers); + request(url, HTTP_DELETE, NULL, responder, timeout, headers); } // static @@ -610,8 +617,8 @@ void LLHTTPClient::move( const F32 timeout) { LLSD headers = hdrs; - headers["Destination"] = destination; - request(url, LLURLRequest::HTTP_MOVE, NULL, responder, timeout, headers); + headers[HTTP_HEADER_DESTINATION] = destination; + request(url, HTTP_MOVE, NULL, responder, timeout, headers); } diff --git a/indra/llmessage/llhttpclientadapter.cpp b/indra/llmessage/llhttpclientadapter.cpp index f5d7a9abb6..aaa31e36fc 100644 --- a/indra/llmessage/llhttpclientadapter.cpp +++ b/indra/llmessage/llhttpclientadapter.cpp @@ -35,16 +35,19 @@ void LLHTTPClientAdapter::get(const std::string& url, LLCurl::ResponderPtr respo { LLSD empty_pragma_header; // Pragma is required to stop curl adding "no-cache" - // Space is required to stop llurlrequest from turnning off proxying - empty_pragma_header["Pragma"] = " "; + // Space is required to stop llurlrequest from turning off proxying + empty_pragma_header[HTTP_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; - // as above - empty_pragma_header["Pragma"] = " "; + if (!empty_pragma_header.has(HTTP_HEADER_PRAGMA)) + { + // as above + empty_pragma_header[HTTP_HEADER_PRAGMA] = " "; + } LLHTTPClient::get(url, responder, empty_pragma_header); } @@ -53,3 +56,18 @@ void LLHTTPClientAdapter::put(const std::string& url, const LLSD& body, LLCurl:: 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 index aae6426a59..270282c66f 100644 --- a/indra/llmessage/llhttpclientadapter.h +++ b/indra/llmessage/llhttpclientadapter.h @@ -37,6 +37,14 @@ public: 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/llhttpconstants.cpp b/indra/llmessage/llhttpconstants.cpp new file mode 100644 index 0000000000..2134024a14 --- /dev/null +++ b/indra/llmessage/llhttpconstants.cpp @@ -0,0 +1,219 @@ +/** + * @file llhttpconstants.cpp + * @brief Implementation of the HTTP request / response constant lookups + * + * $LicenseInfo:firstyear=2013&license=viewergpl$ + * + * Copyright (c) 2013, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "llhttpconstants.h" +#include "lltimer.h" + +// for curl_getdate() (apparently parsing RFC 1123 dates is hard) +#include <curl/curl.h> + +const std::string HTTP_HEADER_ACCEPT("Accept"); +const std::string HTTP_HEADER_ACCEPT_CHARSET("Accept-Charset"); +const std::string HTTP_HEADER_ACCEPT_ENCODING("Accept-Encoding"); +const std::string HTTP_HEADER_ACCEPT_LANGUAGE("Accept-Language"); +const std::string HTTP_HEADER_ACCEPT_RANGES("Accept-Ranges"); +const std::string HTTP_HEADER_AGE("Age"); +const std::string HTTP_HEADER_ALLOW("Allow"); +const std::string HTTP_HEADER_AUTHORIZATION("Authorization"); +const std::string HTTP_HEADER_CACHE_CONTROL("Cache-Control"); +const std::string HTTP_HEADER_CONNECTION("Connection"); +const std::string HTTP_HEADER_CONTENT_DESCRIPTION("Content-Description"); +const std::string HTTP_HEADER_CONTENT_ENCODING("Content-Encoding"); +const std::string HTTP_HEADER_CONTENT_ID("Content-ID"); +const std::string HTTP_HEADER_CONTENT_LANGUAGE("Content-Language"); +const std::string HTTP_HEADER_CONTENT_LENGTH("Content-Length"); +const std::string HTTP_HEADER_CONTENT_LOCATION("Content-Location"); +const std::string HTTP_HEADER_CONTENT_MD5("Content-MD5"); +const std::string HTTP_HEADER_CONTENT_RANGE("Content-Range"); +const std::string HTTP_HEADER_CONTENT_TRANSFER_ENCODING("Content-Transfer-Encoding"); +const std::string HTTP_HEADER_CONTENT_TYPE("Content-Type"); +const std::string HTTP_HEADER_COOKIE("Cookie"); +const std::string HTTP_HEADER_DATE("Date"); +const std::string HTTP_HEADER_DESTINATION("Destination"); +const std::string HTTP_HEADER_ETAG("ETag"); +const std::string HTTP_HEADER_EXPECT("Expect"); +const std::string HTTP_HEADER_EXPIRES("Expires"); +const std::string HTTP_HEADER_FROM("From"); +const std::string HTTP_HEADER_HOST("Host"); +const std::string HTTP_HEADER_IF_MATCH("If-Match"); +const std::string HTTP_HEADER_IF_MODIFIED_SINCE("If-Modified-Since"); +const std::string HTTP_HEADER_IF_NONE_MATCH("If-None-Match"); +const std::string HTTP_HEADER_IF_RANGE("If-Range"); +const std::string HTTP_HEADER_IF_UNMODIFIED_SINCE("If-Unmodified-Since"); +const std::string HTTP_HEADER_KEEP_ALIVE("Keep-Alive"); +const std::string HTTP_HEADER_LAST_MODIFIED("Last-Modified"); +const std::string HTTP_HEADER_LOCATION("Location"); +const std::string HTTP_HEADER_MAX_FORWARDS("Max-Forwards"); +const std::string HTTP_HEADER_MIME_VERSION("MIME-Version"); +const std::string HTTP_HEADER_PRAGMA("Pragma"); +const std::string HTTP_HEADER_PROXY_AUTHENTICATE("Proxy-Authenticate"); +const std::string HTTP_HEADER_PROXY_AUTHORIZATION("Proxy-Authorization"); +const std::string HTTP_HEADER_RANGE("Range"); +const std::string HTTP_HEADER_REFERER("Referer"); +const std::string HTTP_HEADER_RETRY_AFTER("Retry-After"); +const std::string HTTP_HEADER_SERVER("Server"); +const std::string HTTP_HEADER_SET_COOKIE("Set-Cookie"); +const std::string HTTP_HEADER_TE("TE"); +const std::string HTTP_HEADER_TRAILER("Trailer"); +const std::string HTTP_HEADER_TRANSFER_ENCODING("Transfer-Encoding"); +const std::string HTTP_HEADER_UPGRADE("Upgrade"); +const std::string HTTP_HEADER_USER_AGENT("User-Agent"); +const std::string HTTP_HEADER_VARY("Vary"); +const std::string HTTP_HEADER_VIA("Via"); +const std::string HTTP_HEADER_WARNING("Warning"); +const std::string HTTP_HEADER_WWW_AUTHENTICATE("WWW-Authenticate"); + + +// Sadly, our proxied headers do not follow http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html +// We need to deal with lowercase headers +const std::string HTTP_HEADER_LOWER_ACCEPT_LANGUAGE("accept-language"); +const std::string HTTP_HEADER_LOWER_CACHE_CONTROL("cache-control"); +const std::string HTTP_HEADER_LOWER_CONTENT_LENGTH("content-length"); +const std::string HTTP_HEADER_LOWER_CONTENT_TYPE("content-type"); +const std::string HTTP_HEADER_LOWER_HOST("host"); +const std::string HTTP_HEADER_LOWER_USER_AGENT("user-agent"); +const std::string HTTP_HEADER_LOWER_X_FORWARDED_FOR("x-forwarded-for"); + +const std::string HTTP_CONTENT_LLSD_XML("application/llsd+xml"); +const std::string HTTP_CONTENT_OCTET_STREAM("application/octet-stream"); +const std::string HTTP_CONTENT_XML("application/xml"); +const std::string HTTP_CONTENT_JSON("application/json"); +const std::string HTTP_CONTENT_TEXT_HTML("text/html"); +const std::string HTTP_CONTENT_TEXT_HTML_UTF8("text/html; charset=utf-8"); +const std::string HTTP_CONTENT_TEXT_PLAIN_UTF8("text/plain; charset=utf-8"); +const std::string HTTP_CONTENT_TEXT_LLSD("text/llsd"); +const std::string HTTP_CONTENT_TEXT_XML("text/xml"); +const std::string HTTP_CONTENT_TEXT_LSL("text/lsl"); +const std::string HTTP_CONTENT_TEXT_PLAIN("text/plain"); +const std::string HTTP_CONTENT_IMAGE_X_J2C("image/x-j2c"); +const std::string HTTP_CONTENT_IMAGE_J2C("image/j2c"); +const std::string HTTP_CONTENT_IMAGE_JPEG("image/jpeg"); +const std::string HTTP_CONTENT_IMAGE_PNG("image/png"); +const std::string HTTP_CONTENT_IMAGE_BMP("image/bmp"); + +const std::string HTTP_VERB_INVALID("(invalid)"); +const std::string HTTP_VERB_HEAD("HEAD"); +const std::string HTTP_VERB_GET("GET"); +const std::string HTTP_VERB_PUT("PUT"); +const std::string HTTP_VERB_POST("POST"); +const std::string HTTP_VERB_DELETE("DELETE"); +const std::string HTTP_VERB_MOVE("MOVE"); +const std::string HTTP_VERB_OPTIONS("OPTIONS"); + +const std::string& httpMethodAsVerb(EHTTPMethod method) +{ + static const std::string VERBS[] = + { + HTTP_VERB_INVALID, + HTTP_VERB_HEAD, + HTTP_VERB_GET, + HTTP_VERB_PUT, + HTTP_VERB_POST, + HTTP_VERB_DELETE, + HTTP_VERB_MOVE, + HTTP_VERB_OPTIONS + }; + if(((S32)method <=0) || ((S32)method >= HTTP_METHOD_COUNT)) + { + return VERBS[0]; + } + return VERBS[method]; +} + +bool isHttpInformationalStatus(S32 status) +{ + // Check for status 1xx. + return((100 <= status) && (status < 200)); +} + +bool isHttpGoodStatus(S32 status) +{ + // Check for status 2xx. + return((200 <= status) && (status < 300)); +} + +bool isHttpRedirectStatus(S32 status) +{ + // Check for status 3xx. + return((300 <= status) && (status < 400)); +} + +bool isHttpClientErrorStatus(S32 status) +{ + // Status 499 is sometimes used for re-interpreted status 2xx errors + // based on body content. Treat these as potentially retryable 'server' status errors, + // since we do not have enough context to know if this will always fail. + if (HTTP_INTERNAL_ERROR == status) return false; + + // Check for status 5xx. + return((400 <= status) && (status < 500)); +} + +bool isHttpServerErrorStatus(S32 status) +{ + // Status 499 is sometimes used for re-interpreted status 2xx errors. + // Allow retry of these, since we don't have enough information in this + // context to know if this will always fail. + if (HTTP_INTERNAL_ERROR == status) return true; + + // Check for status 5xx. + return((500 <= status) && (status < 600)); +} + +// Parses 'Retry-After' header contents and returns seconds until retry should occur. +bool getSecondsUntilRetryAfter(const std::string& retry_after, F32& seconds_to_wait) +{ + // *TODO: This needs testing! Not in use yet. + // Examples of Retry-After headers: + // Retry-After: Fri, 31 Dec 1999 23:59:59 GMT + // Retry-After: 120 + + // Check for number of seconds version, first: + char* end = 0; + // Parse as double + double seconds = std::strtod(retry_after.c_str(), &end); + if ( end != 0 && *end == 0 ) + { + // Successful parse + seconds_to_wait = (F32) seconds; + return true; + } + + // Parse rfc1123 date. + time_t date = curl_getdate(retry_after.c_str(), NULL ); + if (-1 == date) return false; + + seconds_to_wait = (F32)date - (F32)LLTimer::getTotalSeconds(); + return true; +} + diff --git a/indra/llmessage/llhttpconstants.h b/indra/llmessage/llhttpconstants.h new file mode 100644 index 0000000000..34263e17c8 --- /dev/null +++ b/indra/llmessage/llhttpconstants.h @@ -0,0 +1,220 @@ +/** + * @file llhttpconstants.h + * @brief Constants for HTTP requests and responses + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2013, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_HTTP_CONSTANTS_H +#define LL_HTTP_CONSTANTS_H + +#include "stdtypes.h" + +/////// HTTP STATUS CODES /////// + +// Standard errors from HTTP spec: +// http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1 +const S32 HTTP_CONTINUE = 100; +const S32 HTTP_SWITCHING_PROTOCOLS = 101; + +// Success +const S32 HTTP_OK = 200; +const S32 HTTP_CREATED = 201; +const S32 HTTP_ACCEPTED = 202; +const S32 HTTP_NON_AUTHORITATIVE_INFORMATION = 203; +const S32 HTTP_NO_CONTENT = 204; +const S32 HTTP_RESET_CONTENT = 205; +const S32 HTTP_PARTIAL_CONTENT = 206; + +// Redirection +const S32 HTTP_MULTIPLE_CHOICES = 300; +const S32 HTTP_MOVED_PERMANENTLY = 301; +const S32 HTTP_FOUND = 302; +const S32 HTTP_SEE_OTHER = 303; +const S32 HTTP_NOT_MODIFIED = 304; +const S32 HTTP_USE_PROXY = 305; +const S32 HTTP_TEMPORARY_REDIRECT = 307; + +// Client Error +const S32 HTTP_BAD_REQUEST = 400; +const S32 HTTP_UNAUTHORIZED = 401; +const S32 HTTP_PAYMENT_REQUIRED = 402; +const S32 HTTP_FORBIDDEN = 403; +const S32 HTTP_NOT_FOUND = 404; +const S32 HTTP_METHOD_NOT_ALLOWED = 405; +const S32 HTTP_NOT_ACCEPTABLE = 406; +const S32 HTTP_PROXY_AUTHENTICATION_REQUIRED = 407; +const S32 HTTP_REQUEST_TIME_OUT = 408; +const S32 HTTP_CONFLICT = 409; +const S32 HTTP_GONE = 410; +const S32 HTTP_LENGTH_REQUIRED = 411; +const S32 HTTP_PRECONDITION_FAILED = 412; +const S32 HTTP_REQUEST_ENTITY_TOO_LARGE = 413; +const S32 HTTP_REQUEST_URI_TOO_LARGE = 414; +const S32 HTTP_UNSUPPORTED_MEDIA_TYPE = 415; +const S32 HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416; +const S32 HTTP_EXPECTATION_FAILED = 417; + +// Server Error +const S32 HTTP_INTERNAL_SERVER_ERROR = 500; +const S32 HTTP_NOT_IMPLEMENTED = 501; +const S32 HTTP_BAD_GATEWAY = 502; +const S32 HTTP_SERVICE_UNAVAILABLE = 503; +const S32 HTTP_GATEWAY_TIME_OUT = 504; +const S32 HTTP_VERSION_NOT_SUPPORTED = 505; + +// We combine internal process errors with status codes +// These status codes should not be sent over the wire +// and indicate something went wrong internally. +// If you get these they are not normal. +const S32 HTTP_INTERNAL_CURL_ERROR = 498; +const S32 HTTP_INTERNAL_ERROR = 499; + + +////// HTTP Methods ////// + +extern const std::string HTTP_VERB_INVALID; +extern const std::string HTTP_VERB_HEAD; +extern const std::string HTTP_VERB_GET; +extern const std::string HTTP_VERB_PUT; +extern const std::string HTTP_VERB_POST; +extern const std::string HTTP_VERB_DELETE; +extern const std::string HTTP_VERB_MOVE; +extern const std::string HTTP_VERB_OPTIONS; + +enum EHTTPMethod +{ + HTTP_INVALID = 0, + HTTP_HEAD, + HTTP_GET, + HTTP_PUT, + HTTP_POST, + HTTP_DELETE, + HTTP_MOVE, // Caller will need to set 'Destination' header + HTTP_OPTIONS, + HTTP_METHOD_COUNT +}; + +const std::string& httpMethodAsVerb(EHTTPMethod method); +bool isHttpInformationalStatus(S32 status); +bool isHttpGoodStatus(S32 status); +bool isHttpRedirectStatus(S32 status); +bool isHttpClientErrorStatus(S32 status); +bool isHttpServerErrorStatus(S32 status); + +// Parses 'Retry-After' header contents and returns seconds until retry should occur. +bool getSecondsUntilRetryAfter(const std::string& retry_after, F32& seconds_to_wait); + +//// HTTP Headers ///// + +extern const std::string HTTP_HEADER_ACCEPT; +extern const std::string HTTP_HEADER_ACCEPT_CHARSET; +extern const std::string HTTP_HEADER_ACCEPT_ENCODING; +extern const std::string HTTP_HEADER_ACCEPT_LANGUAGE; +extern const std::string HTTP_HEADER_ACCEPT_RANGES; +extern const std::string HTTP_HEADER_AGE; +extern const std::string HTTP_HEADER_ALLOW; +extern const std::string HTTP_HEADER_AUTHORIZATION; +extern const std::string HTTP_HEADER_CACHE_CONTROL; +extern const std::string HTTP_HEADER_CONNECTION; +extern const std::string HTTP_HEADER_CONTENT_DESCRIPTION; +extern const std::string HTTP_HEADER_CONTENT_ENCODING; +extern const std::string HTTP_HEADER_CONTENT_ID; +extern const std::string HTTP_HEADER_CONTENT_LANGUAGE; +extern const std::string HTTP_HEADER_CONTENT_LENGTH; +extern const std::string HTTP_HEADER_CONTENT_LOCATION; +extern const std::string HTTP_HEADER_CONTENT_MD5; +extern const std::string HTTP_HEADER_CONTENT_RANGE; +extern const std::string HTTP_HEADER_CONTENT_TRANSFER_ENCODING; +extern const std::string HTTP_HEADER_CONTENT_TYPE; +extern const std::string HTTP_HEADER_COOKIE; +extern const std::string HTTP_HEADER_DATE; +extern const std::string HTTP_HEADER_DESTINATION; +extern const std::string HTTP_HEADER_ETAG; +extern const std::string HTTP_HEADER_EXPECT; +extern const std::string HTTP_HEADER_EXPIRES; +extern const std::string HTTP_HEADER_FROM; +extern const std::string HTTP_HEADER_HOST; +extern const std::string HTTP_HEADER_IF_MATCH; +extern const std::string HTTP_HEADER_IF_MODIFIED_SINCE; +extern const std::string HTTP_HEADER_IF_NONE_MATCH; +extern const std::string HTTP_HEADER_IF_RANGE; +extern const std::string HTTP_HEADER_IF_UNMODIFIED_SINCE; +extern const std::string HTTP_HEADER_KEEP_ALIVE; +extern const std::string HTTP_HEADER_LAST_MODIFIED; +extern const std::string HTTP_HEADER_LOCATION; +extern const std::string HTTP_HEADER_MAX_FORWARDS; +extern const std::string HTTP_HEADER_MIME_VERSION; +extern const std::string HTTP_HEADER_PRAGMA; +extern const std::string HTTP_HEADER_PROXY_AUTHENTICATE; +extern const std::string HTTP_HEADER_PROXY_AUTHORIZATION; +extern const std::string HTTP_HEADER_RANGE; +extern const std::string HTTP_HEADER_REFERER; +extern const std::string HTTP_HEADER_RETRY_AFTER; +extern const std::string HTTP_HEADER_SERVER; +extern const std::string HTTP_HEADER_SET_COOKIE; +extern const std::string HTTP_HEADER_TE; +extern const std::string HTTP_HEADER_TRAILER; +extern const std::string HTTP_HEADER_TRANSFER_ENCODING; +extern const std::string HTTP_HEADER_UPGRADE; +extern const std::string HTTP_HEADER_USER_AGENT; +extern const std::string HTTP_HEADER_VARY; +extern const std::string HTTP_HEADER_VIA; +extern const std::string HTTP_HEADER_WARNING; +extern const std::string HTTP_HEADER_WWW_AUTHENTICATE; + +// Sadly, our proxied headers do not follow http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html +// We need to deal with lowercase headers +extern const std::string HTTP_HEADER_LOWER_ACCEPT_LANGUAGE; +extern const std::string HTTP_HEADER_LOWER_CACHE_CONTROL; +extern const std::string HTTP_HEADER_LOWER_CONTENT_LENGTH; +extern const std::string HTTP_HEADER_LOWER_CONTENT_TYPE; +extern const std::string HTTP_HEADER_LOWER_HOST; +extern const std::string HTTP_HEADER_LOWER_USER_AGENT; +extern const std::string HTTP_HEADER_LOWER_X_FORWARDED_FOR; + +//// HTTP Content Types //// + +extern const std::string HTTP_CONTENT_LLSD_XML; +extern const std::string HTTP_CONTENT_OCTET_STREAM; +extern const std::string HTTP_CONTENT_XML; +extern const std::string HTTP_CONTENT_JSON; +extern const std::string HTTP_CONTENT_TEXT_HTML; +extern const std::string HTTP_CONTENT_TEXT_HTML_UTF8; +extern const std::string HTTP_CONTENT_TEXT_PLAIN_UTF8; +extern const std::string HTTP_CONTENT_TEXT_LLSD; +extern const std::string HTTP_CONTENT_TEXT_XML; +extern const std::string HTTP_CONTENT_TEXT_LSL; +extern const std::string HTTP_CONTENT_TEXT_PLAIN; +extern const std::string HTTP_CONTENT_IMAGE_X_J2C; +extern const std::string HTTP_CONTENT_IMAGE_J2C; +extern const std::string HTTP_CONTENT_IMAGE_JPEG; +extern const std::string HTTP_CONTENT_IMAGE_PNG; +extern const std::string HTTP_CONTENT_IMAGE_BMP; + +#endif diff --git a/indra/llmessage/llhttpnode.cpp b/indra/llmessage/llhttpnode.cpp index 5c2f73eccb..e3b42b1b16 100644 --- a/indra/llmessage/llhttpnode.cpp +++ b/indra/llmessage/llhttpnode.cpp @@ -30,6 +30,7 @@ #include <boost/tokenizer.hpp> #include "llstl.h" +#include "llhttpconstants.h" #include "lliohttpserver.h" // for string constants static const std::string CONTEXT_WILDCARD("wildcard"); @@ -173,13 +174,15 @@ LLSD LLHTTPNode::simpleDel(const LLSD&) const void LLHTTPNode::options(ResponsePtr response, const LLSD& context) const { //llinfos << "options context: " << context << llendl; + LL_DEBUGS("LLHTTPNode") << "context: " << context << LL_ENDL; // default implementation constructs an url to the documentation. + // *TODO: Check for 'Host' header instead of 'host' header? std::string host( - context[CONTEXT_REQUEST][CONTEXT_HEADERS]["host"].asString()); + context[CONTEXT_REQUEST][CONTEXT_HEADERS][HTTP_HEADER_LOWER_HOST].asString()); if(host.empty()) { - response->status(400, "Bad Request -- need Host header"); + response->status(HTTP_BAD_REQUEST, "Bad Request -- need Host header"); return; } std::ostringstream ostr; @@ -187,7 +190,7 @@ void LLHTTPNode::options(ResponsePtr response, const LLSD& context) const ostr << context[CONTEXT_REQUEST]["path"].asString(); static const std::string DOC_HEADER("X-Documentation-URL"); response->addHeader(DOC_HEADER, ostr.str()); - response->status(200, "OK"); + response->status(HTTP_OK, "OK"); } @@ -389,17 +392,17 @@ void LLHTTPNode::Response::statusUnknownError(S32 code) void LLHTTPNode::Response::notFound(const std::string& message) { - status(404, message); + status(HTTP_NOT_FOUND, message); } void LLHTTPNode::Response::notFound() { - status(404, "Not Found"); + status(HTTP_NOT_FOUND, "Not Found"); } void LLHTTPNode::Response::methodNotAllowed() { - status(405, "Method Not Allowed"); + status(HTTP_METHOD_NOT_ALLOWED, "Method Not Allowed"); } void LLHTTPNode::Response::addHeader( @@ -467,7 +470,7 @@ LLSimpleResponse::~LLSimpleResponse() void LLSimpleResponse::result(const LLSD& result) { - status(200, "OK"); + status(HTTP_OK, "OK"); } void LLSimpleResponse::extendedResult(S32 code, const std::string& body, const LLSD& headers) @@ -475,6 +478,11 @@ void LLSimpleResponse::extendedResult(S32 code, const std::string& body, const L status(code,body); } +void LLSimpleResponse::extendedResult(S32 code, const LLSD& r, const LLSD& headers) +{ + status(code,"(LLSD)"); +} + void LLSimpleResponse::status(S32 code, const std::string& message) { mCode = code; diff --git a/indra/llmessage/llhttpnode.h b/indra/llmessage/llhttpnode.h index 148647ddde..2539eec6c3 100644 --- a/indra/llmessage/llhttpnode.h +++ b/indra/llmessage/llhttpnode.h @@ -60,6 +60,8 @@ class LLChainIOFactory; */ class LLHTTPNode { +protected: + LOG_CLASS(LLHTTPNode); public: LLHTTPNode(); virtual ~LLHTTPNode(); @@ -100,7 +102,12 @@ public: /** * @brief return status code and message with headers. */ - virtual void extendedResult(S32 code, const std::string& message, const LLSD& headers) = 0; + virtual void extendedResult(S32 code, const std::string& message, const LLSD& headers = LLSD()) = 0; + + /** + * @brief return status code and LLSD result with headers. + */ + virtual void extendedResult(S32 code, const LLSD& result, const LLSD& headers = LLSD()) = 0; /** * @brief return status code and reason string on http header, @@ -287,7 +294,7 @@ public: void result(const LLSD& result); void extendedResult(S32 code, const std::string& body, const LLSD& headers); - + void extendedResult(S32 code, const LLSD& result, const LLSD& headers); void status(S32 code, const std::string& message); void print(std::ostream& out) const; diff --git a/indra/llmessage/lliohttpserver.cpp b/indra/llmessage/lliohttpserver.cpp index 1236fc8b71..509719786c 100644 --- a/indra/llmessage/lliohttpserver.cpp +++ b/indra/llmessage/lliohttpserver.cpp @@ -33,6 +33,7 @@ #include "llapr.h" #include "llbuffer.h" #include "llbufferstream.h" +#include "llhttpconstants.h" #include "llhttpnode.h" #include "lliopipe.h" #include "lliosocket.h" @@ -53,11 +54,6 @@ const std::string CONTEXT_REQUEST("request"); const std::string CONTEXT_RESPONSE("response"); const std::string CONTEXT_VERB("verb"); const std::string CONTEXT_HEADERS("headers"); -const std::string HTTP_VERB_GET("GET"); -const std::string HTTP_VERB_PUT("PUT"); -const std::string HTTP_VERB_POST("POST"); -const std::string HTTP_VERB_DELETE("DELETE"); -const std::string HTTP_VERB_OPTIONS("OPTIONS"); static LLIOHTTPServer::timing_callback_t sTimingCallback = NULL; static void* sTimingCallbackData = NULL; @@ -102,7 +98,7 @@ private: // from LLHTTPNode::Response virtual void result(const LLSD&); virtual void extendedResult(S32 code, const std::string& body, const LLSD& headers); - + virtual void extendedResult(S32 code, const LLSD& body, const LLSD& headers); virtual void status(S32 code, const std::string& message); void nullPipe(); @@ -122,7 +118,8 @@ private: STATE_LOCKED, STATE_GOOD_RESULT, STATE_STATUS_RESULT, - STATE_EXTENDED_RESULT + STATE_EXTENDED_RESULT, + STATE_EXTENDED_LLSD_RESULT }; State mState; @@ -132,7 +129,7 @@ private: void lockChain(LLPumpIO*); void unlockChain(); - LLSD mGoodResult; + LLSD mResult; S32 mStatusCode; std::string mStatusMessage; LLSD mHeaders; @@ -193,7 +190,7 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl( } else if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_TEXT) { - std::stringstream strstrm; + std::ostringstream strstrm; strstrm << istr.rdbuf(); input = strstrm.str(); } @@ -209,7 +206,7 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl( } else if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_TEXT) { - std::stringstream strstrm; + std::ostringstream strstrm; strstrm << istr.rdbuf(); input = strstrm.str(); } @@ -249,7 +246,7 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl( << "s" << llendl; // Log Internal Server Errors - //if(mStatusCode == 500) + //if(mStatusCode == HTTP_INTERNAL_SERVER_ERROR) //{ // llwarns << "LLHTTPPipe::process_impl:500:Internal Server Error" // << llendl; @@ -271,10 +268,10 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl( case STATE_GOOD_RESULT: { LLSD headers = mHeaders; - headers["Content-Type"] = "application/llsd+xml"; + headers[HTTP_HEADER_CONTENT_TYPE] = HTTP_CONTENT_LLSD_XML; context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = headers; LLBufferStream ostr(channels, buffer.get()); - LLSDSerialize::toXML(mGoodResult, ostr); + LLSDSerialize::toXML(mResult, ostr); return STATUS_DONE; } @@ -282,7 +279,7 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl( case STATE_STATUS_RESULT: { LLSD headers = mHeaders; - headers["Content-Type"] = "text/plain"; + headers[HTTP_HEADER_CONTENT_TYPE] = HTTP_CONTENT_TEXT_PLAIN; context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = headers; context[CONTEXT_RESPONSE]["statusCode"] = mStatusCode; context[CONTEXT_RESPONSE]["statusMessage"] = mStatusMessage; @@ -300,6 +297,17 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl( return STATUS_DONE; } + case STATE_EXTENDED_LLSD_RESULT: + { + LLSD headers = mHeaders; + headers[HTTP_HEADER_CONTENT_TYPE] = HTTP_CONTENT_LLSD_XML; + context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = headers; + context[CONTEXT_RESPONSE]["statusCode"] = mStatusCode; + LLBufferStream ostr(channels, buffer.get()); + LLSDSerialize::toXML(mResult, ostr); + + return STATUS_DONE; + } default: llwarns << "LLHTTPPipe::process_impl: unexpected state " << mState << llendl; @@ -335,19 +343,35 @@ void LLHTTPPipe::Response::result(const LLSD& r) return; } - mPipe->mStatusCode = 200; + mPipe->mStatusCode = HTTP_OK; mPipe->mStatusMessage = "OK"; - mPipe->mGoodResult = r; + mPipe->mResult = r; mPipe->mState = STATE_GOOD_RESULT; mPipe->mHeaders = mHeaders; - mPipe->unlockChain(); + mPipe->unlockChain(); +} + +void LLHTTPPipe::Response::extendedResult(S32 code, const LLSD& r, const LLSD& headers) +{ + if(! mPipe) + { + llwarns << "LLHTTPPipe::Response::extendedResult: NULL pipe" << llendl; + return; + } + + mPipe->mStatusCode = code; + mPipe->mStatusMessage = "(LLSD)"; + mPipe->mResult = r; + mPipe->mHeaders = headers; + mPipe->mState = STATE_EXTENDED_LLSD_RESULT; + mPipe->unlockChain(); } void LLHTTPPipe::Response::extendedResult(S32 code, const std::string& body, const LLSD& headers) { if(! mPipe) { - llwarns << "LLHTTPPipe::Response::status: NULL pipe" << llendl; + llwarns << "LLHTTPPipe::Response::extendedResult: NULL pipe" << llendl; return; } @@ -454,9 +478,9 @@ LLIOPipe::EStatus LLHTTPResponseHeader::process_impl( std::string message = context[CONTEXT_RESPONSE]["statusMessage"]; int code = context[CONTEXT_RESPONSE]["statusCode"]; - if (code < 200) + if (code < HTTP_OK) { - code = 200; + code = HTTP_OK; message = "OK"; } @@ -465,7 +489,7 @@ LLIOPipe::EStatus LLHTTPResponseHeader::process_impl( S32 content_length = buffer->countAfter(channels.in(), NULL); if(0 < content_length) { - ostr << "Content-Length: " << content_length << "\r\n"; + ostr << HTTP_HEADER_CONTENT_LENGTH << ": " << content_length << "\r\n"; } // *NOTE: This guard can go away once the LLSD static map // iterator is available. Phoenix. 2008-05-09 @@ -771,7 +795,7 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl( std::string name(buf, pos_colon - buf); std::string value(pos_colon + 2); LLStringUtil::toLower(name); - if("content-length" == name) + if(HTTP_HEADER_LOWER_CONTENT_LENGTH == name) { lldebugs << "Content-Length: " << value << llendl; mContentLength = atoi(value.c_str()); diff --git a/indra/llmessage/lliohttpserver.h b/indra/llmessage/lliohttpserver.h index 5c1b0531ff..40537e05bc 100644 --- a/indra/llmessage/lliohttpserver.h +++ b/indra/llmessage/lliohttpserver.h @@ -39,11 +39,6 @@ extern const std::string CONTEXT_REQUEST; extern const std::string CONTEXT_RESPONSE; extern const std::string CONTEXT_VERB; extern const std::string CONTEXT_HEADERS; -extern const std::string HTTP_VERB_GET; -extern const std::string HTTP_VERB_PUT; -extern const std::string HTTP_VERB_POST; -extern const std::string HTTP_VERB_DELETE; -extern const std::string HTTP_VERB_OPTIONS; class LLIOHTTPServer { diff --git a/indra/llmessage/llmime.cpp b/indra/llmessage/llmime.cpp index 9d9c4ebd68..90653098db 100644 --- a/indra/llmessage/llmime.cpp +++ b/indra/llmessage/llmime.cpp @@ -27,6 +27,7 @@ */ #include "linden_common.h" +#include "llhttpconstants.h" #include "llmime.h" #include <vector> @@ -36,20 +37,6 @@ /** * Useful constants. */ -// Headers specified in rfc-2045 will be canonicalized below. -static const std::string CONTENT_LENGTH("Content-Length"); -static const std::string CONTENT_TYPE("Content-Type"); -static const S32 KNOWN_HEADER_COUNT = 6; -static const std::string KNOWN_HEADER[KNOWN_HEADER_COUNT] = -{ - CONTENT_LENGTH, - CONTENT_TYPE, - std::string("MIME-Version"), - std::string("Content-Transfer-Encoding"), - std::string("Content-ID"), - std::string("Content-Description"), -}; - // parser helpers static const std::string MULTIPART("multipart"); static const std::string BOUNDARY("boundary"); @@ -115,7 +102,7 @@ S32 LLMimeIndex::contentLength() const { // Find the content length in the headers. S32 length = -1; - LLSD content_length = mImpl->mHeaders[CONTENT_LENGTH]; + LLSD content_length = mImpl->mHeaders[HTTP_HEADER_CONTENT_LENGTH]; if(content_length.isDefined()) { length = content_length.asInteger(); @@ -126,7 +113,7 @@ S32 LLMimeIndex::contentLength() const std::string LLMimeIndex::contentType() const { std::string type; - LLSD content_type = mImpl->mHeaders[CONTENT_TYPE]; + LLSD content_type = mImpl->mHeaders[HTTP_HEADER_CONTENT_TYPE]; if(content_type.isDefined()) { type = content_type.asString(); @@ -137,7 +124,7 @@ std::string LLMimeIndex::contentType() const bool LLMimeIndex::isMultipart() const { bool multipart = false; - LLSD content_type = mImpl->mHeaders[CONTENT_TYPE]; + LLSD content_type = mImpl->mHeaders[HTTP_HEADER_CONTENT_TYPE]; if(content_type.isDefined()) { std::string type = content_type.asString(); @@ -354,7 +341,7 @@ bool LLMimeParser::Impl::parseIndex( if(index.isMultipart()) { // Figure out the separator, scan past it, and recurse. - std::string ct = headers[CONTENT_TYPE].asString(); + std::string ct = headers[HTTP_HEADER_CONTENT_TYPE].asString(); std::string sep = findSeparator(ct); scanPastSeparator(istr, limit, sep); while(continueParse() && parseIndex(istr, limit, sep, true, mime)) @@ -381,6 +368,18 @@ bool LLMimeParser::Impl::parseHeaders( S32 limit, LLSD& headers) { + // Headers specified in rfc-2045 will be canonicalized below. + static const S32 KNOWN_HEADER_COUNT = 6; + static const std::string KNOWN_HEADER[KNOWN_HEADER_COUNT] = + { + HTTP_HEADER_CONTENT_LENGTH, + HTTP_HEADER_CONTENT_TYPE, + HTTP_HEADER_MIME_VERSION, + HTTP_HEADER_CONTENT_TRANSFER_ENCODING, + HTTP_HEADER_CONTENT_ID, + HTTP_HEADER_CONTENT_DESCRIPTION, + }; + while(continueParse()) { // Get the next line. @@ -531,9 +530,9 @@ void LLMimeParser::Impl::scanPastContent( LLSD headers, const std::string separator) { - if(headers.has(CONTENT_LENGTH)) + if(headers.has(HTTP_HEADER_CONTENT_LENGTH)) { - S32 content_length = headers[CONTENT_LENGTH].asInteger(); + S32 content_length = headers[HTTP_HEADER_CONTENT_LENGTH].asInteger(); // Subtract 2 here for the \r\n after the content. S32 max_skip = llmin(content_length, limit - mScanCount - 2); istr.ignore(max_skip); diff --git a/indra/llmessage/llregionpresenceverifier.cpp b/indra/llmessage/llregionpresenceverifier.cpp deleted file mode 100644 index 932cbf375e..0000000000 --- a/indra/llmessage/llregionpresenceverifier.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/** - * @file llregionpresenceverifier.cpp - * @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 "linden_common.h" - -#include "llregionpresenceverifier.h" -#include "llhttpclientinterface.h" -#include <sstream> -#include "net.h" -#include "message.h" - -namespace boost -{ - void intrusive_ptr_add_ref(LLRegionPresenceVerifier::Response* p) - { - ++p->mReferenceCount; - } - - void intrusive_ptr_release(LLRegionPresenceVerifier::Response* p) - { - if(p && 0 == --p->mReferenceCount) - { - delete p; - } - } -}; - -LLRegionPresenceVerifier::Response::~Response() -{ -} - -LLRegionPresenceVerifier::RegionResponder::RegionResponder(const std::string& - uri, - ResponsePtr data, - S32 retry_count) : - mUri(uri), - mSharedData(data), - mRetryCount(retry_count) -{ -} - -//virtual -LLRegionPresenceVerifier::RegionResponder::~RegionResponder() -{ -} - -void LLRegionPresenceVerifier::RegionResponder::result(const LLSD& content) -{ - std::string host = content["private_host"].asString(); - U32 port = content["private_port"].asInteger(); - LLHost destination(host, port); - LLUUID id = content["region_id"]; - - lldebugs << "Verifying " << destination.getString() << " is region " << id << llendl; - - std::stringstream uri; - uri << "http://" << destination.getString() << "/state/basic/"; - mSharedData->getHttpClient().get( - uri.str(), - new VerifiedDestinationResponder(mUri, mSharedData, content, mRetryCount)); -} - -void LLRegionPresenceVerifier::RegionResponder::error(U32 status, - const std::string& reason) -{ - // TODO: babbage: distinguish between region presence service and - // region verification errors? - mSharedData->onRegionVerificationFailed(); -} - -LLRegionPresenceVerifier::VerifiedDestinationResponder::VerifiedDestinationResponder(const std::string& uri, ResponsePtr data, const LLSD& content, - S32 retry_count): - mUri(uri), - mSharedData(data), - mContent(content), - mRetryCount(retry_count) -{ -} - -//virtual -LLRegionPresenceVerifier::VerifiedDestinationResponder::~VerifiedDestinationResponder() -{ -} - -void LLRegionPresenceVerifier::VerifiedDestinationResponder::result(const LLSD& content) -{ - LLUUID actual_region_id = content["region_id"]; - LLUUID expected_region_id = mContent["region_id"]; - - lldebugs << "Actual region: " << content << llendl; - lldebugs << "Expected region: " << mContent << llendl; - - if (mSharedData->checkValidity(content) && - (actual_region_id == expected_region_id)) - { - mSharedData->onRegionVerified(mContent); - } - else if (mRetryCount > 0) - { - retry(); - } - else - { - llwarns << "Simulator verification failed. Region: " << mUri << llendl; - mSharedData->onRegionVerificationFailed(); - } -} - -void LLRegionPresenceVerifier::VerifiedDestinationResponder::retry() -{ - LLSD headers; - headers["Cache-Control"] = "no-cache, max-age=0"; - llinfos << "Requesting region information, get uncached for region " - << mUri << llendl; - --mRetryCount; - mSharedData->getHttpClient().get(mUri, new RegionResponder(mUri, mSharedData, mRetryCount), headers); -} - -void LLRegionPresenceVerifier::VerifiedDestinationResponder::error(U32 status, const std::string& reason) -{ - if(mRetryCount > 0) - { - retry(); - } - else - { - llwarns << "Failed to contact simulator for verification. Region: " << mUri << llendl; - mSharedData->onRegionVerificationFailed(); - } -} diff --git a/indra/llmessage/llregionpresenceverifier.h b/indra/llmessage/llregionpresenceverifier.h deleted file mode 100644 index 5e8251e519..0000000000 --- a/indra/llmessage/llregionpresenceverifier.h +++ /dev/null @@ -1,98 +0,0 @@ -/** - * @file llregionpresenceverifier.cpp - * @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_LLREGIONPRESENCEVERIFIER_H -#define LL_LLREGIONPRESENCEVERIFIER_H - -#include "llhttpclient.h" -#include <string> -#include "llsd.h" -#include <boost/intrusive_ptr.hpp> - -class LLHTTPClientInterface; - -class LLRegionPresenceVerifier -{ -public: - class Response - { - public: - virtual ~Response() = 0; - - virtual bool checkValidity(const LLSD& content) const = 0; - virtual void onRegionVerified(const LLSD& region_details) = 0; - virtual void onRegionVerificationFailed() = 0; - - virtual LLHTTPClientInterface& getHttpClient() = 0; - - public: /* but not really -- don't touch this */ - U32 mReferenceCount; - }; - - typedef boost::intrusive_ptr<Response> ResponsePtr; - - class RegionResponder : public LLHTTPClient::Responder - { - public: - RegionResponder(const std::string& uri, ResponsePtr data, - S32 retry_count); - virtual ~RegionResponder(); - virtual void result(const LLSD& content); - virtual void error(U32 status, const std::string& reason); - - private: - ResponsePtr mSharedData; - std::string mUri; - S32 mRetryCount; - }; - - class VerifiedDestinationResponder : public LLHTTPClient::Responder - { - public: - VerifiedDestinationResponder(const std::string& uri, ResponsePtr data, - const LLSD& content, S32 retry_count); - virtual ~VerifiedDestinationResponder(); - virtual void result(const LLSD& content); - - virtual void error(U32 status, const std::string& reason); - - private: - void retry(); - ResponsePtr mSharedData; - LLSD mContent; - std::string mUri; - S32 mRetryCount; - }; -}; - -namespace boost -{ - void intrusive_ptr_add_ref(LLRegionPresenceVerifier::Response* p); - void intrusive_ptr_release(LLRegionPresenceVerifier::Response* p); -}; - -#endif //LL_LLREGIONPRESENCEVERIFIER_H diff --git a/indra/llmessage/llsdmessage.cpp b/indra/llmessage/llsdmessage.cpp index 1c93c12d99..376f69ea36 100644 --- a/indra/llmessage/llsdmessage.cpp +++ b/indra/llmessage/llsdmessage.cpp @@ -92,14 +92,14 @@ bool LLSDMessage::httpListener(const LLSD& request) return false; } -void LLSDMessage::EventResponder::result(const LLSD& data) +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(data); + LLSD response(getContent()); mReqID.stamp(response); mPumps.obtain(mReplyPump).post(response); } @@ -111,7 +111,7 @@ void LLSDMessage::EventResponder::result(const LLSD& data) } } -void LLSDMessage::EventResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) +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 @@ -121,19 +121,16 @@ void LLSDMessage::EventResponder::errorWithContent(U32 status, const std::string LLSD info(mReqID.makeResponse()); info["target"] = mTarget; info["message"] = mMessage; - info["status"] = LLSD::Integer(status); - info["reason"] = reason; - info["content"] = content; + info["status"] = getStatus(); + info["reason"] = getReason(); + info["content"] = getContent(); mPumps.obtain(mErrorPump).post(info); } else // default error handling { - // convention seems to be to use llinfos, but that seems a bit casual? LL_WARNS("LLSDMessage::EventResponder") << "'" << mMessage << "' to '" << mTarget - << "' failed with code " << status << ": " << reason << '\n' - << ll_pretty_print_sd(content) - << LL_ENDL; + << "' failed " << dumpResponse() << LL_ENDL; } } @@ -151,11 +148,11 @@ bool LLSDMessage::ResponderAdapter::listener(const LLSD& payload, bool success) { if (success) { - mResponder->result(payload); + mResponder->successResult(payload); } else { - mResponder->errorWithContent(payload["status"].asInteger(), payload["reason"], payload["content"]); + mResponder->failureResult(payload["status"].asInteger(), payload["reason"], payload["content"]); } /*---------------- MUST BE LAST STATEMENT BEFORE RETURN ----------------*/ diff --git a/indra/llmessage/llsdmessage.h b/indra/llmessage/llsdmessage.h index 0d34847ff2..e5d532d6a4 100644 --- a/indra/llmessage/llsdmessage.h +++ b/indra/llmessage/llsdmessage.h @@ -123,6 +123,7 @@ private: /// LLCapabilityListener. Others should use higher-level APIs. class EventResponder: public LLHTTPClient::Responder { + LOG_CLASS(EventResponder); public: /** * LLHTTPClient::Responder that dispatches via named LLEventPump instances. @@ -149,8 +150,9 @@ private: mErrorPump(errorPump) {} - virtual void result(const LLSD& data); - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content); + protected: + virtual void httpSuccess(); + virtual void httpFailure(); private: LLEventPumps& mPumps; diff --git a/indra/llmessage/llsdrpcclient.h b/indra/llmessage/llsdrpcclient.h index 0cecf4f688..02891d4f32 100644 --- a/indra/llmessage/llsdrpcclient.h +++ b/indra/llmessage/llsdrpcclient.h @@ -240,7 +240,7 @@ public: virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const { lldebugs << "LLSDRPCClientFactory::build" << llendl; - LLURLRequest* http(new LLURLRequest(LLURLRequest::HTTP_POST)); + LLURLRequest* http(new LLURLRequest(HTTP_POST)); if(!http->isValid()) { llwarns << "Creating LLURLRequest failed." << llendl ; @@ -251,7 +251,7 @@ public: LLIOPipe::ptr_t service(new Client); chain.push_back(service); LLIOPipe::ptr_t http_pipe(http); - http->addHeader("Content-Type: text/llsd"); + http->addHeader(HTTP_HEADER_CONTENT_TYPE, HTTP_CONTENT_TEXT_LLSD); if(mURL.empty()) { chain.push_back(LLIOPipe::ptr_t(new LLContextURLExtractor(http))); @@ -291,7 +291,7 @@ public: { lldebugs << "LLXMLSDRPCClientFactory::build" << llendl; - LLURLRequest* http(new LLURLRequest(LLURLRequest::HTTP_POST)); + LLURLRequest* http(new LLURLRequest(HTTP_POST)); if(!http->isValid()) { llwarns << "Creating LLURLRequest failed." << llendl ; @@ -301,7 +301,7 @@ public: LLIOPipe::ptr_t service(new Client); chain.push_back(service); LLIOPipe::ptr_t http_pipe(http); - http->addHeader("Content-Type: text/xml"); + http->addHeader(HTTP_HEADER_CONTENT_TYPE, HTTP_CONTENT_TEXT_XML); if(mURL.empty()) { chain.push_back(LLIOPipe::ptr_t(new LLContextURLExtractor(http))); diff --git a/indra/llmessage/lltrustedmessageservice.cpp b/indra/llmessage/lltrustedmessageservice.cpp index fea7fc72c4..8248b184e9 100644 --- a/indra/llmessage/lltrustedmessageservice.cpp +++ b/indra/llmessage/lltrustedmessageservice.cpp @@ -64,7 +64,7 @@ void LLTrustedMessageService::post(LLHTTPNode::ResponsePtr response, LL_WARNS("Messaging") << "trusted message POST to /trusted-message/" << name << " from unknown or untrusted sender " << sender << llendl; - response->status(403, "Unknown or untrusted sender"); + response->status(HTTP_FORBIDDEN, "Unknown or untrusted sender"); } else { diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp index 627d591839..f354f5ab5d 100755 --- a/indra/llmessage/llurlrequest.cpp +++ b/indra/llmessage/llurlrequest.cpp @@ -40,7 +40,6 @@ #include "llstring.h" #include "apr_env.h" #include "llapr.h" -static const U32 HTTP_STATUS_PIPE_ERROR = 499; /** * String constants @@ -130,34 +129,15 @@ CURLcode LLURLRequest::_sslCtxCallback(CURL * curl, void *sslctx, void *param) * class LLURLRequest */ -// static -std::string LLURLRequest::actionAsVerb(LLURLRequest::ERequestAction action) -{ - static const std::string VERBS[] = - { - "(invalid)", - "HEAD", - "GET", - "PUT", - "POST", - "DELETE", - "MOVE" - }; - if(((S32)action <=0) || ((S32)action >= REQUEST_ACTION_COUNT)) - { - return VERBS[0]; - } - return VERBS[action]; -} -LLURLRequest::LLURLRequest(LLURLRequest::ERequestAction action) : +LLURLRequest::LLURLRequest(EHTTPMethod action) : mAction(action) { initialize(); } LLURLRequest::LLURLRequest( - LLURLRequest::ERequestAction action, + EHTTPMethod action, const std::string& url) : mAction(action) { @@ -180,12 +160,17 @@ void LLURLRequest::setURL(const std::string& url) } } -std::string LLURLRequest::getURL() const +const std::string& LLURLRequest::getURL() const { return mDetail->mURL; } -void LLURLRequest::addHeader(const char* header) +void LLURLRequest::addHeader(const std::string& header, const std::string& value /* = "" */) +{ + mDetail->mCurlRequest->slist_append(header, value); +} + +void LLURLRequest::addHeaderRaw(const char* header) { mDetail->mCurlRequest->slist_append(header); } @@ -272,7 +257,7 @@ LLIOPipe::EStatus LLURLRequest::handleError( LLURLRequestComplete* complete = NULL; complete = (LLURLRequestComplete*)mCompletionCallback.get(); complete->httpStatus( - HTTP_STATUS_PIPE_ERROR, + HTTP_INTERNAL_ERROR, LLIOPipe::lookupStatusString(status)); complete->responseStatus(status); pump->respond(complete); @@ -494,7 +479,7 @@ bool LLURLRequest::configure() case HTTP_PUT: // Disable the expect http 1.1 extension. POST and PUT default // to turning this on, and I am not too sure what it means. - addHeader("Expect:"); + addHeader(HTTP_HEADER_EXPECT); mDetail->mCurlRequest->setopt(CURLOPT_UPLOAD, 1); mDetail->mCurlRequest->setopt(CURLOPT_INFILESIZE, bytes); @@ -504,11 +489,11 @@ bool LLURLRequest::configure() case HTTP_POST: // Disable the expect http 1.1 extension. POST and PUT default // to turning this on, and I am not too sure what it means. - addHeader("Expect:"); + addHeader(HTTP_HEADER_EXPECT); // Disable the content type http header. // *FIX: what should it be? - addHeader("Content-Type:"); + addHeader(HTTP_HEADER_CONTENT_TYPE); // Set the handle for an http post mDetail->mCurlRequest->setPost(NULL, bytes); @@ -638,7 +623,7 @@ static size_t headerCallback(void* data, size_t size, size_t nmemb, void* user) S32 status_code = atoi(status.c_str()); if (status_code > 0) { - complete->httpStatus((U32)status_code, reason); + complete->httpStatus(status_code, reason); return header_len; } } diff --git a/indra/llmessage/llurlrequest.h b/indra/llmessage/llurlrequest.h index 44d358d906..f334c92cc3 100644 --- a/indra/llmessage/llurlrequest.h +++ b/indra/llmessage/llurlrequest.h @@ -68,42 +68,22 @@ class LLURLRequest : public LLIOPipe { LOG_CLASS(LLURLRequest); public: - typedef int (* SSLCertVerifyCallback)(X509_STORE_CTX *ctx, void *param); - /** - * @brief This enumeration is for specifying the type of request. - */ - enum ERequestAction - { - INVALID, - HTTP_HEAD, - HTTP_GET, - HTTP_PUT, - HTTP_POST, - HTTP_DELETE, - HTTP_MOVE, // Caller will need to set 'Destination' header - REQUEST_ACTION_COUNT - }; - - /** - * @brief Turn the requst action into an http verb. - */ - static std::string actionAsVerb(ERequestAction action); /** * @brief Constructor. * - * @param action One of the ERequestAction enumerations. + * @param action One of the EHTTPMethod enumerations. */ - LLURLRequest(ERequestAction action); + LLURLRequest(EHTTPMethod action); /** * @brief Constructor. * - * @param action One of the ERequestAction enumerations. + * @param action One of the EHTTPMethod enumerations. * @param url The url of the request. It should already be encoded. */ - LLURLRequest(ERequestAction action, const std::string& url); + LLURLRequest(EHTTPMethod action, const std::string& url); /** * @brief Destructor. @@ -123,17 +103,17 @@ public: * */ void setURL(const std::string& url); - std::string getURL() const; + const std::string& getURL() const; /** * @brief Add a header to the http post. * - * The header must be correctly formatted for HTTP requests. This - * provides a raw interface if you know what kind of request you + * This provides a raw interface if you know what kind of request you * will be making during construction of this instance. All * required headers will be automatically constructed, so this is * usually useful for encoding parameters. */ - void addHeader(const char* header); + void addHeader(const std::string& header, const std::string& value = ""); + void addHeaderRaw(const char* header); /** * @brief Check remote server certificate signed by a known root CA. @@ -218,7 +198,7 @@ protected: STATE_HAVE_RESPONSE, }; EState mState; - ERequestAction mAction; + EHTTPMethod mAction; LLURLRequestDetail* mDetail; LLIOPipe::ptr_t mCompletionCallback; S32 mRequestTransferedBytes; @@ -315,7 +295,7 @@ public: // May be called more than once, particularly for redirects and proxy madness. // Ex. a 200 for a connection to https through a proxy, followed by the "real" status // a 3xx for a redirect followed by a "real" status, or more redirects. - virtual void httpStatus(U32 status, const std::string& reason) { } + virtual void httpStatus(S32 status, const std::string& reason) { } virtual void complete( const LLChannelDescriptors& channels, @@ -368,7 +348,7 @@ protected: //@} // value to note if we actually got the response. This value - // depends on correct useage from the LLURLRequest instance. + // depends on correct usage from the LLURLRequest instance. EStatus mRequestStatus; }; diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp index ae95087377..78b259c3f1 100644 --- a/indra/llmessage/message.cpp +++ b/indra/llmessage/message.cpp @@ -113,20 +113,20 @@ namespace { } - virtual void error(U32 status, const std::string& reason) + protected: + virtual void httpFailure() { // don't spam when agent communication disconnected already - if (status != 410) + if (HTTP_GONE != getStatus()) { - LL_WARNS("Messaging") << "error status " << status - << " for message " << mMessageName - << " reason " << reason << llendl; + 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 result(const LLSD& content) + virtual void httpSuccess() { if(NULL != mCallback) mCallback(mCallbackData, LL_ERR_NOERR); } diff --git a/indra/llmessage/tests/llcurl_stub.cpp b/indra/llmessage/tests/llcurl_stub.cpp index 9b298d0c04..b7fdf4f437 100644 --- a/indra/llmessage/tests/llcurl_stub.cpp +++ b/indra/llmessage/tests/llcurl_stub.cpp @@ -24,55 +24,76 @@ * $/LicenseInfo$ */ +#ifndef LL_CURL_STUB_CPP +#define LL_CURL_STUB_CPP + + #include "linden_common.h" #include "llcurl.h" +#include "llhttpconstants.cpp" LLCurl::Responder::Responder() { } -void LLCurl::Responder::completed(U32 status, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const &reason, - LLSD const& mContent) +void LLCurl::Responder::httpCompleted() { - if (isGoodStatus(status)) + if (isGoodStatus()) { - result(mContent); + httpSuccess(); } else { - errorWithContent(status, reason, mContent); + httpFailure(); } } -void LLCurl::Responder::completedHeader(unsigned, - std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, - LLSD const&) +void LLCurl::Responder::completedRaw(LLChannelDescriptors const&, + boost::shared_ptr<LLBufferArray> const&) { } -void LLCurl::Responder::completedRaw(unsigned, - std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, - LLChannelDescriptors const&, - boost::shared_ptr<LLBufferArray> const&) +void LLCurl::Responder::httpFailure() { } -void LLCurl::Responder::errorWithContent(unsigned, - std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, - LLSD const&) +LLCurl::Responder::~Responder () { } -LLCurl::Responder::~Responder () +void LLCurl::Responder::httpSuccess() +{ +} + +std::string LLCurl::Responder::dumpResponse() const +{ + return "dumpResponse()"; +} + +void LLCurl::Responder::successResult(const LLSD& content) { + setResult(HTTP_OK, "", content); + httpSuccess(); } -void LLCurl::Responder::error(unsigned, - std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) +void LLCurl::Responder::failureResult(S32 status, const std::string& reason, const LLSD& content) +{ + setResult(status, reason, content); + httpFailure(); +} + + +void LLCurl::Responder::completeResult(S32 status, const std::string& reason, const LLSD& content) { + setResult(status, reason, content); + httpCompleted(); } -void LLCurl::Responder::result(LLSD const&) +void LLCurl::Responder::setResult(S32 status, const std::string& reason, const LLSD& content /* = LLSD() */) { + mStatus = status; + mReason = reason; + mContent = content; } +#endif diff --git a/indra/llmessage/tests/llhttpclient_test.cpp b/indra/llmessage/tests/llhttpclient_test.cpp index 87cbafa404..bdc48ce53d 100644 --- a/indra/llmessage/tests/llhttpclient_test.cpp +++ b/indra/llmessage/tests/llhttpclient_test.cpp @@ -101,7 +101,7 @@ namespace tut if (mSawError) { std::string msg = - llformat("error() called when not expected, status %d", + llformat("httpFailure() called when not expected, status %d", mStatus); fail(msg); } @@ -111,7 +111,7 @@ namespace tut { if (!mSawError) { - fail("error() wasn't called"); + fail("httpFailure() wasn't called"); } } @@ -153,33 +153,26 @@ namespace tut mClient.mResultDeleted = true; } - virtual void error(U32 status, const std::string& reason) + protected: + virtual void httpFailure() { mClient.mSawError = true; - mClient.mStatus = status; - mClient.mReason = reason; + mClient.mStatus = getStatus(); + mClient.mReason = getReason(); } - virtual void result(const LLSD& content) + virtual void httpSuccess() { - mClient.mResult = content; + mClient.mResult = getContent(); } - virtual void completed( - U32 status, const std::string& reason, - const LLSD& content) + virtual void httpCompleted() { - LLHTTPClient::Responder::completed(status, reason, content); - + LLHTTPClient::Responder::httpCompleted(); + mClient.mSawCompleted = true; - } - - virtual void completedHeader( - U32 status, const std::string& reason, - const LLSD& content) - { - mClient.mHeader = content; mClient.mSawCompletedHeader = true; + mClient.mHeader = getResponseHeaders(); } private: diff --git a/indra/llmessage/tests/llhttpclientadapter_test.cpp b/indra/llmessage/tests/llhttpclientadapter_test.cpp index 13ce0a0edd..cc7feeab4f 100644 --- a/indra/llmessage/tests/llhttpclientadapter_test.cpp +++ b/indra/llmessage/tests/llhttpclientadapter_test.cpp @@ -1,6 +1,6 @@ /** - * @file - * @brief + * @file llhttpclientadapter_test.cpp + * @brief Tests for LLHTTPClientAdapter * * $LicenseInfo:firstyear=2008&license=viewerlgpl$ * Second Life Viewer Source Code @@ -33,8 +33,8 @@ float const HTTP_REQUEST_EXPIRY_SECS = 1.0F; std::vector<std::string> get_urls; -std::vector<boost::intrusive_ptr<LLCurl::Responder> > get_responders; -void LLHTTPClient::get(const std::string& url, boost::intrusive_ptr<LLCurl::Responder> responder, const LLSD& headers, const F32 timeout) +std::vector< LLCurl::ResponderPtr > get_responders; +void LLHTTPClient::get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers, const F32 timeout) { get_urls.push_back(url); get_responders.push_back(responder); @@ -42,16 +42,30 @@ void LLHTTPClient::get(const std::string& url, boost::intrusive_ptr<LLCurl::Resp std::vector<std::string> put_urls; std::vector<LLSD> put_body; -std::vector<boost::intrusive_ptr<LLCurl::Responder> > put_responders; +std::vector<LLSD> put_headers; +std::vector<LLCurl::ResponderPtr> put_responders; -void LLHTTPClient::put(const std::string& url, const LLSD& body, boost::intrusive_ptr<LLCurl::Responder> responder, const LLSD& headers, const F32 timeout) +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 { @@ -64,6 +78,9 @@ namespace tut put_urls.clear(); put_responders.clear(); put_body.clear(); + put_headers.clear(); + delete_urls.clear(); + delete_responders.clear(); } }; @@ -73,7 +90,7 @@ namespace tut namespace { - tut::factory tf("LLHTTPClientAdapterData test"); + tut::factory tf("LLHTTPClientAdapterData"); } namespace tut @@ -91,7 +108,7 @@ namespace tut { LLHTTPClientAdapter adapter; - boost::intrusive_ptr<LLCurl::Responder> responder = new LLCurl::Responder(); + LLCurl::ResponderPtr responder = new LLCurl::Responder(); adapter.get("Made up URL", responder); ensure_equals(get_urls.size(), 1); @@ -103,7 +120,7 @@ namespace tut void object::test<3>() { LLHTTPClientAdapter adapter; - boost::intrusive_ptr<LLCurl::Responder> responder = new LLCurl::Responder(); + LLCurl::ResponderPtr responder = new LLCurl::Responder(); adapter.get("Made up URL", responder); @@ -117,7 +134,7 @@ namespace tut { LLHTTPClientAdapter adapter; - boost::intrusive_ptr<LLCurl::Responder> responder = new LLCurl::Responder(); + LLCurl::ResponderPtr responder = new LLCurl::Responder(); LLSD body; body["TestBody"] = "Foobar"; @@ -133,7 +150,7 @@ namespace tut { LLHTTPClientAdapter adapter; - boost::intrusive_ptr<LLCurl::Responder> responder = new LLCurl::Responder(); + LLCurl::ResponderPtr responder = new LLCurl::Responder(); LLSD body; body["TestBody"] = "Foobar"; @@ -150,7 +167,7 @@ namespace tut { LLHTTPClientAdapter adapter; - boost::intrusive_ptr<LLCurl::Responder> responder = new LLCurl::Responder(); + LLCurl::ResponderPtr responder = new LLCurl::Responder(); LLSD body; body["TestBody"] = "Foobar"; @@ -160,5 +177,45 @@ namespace tut 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/llmime_test.cpp b/indra/llmessage/tests/llmime_test.cpp index aed5c4589c..f8bf03bbcb 100644 --- a/indra/llmessage/tests/llmime_test.cpp +++ b/indra/llmessage/tests/llmime_test.cpp @@ -29,6 +29,7 @@ #include "linden_common.h" #include "llsdserialize.h" +#include "llhttpconstants.cpp" #include "../llmime.h" diff --git a/indra/llmessage/tests/llregionpresenceverifier_test.cpp b/indra/llmessage/tests/llregionpresenceverifier_test.cpp deleted file mode 100644 index 5b89f2a8c6..0000000000 --- a/indra/llmessage/tests/llregionpresenceverifier_test.cpp +++ /dev/null @@ -1,108 +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 "linden_common.h" - -#include "../test/lltut.h" -#include "llregionpresenceverifier.h" -#include "llcurl_stub.cpp" -#include "llhost.cpp" -#include "net.cpp" -#include "lltesthttpclientadapter.cpp" - -class LLTestResponse : public LLRegionPresenceVerifier::Response -{ -public: - - virtual bool checkValidity(const LLSD& content) const - { - return true; - } - - virtual void onRegionVerified(const LLSD& region_details) - { - } - - virtual void onRegionVerificationFailed() - { - } - - virtual LLHTTPClientInterface& getHttpClient() - { - return mHttpInterface; - } - - LLTestHTTPClientAdapter mHttpInterface; -}; - -namespace tut -{ - struct LLRegionPresenceVerifierData - { - LLRegionPresenceVerifierData() : - mResponse(new LLTestResponse()), - mResponder("", LLRegionPresenceVerifier::ResponsePtr(mResponse), - LLSD(), 3) - { - } - - LLTestResponse* mResponse; - LLRegionPresenceVerifier::VerifiedDestinationResponder mResponder; - }; - - typedef test_group<LLRegionPresenceVerifierData> factory; - typedef factory::object object; -} - -namespace -{ - tut::factory tf("LLRegionPresenceVerifier"); -} - -namespace tut -{ - // Test that VerifiedDestinationResponder does retry - // on error when shouldRetry returns true. - template<> template<> - void object::test<1>() - { - mResponder.error(500, "Internal server error"); - ensure_equals(mResponse->mHttpInterface.mGetUrl.size(), 1); - } - - // Test that VerifiedDestinationResponder only retries - // on error until shouldRetry returns false. - template<> template<> - void object::test<2>() - { - mResponder.error(500, "Internal server error"); - mResponder.error(500, "Internal server error"); - mResponder.error(500, "Internal server error"); - mResponder.error(500, "Internal server error"); - ensure_equals(mResponse->mHttpInterface.mGetUrl.size(), 3); - } -} - diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index baedac1f2d..eb41c0aa3a 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -2068,10 +2068,21 @@ if (LL_TESTS) #llviewertexturelist.cpp ) + set(test_libs + ${JSONCPP_LIBRARIES} + ${CURL_LIBRARIES} + ) + set_source_files_properties( lltranslate.cpp PROPERTIES - LL_TEST_ADDITIONAL_LIBRARIES "${JSONCPP_LIBRARIES}" + LL_TEST_ADDITIONAL_LIBRARIES "${test_libs}" + ) + + set_source_files_properties( + llmediadataclient.cpp + PROPERTIES + LL_TEST_ADDITIONAL_LIBRARIES "${CURL_LIBRARIES}" ) set_source_files_properties( diff --git a/indra/newview/llaccountingcostmanager.cpp b/indra/newview/llaccountingcostmanager.cpp index 7662a9689d..55d453cdcc 100644 --- a/indra/newview/llaccountingcostmanager.cpp +++ b/indra/newview/llaccountingcostmanager.cpp @@ -36,6 +36,7 @@ LLAccountingCostManager::LLAccountingCostManager() //=============================================================================== class LLAccountingCostResponder : public LLCurl::Responder { + LOG_CLASS(LLAccountingCostResponder); public: LLAccountingCostResponder( const LLSD& objectIDs, const LLHandle<LLAccountingCostObserver>& observer_handle ) : mObjectIDs( objectIDs ), @@ -56,24 +57,27 @@ public: } } - void errorWithContent( U32 statusNum, const std::string& reason, const LLSD& content ) +protected: + void httpFailure() { - llwarns << "Transport error [status:" << statusNum << "]: " << content <<llendl; + llwarns << dumpResponse() << llendl; clearPendingRequests(); LLAccountingCostObserver* observer = mObserverHandle.get(); if (observer && observer->getTransactionID() == mTransactionID) { - observer->setErrorStatus(statusNum, reason); + observer->setErrorStatus(getStatus(), getReason()); } } - void result( const LLSD& content ) + void httpSuccess() { + const LLSD& content = getContent(); //Check for error if ( !content.isMap() || content.has("error") ) { - llwarns << "Error on fetched data"<< llendl; + failureResult(HTTP_INTERNAL_ERROR, "Error on fetched data", content); + return; } else if (content.has("selected")) { diff --git a/indra/newview/llaccountingcostmanager.h b/indra/newview/llaccountingcostmanager.h index 0bca1f54ef..3ade34c81d 100644 --- a/indra/newview/llaccountingcostmanager.h +++ b/indra/newview/llaccountingcostmanager.h @@ -38,7 +38,7 @@ public: LLAccountingCostObserver() { mObserverHandle.bind(this); } virtual ~LLAccountingCostObserver() {} virtual void onWeightsUpdate(const SelectionCost& selection_cost) = 0; - virtual void setErrorStatus(U32 status, const std::string& reason) = 0; + virtual void setErrorStatus(S32 status, const std::string& reason) = 0; const LLHandle<LLAccountingCostObserver>& getObserverHandle() const { return mObserverHandle; } const LLUUID& getTransactionID() { return mTransactionID; } diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 20954e4bae..4b0f451036 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -2546,17 +2546,19 @@ int LLAgent::convertTextToMaturity(char text) class LLMaturityPreferencesResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLMaturityPreferencesResponder); public: LLMaturityPreferencesResponder(LLAgent *pAgent, U8 pPreferredMaturity, U8 pPreviousMaturity); virtual ~LLMaturityPreferencesResponder(); - virtual void result(const LLSD &pContent); - virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent); +protected: + virtual void httpSuccess(); + virtual void httpFailure(); protected: private: - U8 parseMaturityFromServerResponse(const LLSD &pContent); + U8 parseMaturityFromServerResponse(const LLSD &pContent) const; LLAgent *mAgent; U8 mPreferredMaturity; @@ -2575,29 +2577,33 @@ LLMaturityPreferencesResponder::~LLMaturityPreferencesResponder() { } -void LLMaturityPreferencesResponder::result(const LLSD &pContent) +void LLMaturityPreferencesResponder::httpSuccess() { - U8 actualMaturity = parseMaturityFromServerResponse(pContent); + U8 actualMaturity = parseMaturityFromServerResponse(getContent()); if (actualMaturity != mPreferredMaturity) { - llwarns << "while attempting to change maturity preference from '" << LLViewerRegion::accessToString(mPreviousMaturity) - << "' to '" << LLViewerRegion::accessToString(mPreferredMaturity) << "', the server responded with '" - << LLViewerRegion::accessToString(actualMaturity) << "' [value:" << static_cast<U32>(actualMaturity) << ", llsd:" - << pContent << "]" << llendl; + llwarns << "while attempting to change maturity preference from '" + << LLViewerRegion::accessToString(mPreviousMaturity) + << "' to '" << LLViewerRegion::accessToString(mPreferredMaturity) + << "', the server responded with '" + << LLViewerRegion::accessToString(actualMaturity) + << "' [value:" << static_cast<U32>(actualMaturity) + << "], " << dumpResponse() << llendl; } mAgent->handlePreferredMaturityResult(actualMaturity); } -void LLMaturityPreferencesResponder::errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent) +void LLMaturityPreferencesResponder::httpFailure() { - llwarns << "while attempting to change maturity preference from '" << LLViewerRegion::accessToString(mPreviousMaturity) - << "' to '" << LLViewerRegion::accessToString(mPreferredMaturity) << "', we got an error with [status:" - << pStatus << "]: " << (pContent.isDefined() ? pContent : LLSD(pReason)) << llendl; + llwarns << "while attempting to change maturity preference from '" + << LLViewerRegion::accessToString(mPreviousMaturity) + << "' to '" << LLViewerRegion::accessToString(mPreferredMaturity) + << "', " << dumpResponse() << llendl; mAgent->handlePreferredMaturityError(); } -U8 LLMaturityPreferencesResponder::parseMaturityFromServerResponse(const LLSD &pContent) +U8 LLMaturityPreferencesResponder::parseMaturityFromServerResponse(const LLSD &pContent) const { // stinson 05/24/2012 Pathfinding regions have re-defined the response behavior. In the old server code, // if you attempted to change the preferred maturity to the same value, the response content would be an @@ -2605,7 +2611,7 @@ U8 LLMaturityPreferencesResponder::parseMaturityFromServerResponse(const LLSD &p // defined. Thus, the check for isUndefined() can be replaced with an assert after pathfinding is merged // into server trunk and fully deployed. U8 maturity = SIM_ACCESS_MIN; - if (pContent.isUndefined()) + if (pContent.isUndefined() || !pContent.isMap()) { maturity = mPreferredMaturity; } @@ -2783,7 +2789,7 @@ void LLAgent::sendMaturityPreferenceToServer(U8 pPreferredMaturity) // If we don't have a region, report it as an error if (getRegion() == NULL) { - responderPtr->errorWithContent(0U, "region is not defined", LLSD()); + responderPtr->failureResult(0U, "region is not defined", LLSD()); } else { @@ -2793,7 +2799,7 @@ void LLAgent::sendMaturityPreferenceToServer(U8 pPreferredMaturity) // If the capability is not defined, report it as an error if (url.empty()) { - responderPtr->errorWithContent(0U, + responderPtr->failureResult(0U, "capability 'UpdateAgentInformation' is not defined for region", LLSD()); } else @@ -3292,8 +3298,7 @@ class LLAgentDropGroupViewerNode : public LLHTTPNode !input.has("body") ) { //what to do with badly formed message? - response->statusUnknownError(400); - response->result(LLSD("Invalid message parameters")); + response->extendedResult(HTTP_BAD_REQUEST, LLSD("Invalid message parameters")); } LLSD body = input["body"]; @@ -3362,8 +3367,7 @@ class LLAgentDropGroupViewerNode : public LLHTTPNode else { //what to do with badly formed message? - response->statusUnknownError(400); - response->result(LLSD("Invalid message parameters")); + response->extendedResult(HTTP_BAD_REQUEST, LLSD("Invalid message parameters")); } } }; diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 2c76efc7fb..92a896a3c2 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2984,20 +2984,23 @@ class LLHTTPRetryPolicy: public LLThreadSafeRefCount public: LLHTTPRetryPolicy() {} virtual ~LLHTTPRetryPolicy() {} - virtual bool shouldRetry(U32 status, F32& seconds_to_wait) = 0; + virtual bool shouldRetry(S32 status, const LLSD& headers, F32& seconds_to_wait) = 0; }; // Example of simplest possible policy, not necessarily recommended. +// This would be a potentially dangerous policy to enable. Removing for now: +#if 0 class LLAlwaysRetryImmediatelyPolicy: public LLHTTPRetryPolicy { public: LLAlwaysRetryImmediatelyPolicy() {} - bool shouldRetry(U32 status, F32& seconds_to_wait) + bool shouldRetry(S32 status, const LLSD& headers, F32& seconds_to_wait) { seconds_to_wait = 0.0; return true; } }; +#endif // Very general policy with geometric back-off after failures, // up to a maximum delay, and maximum number of retries. @@ -3014,10 +3017,25 @@ public: { } - bool shouldRetry(U32 status, F32& seconds_to_wait) + bool shouldRetry(S32 status, const LLSD& headers, F32& seconds_to_wait) { - seconds_to_wait = mDelay; - mDelay = llclamp(mDelay*mBackoffFactor,mMinDelay,mMaxDelay); +#if 0 + // *TODO: Test using status codes to only retry server errors. + // Only server errors would potentially return a different result on retry. + if (!isHttpServerErrorStatus(status)) return false; +#endif + +#if 0 + // *TODO: Honor server Retry-After header. + // Status 503 may ask us to wait for a certain amount of time before retrying. + if (!headers.has(HTTP_HEADER_RETRY_AFTER) + || !getSecondsUntilRetryAfter(headers[HTTP_HEADER_RETRY_AFTER].asStringRef(), seconds_to_wait)) +#endif + { + seconds_to_wait = mDelay; + mDelay = llclamp(mDelay*mBackoffFactor,mMinDelay,mMaxDelay); + } + mRetryCount++; return (mRetryCount<=mMaxRetries); } @@ -3033,6 +3051,7 @@ private: class RequestAgentUpdateAppearanceResponder: public LLHTTPClient::Responder { + LOG_CLASS(RequestAgentUpdateAppearanceResponder); public: RequestAgentUpdateAppearanceResponder() { @@ -3043,13 +3062,19 @@ public: { } +protected: // Successful completion. - /* virtual */ void result(const LLSD& content) + /* virtual */ void httpSuccess() { - LL_DEBUGS("Avatar") << "content: " << ll_pretty_print_sd(content) << LL_ENDL; + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } if (content["success"].asBoolean()) { - LL_DEBUGS("Avatar") << "OK" << LL_ENDL; + LL_DEBUGS("Avatar") << dumpResponse() << LL_ENDL; if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) { dumpContents(gAgentAvatarp->getFullname() + "_appearance_request_ok", content); @@ -3057,33 +3082,35 @@ public: } else { - onFailure(200); + failureResult(HTTP_INTERNAL_ERROR, "Non-success response", content); } } // Error - /*virtual*/ void errorWithContent(U32 status, const std::string& reason, const LLSD& content) + /*virtual*/ void httpFailure() { - llwarns << "appearance update request failed, status: " << status << " reason: " << reason << " code: " << content["code"].asInteger() << " error: \"" << content["error"].asString() << "\"" << llendl; + const LLSD& content = getContent(); + LL_WARNS("Avatar") << "appearance update request failed " + << dumpResponse() << LL_ENDL; if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) { dumpContents(gAgentAvatarp->getFullname() + "_appearance_request_error", content); debugCOF(content); } - onFailure(status); - } + onFailure(); + } - void onFailure(U32 status) + void onFailure() { F32 seconds_to_wait; - if (mRetryPolicy->shouldRetry(status,seconds_to_wait)) + if (mRetryPolicy->shouldRetry(getStatus(), getResponseHeaders(), seconds_to_wait)) { llinfos << "retrying" << llendl; doAfterInterval(boost::bind(&LLAppearanceMgr::requestServerAppearanceUpdate, LLAppearanceMgr::getInstance(), - LLCurl::ResponderPtr(this)), - seconds_to_wait); + LLHTTPClient::ResponderPtr(this)), + seconds_to_wait); } else { @@ -3286,6 +3313,7 @@ void LLAppearanceMgr::requestServerAppearanceUpdate(LLCurl::ResponderPtr respond class LLIncrementCofVersionResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLIncrementCofVersionResponder); public: LLIncrementCofVersionResponder() : LLHTTPClient::Responder() { @@ -3296,10 +3324,17 @@ public: { } - virtual void result(const LLSD &pContent) +protected: + virtual void httpSuccess() { llinfos << "Successfully incremented agent's COF." << llendl; - S32 new_version = pContent["category"]["version"].asInteger(); + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } + S32 new_version = content["category"]["version"].asInteger(); LLAppearanceMgr* app_mgr = LLAppearanceMgr::getInstance(); @@ -3308,12 +3343,13 @@ public: app_mgr->mLastUpdateRequestCOFVersion = new_version; } - virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& content) + + virtual void httpFailure() { - llwarns << "While attempting to increment the agent's cof we got an error with [status:" - << pStatus << "]: " << content << llendl; + LL_WARNS("Avatar") << "While attempting to increment the agent's cof we got an error " + << dumpResponse() << LL_ENDL; F32 seconds_to_wait; - if (mRetryPolicy->shouldRetry(pStatus,seconds_to_wait)) + if (mRetryPolicy->shouldRetry(getStatus(), getResponseHeaders(), seconds_to_wait)) { llinfos << "retrying" << llendl; doAfterInterval(boost::bind(&LLAppearanceMgr::incrementCofVersion, @@ -3327,6 +3363,7 @@ public: } } +private: LLPointer<LLHTTPRetryPolicy> mRetryPolicy; }; diff --git a/indra/newview/llassetuploadqueue.cpp b/indra/newview/llassetuploadqueue.cpp index 4bdb690225..cde9bc9dc0 100644 --- a/indra/newview/llassetuploadqueue.cpp +++ b/indra/newview/llassetuploadqueue.cpp @@ -36,6 +36,7 @@ class LLAssetUploadChainResponder : public LLUpdateTaskInventoryResponder { + LOG_CLASS(LLAssetUploadChainResponder); public: LLAssetUploadChainResponder(const LLSD& post_data, @@ -51,52 +52,54 @@ public: mDataSize(data_size), mScriptName(script_name) { - } + } virtual ~LLAssetUploadChainResponder() - { - if(mSupplier) - { - LLAssetUploadQueue *queue = mSupplier->get(); - if (queue) - { - // Give ownership of supplier back to queue. - queue->mSupplier = mSupplier; - mSupplier = NULL; - } - } - delete mSupplier; + { + if(mSupplier) + { + LLAssetUploadQueue *queue = mSupplier->get(); + if (queue) + { + // Give ownership of supplier back to queue. + queue->mSupplier = mSupplier; + mSupplier = NULL; + } + } + delete mSupplier; delete mData; - } + } - virtual void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) - { - llwarns << "LLAssetUploadChainResponder Error [status:" - << statusNum << "]: " << content << llendl; - LLUpdateTaskInventoryResponder::errorWithContent(statusNum, reason, content); - LLAssetUploadQueue *queue = mSupplier->get(); - if (queue) +protected: + virtual void httpFailure() + { + // Parent class will spam the failure. + //llwarns << dumpResponse() << llendl; + LLUpdateTaskInventoryResponder::httpFailure(); + LLAssetUploadQueue *queue = mSupplier->get(); + if (queue) + { + queue->request(&mSupplier); + } + } + + virtual void httpSuccess() + { + LLUpdateTaskInventoryResponder::httpSuccess(); + LLAssetUploadQueue *queue = mSupplier->get(); + if (queue) { - queue->request(&mSupplier); - } - } - - virtual void result(const LLSD& content) - { - LLUpdateTaskInventoryResponder::result(content); - LLAssetUploadQueue *queue = mSupplier->get(); - if (queue) - { - // Responder is reused across 2 phase upload, - // so only start next upload after 2nd phase complete. - std::string state = content["state"]; - if(state == "complete") - { - queue->request(&mSupplier); - } - } - } + // Responder is reused across 2 phase upload, + // so only start next upload after 2nd phase complete. + const std::string& state = getContent()["state"].asStringRef(); + if(state == "complete") + { + queue->request(&mSupplier); + } + } + } +public: virtual void uploadUpload(const LLSD& content) { std::string uploader = content["uploader"]; diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index 2564802387..ea511b18e2 100644 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -225,37 +225,41 @@ LLAssetUploadResponder::~LLAssetUploadResponder() } // virtual -void LLAssetUploadResponder::errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) +void LLAssetUploadResponder::httpFailure() { - llinfos << "LLAssetUploadResponder::error [status:" - << statusNum << "]: " << content << llendl; + // *TODO: Add adaptive retry policy? + llwarns << dumpResponse() << llendl; LLSD args; - switch(statusNum) + if (isHttpClientErrorStatus(getStatus())) { - case 400: - args["FILE"] = (mFileName.empty() ? mVFileID.asString() : mFileName); - args["REASON"] = "Error in upload request. Please visit " - "http://secondlife.com/support for help fixing this problem."; - LLNotificationsUtil::add("CannotUploadReason", args); - break; - case 500: - default: - args["FILE"] = (mFileName.empty() ? mVFileID.asString() : mFileName); - args["REASON"] = "The server is experiencing unexpected " - "difficulties."; - LLNotificationsUtil::add("CannotUploadReason", args); - break; + args["FILE"] = (mFileName.empty() ? mVFileID.asString() : mFileName); + args["REASON"] = "Error in upload request. Please visit " + "http://secondlife.com/support for help fixing this problem."; + LLNotificationsUtil::add("CannotUploadReason", args); + } + else + { + args["FILE"] = (mFileName.empty() ? mVFileID.asString() : mFileName); + args["REASON"] = "The server is experiencing unexpected " + "difficulties."; + LLNotificationsUtil::add("CannotUploadReason", args); } LLUploadDialog::modalUploadFinished(); LLFilePicker::instance().reset(); // unlock file picker when bulk upload fails } //virtual -void LLAssetUploadResponder::result(const LLSD& content) +void LLAssetUploadResponder::httpSuccess() { + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } lldebugs << "LLAssetUploadResponder::result from capabilities" << llendl; - std::string state = content["state"]; + const std::string& state = content["state"].asStringRef(); if (state == "upload") { @@ -280,7 +284,7 @@ void LLAssetUploadResponder::result(const LLSD& content) void LLAssetUploadResponder::uploadUpload(const LLSD& content) { - std::string uploader = content["uploader"]; + const std::string& uploader = content["uploader"].asStringRef(); if (mFileName.empty()) { LLHTTPClient::postFile(uploader, mVFileID, mAssetType, this); @@ -293,6 +297,7 @@ void LLAssetUploadResponder::uploadUpload(const LLSD& content) void LLAssetUploadResponder::uploadFailure(const LLSD& content) { + llwarns << dumpResponse() << llendl; // remove the "Uploading..." message LLUploadDialog::modalUploadFinished(); LLFloater* floater_snapshot = LLFloaterReg::findInstance("snapshot"); @@ -301,7 +306,7 @@ void LLAssetUploadResponder::uploadFailure(const LLSD& content) floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", false).with("msg", "inventory"))); } - std::string reason = content["state"]; + const std::string& reason = content["state"].asStringRef(); // deal with L$ errors if (reason == "insufficient funds") { @@ -340,9 +345,9 @@ LLNewAgentInventoryResponder::LLNewAgentInventoryResponder( } // virtual -void LLNewAgentInventoryResponder::errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) +void LLNewAgentInventoryResponder::httpFailure() { - LLAssetUploadResponder::errorWithContent(statusNum, reason, content); + LLAssetUploadResponder::httpFailure(); //LLImportColladaAssetCache::getInstance()->assetUploaded(mVFileID, LLUUID(), FALSE); } @@ -487,10 +492,9 @@ void LLSendTexLayerResponder::uploadComplete(const LLSD& content) } } -void LLSendTexLayerResponder::errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) +void LLSendTexLayerResponder::httpFailure() { - llinfos << "LLSendTexLayerResponder error [status:" - << statusNum << "]: " << content << llendl; + llwarns << dumpResponse() << llendl; // Invoke the original callback with an error result LLViewerTexLayerSetBuffer::onTextureUploadComplete(LLUUID(), (void*) mBakedUploadData, -1, LL_EXSTAT_NONE); @@ -1009,19 +1013,14 @@ LLNewAgentInventoryVariablePriceResponder::~LLNewAgentInventoryVariablePriceResp delete mImpl; } -void LLNewAgentInventoryVariablePriceResponder::errorWithContent( - U32 statusNum, - const std::string& reason, - const LLSD& content) +void LLNewAgentInventoryVariablePriceResponder::httpFailure() { - lldebugs - << "LLNewAgentInventoryVariablePrice::error " << statusNum - << " reason: " << reason << llendl; + const LLSD& content = getContent(); + LL_WARNS("Upload") << dumpResponse() << LL_ENDL; - if ( content.has("error") ) + static const std::string _ERROR = "error"; + if ( content.has(_ERROR) ) { - static const std::string _ERROR = "error"; - mImpl->onTransportError(content[_ERROR]); } else @@ -1030,8 +1029,14 @@ void LLNewAgentInventoryVariablePriceResponder::errorWithContent( } } -void LLNewAgentInventoryVariablePriceResponder::result(const LLSD& content) +void LLNewAgentInventoryVariablePriceResponder::httpSuccess() { + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } // Parse out application level errors and the appropriate // responses for them static const std::string _ERROR = "error"; @@ -1047,6 +1052,7 @@ void LLNewAgentInventoryVariablePriceResponder::result(const LLSD& content) // Check for application level errors if ( content.has(_ERROR) ) { + LL_WARNS("Upload") << dumpResponse() << LL_ENDL; onApplicationLevelError(content[_ERROR]); return; } @@ -1090,6 +1096,7 @@ void LLNewAgentInventoryVariablePriceResponder::result(const LLSD& content) } else { + LL_WARNS("Upload") << dumpResponse() << LL_ENDL; onApplicationLevelError(""); } } diff --git a/indra/newview/llassetuploadresponders.h b/indra/newview/llassetuploadresponders.h index a6d1016136..abfdc4ca77 100644 --- a/indra/newview/llassetuploadresponders.h +++ b/indra/newview/llassetuploadresponders.h @@ -33,6 +33,8 @@ // via capabilities class LLAssetUploadResponder : public LLHTTPClient::Responder { +protected: + LOG_CLASS(LLAssetUploadResponder); public: LLAssetUploadResponder(const LLSD& post_data, const LLUUID& vfile_id, @@ -42,8 +44,11 @@ public: LLAssetType::EType asset_type); ~LLAssetUploadResponder(); - virtual void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content); - virtual void result(const LLSD& content); +protected: + virtual void httpFailure(); + virtual void httpSuccess(); + +public: virtual void uploadUpload(const LLSD& content); virtual void uploadComplete(const LLSD& content); virtual void uploadFailure(const LLSD& content); @@ -58,6 +63,7 @@ protected: // TODO*: Remove this once deprecated class LLNewAgentInventoryResponder : public LLAssetUploadResponder { + LOG_CLASS(LLNewAgentInventoryResponder); public: LLNewAgentInventoryResponder( const LLSD& post_data, @@ -67,9 +73,10 @@ public: const LLSD& post_data, const std::string& file_name, LLAssetType::EType asset_type); - virtual void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content); virtual void uploadComplete(const LLSD& content); virtual void uploadFailure(const LLSD& content); +protected: + virtual void httpFailure(); }; // A base class which goes through and performs some default @@ -79,6 +86,7 @@ public: class LLNewAgentInventoryVariablePriceResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLNewAgentInventoryVariablePriceResponder); public: LLNewAgentInventoryVariablePriceResponder( const LLUUID& vfile_id, @@ -91,12 +99,11 @@ public: const LLSD& inventory_info); virtual ~LLNewAgentInventoryVariablePriceResponder(); - void errorWithContent( - U32 statusNum, - const std::string& reason, - const LLSD& content); - void result(const LLSD& content); +private: + /* virtual */ void httpFailure(); + /* virtual */ void httpSuccess(); +public: virtual void onApplicationLevelError( const LLSD& error); virtual void showConfirmationDialog( @@ -122,8 +129,11 @@ public: ~LLSendTexLayerResponder(); virtual void uploadComplete(const LLSD& content); - virtual void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content); +protected: + virtual void httpFailure(); + +private: LLBakedUploadData * mBakedUploadData; }; diff --git a/indra/newview/llclassifiedstatsresponder.cpp b/indra/newview/llclassifiedstatsresponder.cpp index e3cd83e174..923662e887 100644 --- a/indra/newview/llclassifiedstatsresponder.cpp +++ b/indra/newview/llclassifiedstatsresponder.cpp @@ -44,8 +44,14 @@ mClassifiedID(classified_id) } /*virtual*/ -void LLClassifiedStatsResponder::result(const LLSD& content) +void LLClassifiedStatsResponder::httpSuccess() { + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } S32 teleport = content["teleport_clicks"].asInteger(); S32 map = content["map_clicks"].asInteger(); S32 profile = content["profile_clicks"].asInteger(); @@ -62,7 +68,8 @@ void LLClassifiedStatsResponder::result(const LLSD& content) } /*virtual*/ -void LLClassifiedStatsResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) +void LLClassifiedStatsResponder::httpFailure() { - llinfos << "LLClassifiedStatsResponder::error [status:" << status << "]: " << content << llendl; + llwarns << dumpResponse() << llendl; } + diff --git a/indra/newview/llclassifiedstatsresponder.h b/indra/newview/llclassifiedstatsresponder.h index 06dcb62fd0..efa4d82411 100644 --- a/indra/newview/llclassifiedstatsresponder.h +++ b/indra/newview/llclassifiedstatsresponder.h @@ -33,13 +33,15 @@ class LLClassifiedStatsResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLClassifiedStatsResponder); public: LLClassifiedStatsResponder(LLUUID classified_id); + +protected: //If we get back a normal response, handle it here - virtual void result(const LLSD& content); + virtual void httpSuccess(); //If we get back an error (not found, etc...), handle it here - - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content); + virtual void httpFailure(); protected: LLUUID mClassifiedID; diff --git a/indra/newview/llestateinfomodel.cpp b/indra/newview/llestateinfomodel.cpp index 2669b0340f..db2c15a444 100644 --- a/indra/newview/llestateinfomodel.cpp +++ b/indra/newview/llestateinfomodel.cpp @@ -112,19 +112,19 @@ void LLEstateInfoModel::notifyCommit() class LLEstateChangeInfoResponder : public LLHTTPClient::Responder { -public: - + LOG_CLASS(LLEstateChangeInfoResponder); +protected: // if we get a normal response, handle it here - virtual void result(const LLSD& content) + virtual void httpSuccesss() { llinfos << "Committed estate info" << llendl; LLEstateInfoModel::instance().notifyCommit(); } // if we get an error response - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content) + virtual void httpFailure() { - llwarns << "Failed to commit estate info [status:" << status << "]: " << content << llendl; + llwarns << "Failed to commit estate info " << dumpResponse() << llendl; } }; diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp index e0f7223a8c..c3b53d5e4a 100644 --- a/indra/newview/lleventpoll.cpp +++ b/indra/newview/lleventpoll.cpp @@ -31,7 +31,7 @@ #include "llagent.h" #include "llhttpclient.h" -#include "llhttpstatuscodes.h" +#include "llhttpconstants.h" #include "llsdserialize.h" #include "lleventtimer.h" #include "llviewerregion.h" @@ -49,6 +49,7 @@ namespace class LLEventPollResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLEventPollResponder); public: static LLHTTPClient::ResponderPtr start(const std::string& pollURL, const LLHost& sender); @@ -56,19 +57,19 @@ namespace void makeRequest(); + /* virtual */ void completedRaw(const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer); + private: LLEventPollResponder(const std::string& pollURL, const LLHost& sender); ~LLEventPollResponder(); void handleMessage(const LLSD& content); - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content); - virtual void result(const LLSD& content); - virtual void completedRaw(U32 status, - const std::string& reason, - const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer); + /* virtual */ void httpFailure(); + /* virtual */ void httpSuccess(); + private: bool mDone; @@ -149,20 +150,18 @@ namespace } // virtual - void LLEventPollResponder::completedRaw(U32 status, - const std::string& reason, - const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer) + void LLEventPollResponder::completedRaw(const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) { - if (status == HTTP_BAD_GATEWAY) + if (getStatus() == HTTP_BAD_GATEWAY) { // These errors are not parsable as LLSD, // which LLHTTPClient::Responder::completedRaw will try to do. - completed(status, reason, LLSD()); + httpCompleted(); } else { - LLHTTPClient::Responder::completedRaw(status,reason,channels,buffer); + LLHTTPClient::Responder::completedRaw(channels,buffer); } } @@ -187,13 +186,13 @@ namespace } //virtual - void LLEventPollResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) + void LLEventPollResponder::httpFailure() { if (mDone) return; // A HTTP_BAD_GATEWAY (502) error is our standard timeout response // we get this when there are no events. - if ( status == HTTP_BAD_GATEWAY ) + if ( getStatus() == HTTP_BAD_GATEWAY ) { mErrorCount = 0; makeRequest(); @@ -207,12 +206,12 @@ namespace + mErrorCount * EVENT_POLL_ERROR_RETRY_SECONDS_INC , this); - llwarns << "LLEventPollResponder error [status:" << status << "]: " << content << llendl; + llwarns << dumpResponse() << llendl; } else { - llwarns << "LLEventPollResponder error <" << mCount - << "> [status:" << status << "]: " << content + llwarns << dumpResponse() + << " [count:" << mCount << "] " << (mDone ? " -- done" : "") << llendl; stop(); @@ -234,7 +233,7 @@ namespace } //virtual - void LLEventPollResponder::result(const LLSD& content) + void LLEventPollResponder::httpSuccess() { lldebugs << "LLEventPollResponder::result <" << mCount << ">" << (mDone ? " -- done" : "") << llendl; @@ -243,10 +242,12 @@ namespace mErrorCount = 0; - if (!content.get("events") || + const LLSD& content = getContent(); + if (!content.isMap() || + !content.get("events") || !content.get("id")) { - llwarns << "received event poll with no events or id key" << llendl; + llwarns << "received event poll with no events or id key: " << dumpResponse() << llendl; makeRequest(); return; } diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp index a4cadcd5dc..c4ae718082 100644 --- a/indra/newview/llfeaturemanager.cpp +++ b/indra/newview/llfeaturemanager.cpp @@ -39,6 +39,7 @@ #include "llsecondlifeurls.h" #include "llappviewer.h" +#include "llbufferstream.h" #include "llhttpclient.h" #include "llnotificationsutil.h" #include "llviewercontrol.h" @@ -509,6 +510,7 @@ void LLFeatureManager::parseGPUTable(std::string filename) // responder saves table into file class LLHTTPFeatureTableResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLHTTPFeatureTableResponder); public: LLHTTPFeatureTableResponder(std::string filename) : @@ -517,11 +519,10 @@ public: } - virtual void completedRaw(U32 status, const std::string& reason, - const LLChannelDescriptors& channels, + virtual void completedRaw(const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer) { - if (isGoodStatus(status)) + if (isGoodStatus()) { // write to file @@ -540,7 +541,18 @@ public: out.close(); } } - + else + { + char body[1025]; + body[1024] = '\0'; + LLBufferStream istr(channels, buffer.get()); + istr.get(body,1024); + if (strlen(body) > 0) + { + mContent["body"] = body; + } + llwarns << dumpResponse() << llendl; + } } private: diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index d13f85baa2..89d74666f7 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -1240,9 +1240,9 @@ static std::string add_imageload_filter_to_gtkchooser(GtkWindow *picker) { GtkFileFilter *gfilter = gtk_file_filter_new(); gtk_file_filter_add_pattern(gfilter, "*.tga"); - gtk_file_filter_add_mime_type(gfilter, "image/jpeg"); - gtk_file_filter_add_mime_type(gfilter, "image/png"); - gtk_file_filter_add_mime_type(gfilter, "image/bmp"); + gtk_file_filter_add_mime_type(gfilter, HTTP_CONTENT_IMAGE_JPEG.c_str()); + gtk_file_filter_add_mime_type(gfilter, HTTP_CONTENT_IMAGE_PNG.c_str()); + gtk_file_filter_add_mime_type(gfilter, HTTP_CONTENT_IMAGE_BMP.c_str()); std::string filtername = LLTrans::getString("image_files") + " (*.tga; *.bmp; *.jpg; *.png)"; add_common_filters_to_gtkchooser(gfilter, picker, filtername); return filtername; @@ -1250,13 +1250,13 @@ static std::string add_imageload_filter_to_gtkchooser(GtkWindow *picker) static std::string add_script_filter_to_gtkchooser(GtkWindow *picker) { - return add_simple_mime_filter_to_gtkchooser(picker, "text/plain", + return add_simple_mime_filter_to_gtkchooser(picker, HTTP_CONTENT_TEXT_PLAIN, LLTrans::getString("script_files") + " (*.lsl)"); } static std::string add_dictionary_filter_to_gtkchooser(GtkWindow *picker) { - return add_simple_mime_filter_to_gtkchooser(picker, "text/plain", + return add_simple_mime_filter_to_gtkchooser(picker, HTTP_CONTENT_TEXT_PLAIN, LLTrans::getString("dictionary_files") + " (*.dic; *.xcu)"); } @@ -1294,7 +1294,7 @@ BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename break; case FFSAVE_BMP: caption += add_simple_mime_filter_to_gtkchooser - (picker, "image/bmp", LLTrans::getString("bitmap_image_files") + " (*.bmp)"); + (picker, HTTP_CONTENT_IMAGE_BMP, LLTrans::getString("bitmap_image_files") + " (*.bmp)"); suggest_ext = ".bmp"; break; case FFSAVE_AVI: @@ -1319,6 +1319,7 @@ BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename suggest_ext = ".raw"; break; case FFSAVE_J2C: + // *TODO: Should this be 'image/j2c' ? caption += add_simple_mime_filter_to_gtkchooser (picker, "images/jp2", LLTrans::getString("compressed_image_files") + " (*.j2c)"); diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp index 83fb887d81..63888ace11 100644 --- a/indra/newview/llfloaterabout.cpp +++ b/indra/newview/llfloaterabout.cpp @@ -77,14 +77,9 @@ class LLServerReleaseNotesURLFetcher : public LLHTTPClient::Responder { LOG_CLASS(LLServerReleaseNotesURLFetcher); public: - static void startFetch(); - /*virtual*/ void completedHeader(U32 status, const std::string& reason, const LLSD& content); - /*virtual*/ void completedRaw( - U32 status, - const std::string& reason, - const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer); +private: + /* virtual */ void httpCompleted(); }; ///---------------------------------------------------------------------------- @@ -471,32 +466,27 @@ void LLServerReleaseNotesURLFetcher::startFetch() } // virtual -void LLServerReleaseNotesURLFetcher::completedHeader(U32 status, const std::string& reason, const LLSD& content) +void LLServerReleaseNotesURLFetcher::httpCompleted() { - lldebugs << "Status: " << status << llendl; - lldebugs << "Reason: " << reason << llendl; - lldebugs << "Headers: " << content << llendl; + LL_DEBUGS("ServerReleaseNotes") << dumpResponse() + << " [headers:" << getResponseHeaders() << "]" << LL_ENDL; LLFloaterAbout* floater_about = LLFloaterReg::getTypedInstance<LLFloaterAbout>("sl_about"); if (floater_about) { - std::string location = content["location"].asString(); + const bool check_lower = true; + const std::string& location = getResponseHeader(HTTP_HEADER_LOCATION, check_lower); if (location.empty()) { - location = floater_about->getString("ErrorFetchingServerReleaseNotesURL"); + LL_WARNS("ServerReleaseNotes") << "Missing Location header " + << dumpResponse() << " [headers:" << getResponseHeaders() << "]" << LL_ENDL; + floater_about->updateServerReleaseNotesURL( + floater_about->getString("ErrorFetchingServerReleaseNotesURL")); + } + else + { + floater_about->updateServerReleaseNotesURL(location); } - floater_about->updateServerReleaseNotesURL(location); } } -// virtual -void LLServerReleaseNotesURLFetcher::completedRaw( - U32 status, - const std::string& reason, - const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer) -{ - // Do nothing. - // We're overriding just because the base implementation tries to - // deserialize LLSD which triggers warnings. -} diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index 752aba5e16..eaf4d062fe 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -380,12 +380,14 @@ BOOL LLFloaterAvatarPicker::visibleItemsSelected() const class LLAvatarPickerResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLAvatarPickerResponder); public: LLUUID mQueryID; LLAvatarPickerResponder(const LLUUID& id) : mQueryID(id) { } - /*virtual*/ void completed(U32 status, const std::string& reason, const LLSD& content) +protected: + /*virtual*/ void httpCompleted() { //std::ostringstream ss; //LLSDSerialize::toPrettyXML(content, ss); @@ -393,19 +395,18 @@ public: // in case of invalid characters, the avatar picker returns a 400 // just set it to process so it displays 'not found' - if (isGoodStatus(status) || status == 400) + if (isGoodStatus() || getStatus() == HTTP_BAD_REQUEST) { LLFloaterAvatarPicker* floater = LLFloaterReg::findTypedInstance<LLFloaterAvatarPicker>("avatar_picker"); if (floater) { - floater->processResponse(mQueryID, content); + floater->processResponse(mQueryID, getContent()); } } else { - llwarns << "avatar picker failed [status:" << status << "]: " << content << llendl; - + llwarns << "avatar picker failed " << dumpResponse() << llendl; } } }; diff --git a/indra/newview/llfloaterbuycurrencyhtml.cpp b/indra/newview/llfloaterbuycurrencyhtml.cpp index 013cf74c7b..6e641e7d40 100644 --- a/indra/newview/llfloaterbuycurrencyhtml.cpp +++ b/indra/newview/llfloaterbuycurrencyhtml.cpp @@ -27,6 +27,7 @@ #include "llviewerprecompiledheaders.h" #include "llfloaterbuycurrencyhtml.h" +#include "llhttpconstants.h" #include "llstatusbar.h" //////////////////////////////////////////////////////////////////////////////// @@ -85,7 +86,7 @@ void LLFloaterBuyCurrencyHTML::navigateToFinalURL() llinfos << "Buy currency HTML parsed URL is " << buy_currency_url << llendl; // kick off the navigation - mBrowser->navigateTo( buy_currency_url, "text/html" ); + mBrowser->navigateTo( buy_currency_url, HTTP_CONTENT_TEXT_HTML ); } //////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llfloaterhelpbrowser.cpp b/indra/newview/llfloaterhelpbrowser.cpp index 4cb632bd6a..c0bb213540 100644 --- a/indra/newview/llfloaterhelpbrowser.cpp +++ b/indra/newview/llfloaterhelpbrowser.cpp @@ -29,6 +29,7 @@ #include "llfloaterhelpbrowser.h" #include "llfloaterreg.h" +#include "llhttpconstants.h" #include "llpluginclassmedia.h" #include "llmediactrl.h" #include "llviewerwindow.h" @@ -37,7 +38,6 @@ #include "llui.h" #include "llurlhistory.h" -#include "llmediactrl.h" #include "llviewermedia.h" #include "llviewerhelp.h" @@ -148,7 +148,7 @@ void LLFloaterHelpBrowser::openMedia(const std::string& media_url) { // explicitly make the media mime type for this floater since it will // only ever display one type of content (Web). - mBrowser->setHomePageUrl(media_url, "text/html"); - mBrowser->navigateTo(media_url, "text/html"); + mBrowser->setHomePageUrl(media_url, HTTP_CONTENT_TEXT_HTML); + mBrowser->navigateTo(media_url, HTTP_CONTENT_TEXT_HTML); setCurrentURL(media_url); } diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index c9f5b42b20..c365666f00 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -5839,7 +5839,7 @@ void LLFloaterModelPreview::handleModelPhysicsFeeReceived() mUploadBtn->setEnabled(mHasUploadPerm && !mUploadModelUrl.empty()); } -void LLFloaterModelPreview::setModelPhysicsFeeErrorStatus(U32 status, const std::string& reason) +void LLFloaterModelPreview::setModelPhysicsFeeErrorStatus(S32 status, const std::string& reason) { llwarns << "LLFloaterModelPreview::setModelPhysicsFeeErrorStatus(" << status << " : " << reason << ")" << llendl; doOnIdleOneTime(boost::bind(&LLFloaterModelPreview::toggleCalculateButton, this, true)); @@ -5915,7 +5915,7 @@ void LLFloaterModelPreview::onPermissionsReceived(const LLSD& result) getChild<LLTextBox>("warning_message")->setVisible(!mHasUploadPerm); } -void LLFloaterModelPreview::setPermissonsErrorStatus(U32 status, const std::string& reason) +void LLFloaterModelPreview::setPermissonsErrorStatus(S32 status, const std::string& reason) { llwarns << "LLFloaterModelPreview::setPermissonsErrorStatus(" << status << " : " << reason << ")" << llendl; diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h index e588418f7b..6c0c60b87f 100644 --- a/indra/newview/llfloatermodelpreview.h +++ b/indra/newview/llfloatermodelpreview.h @@ -200,11 +200,11 @@ public: /*virtual*/ void onPermissionsReceived(const LLSD& result); // called when error occurs during permissions request - /*virtual*/ void setPermissonsErrorStatus(U32 status, const std::string& reason); + /*virtual*/ void setPermissonsErrorStatus(S32 status, const std::string& reason); /*virtual*/ void onModelPhysicsFeeReceived(const LLSD& result, std::string upload_url); void handleModelPhysicsFeeReceived(); - /*virtual*/ void setModelPhysicsFeeErrorStatus(U32 status, const std::string& reason); + /*virtual*/ void setModelPhysicsFeeErrorStatus(S32 status, const std::string& reason); /*virtual*/ void onModelUploadSuccess(); diff --git a/indra/newview/llfloatermodeluploadbase.cpp b/indra/newview/llfloatermodeluploadbase.cpp index 6d3800bfa4..9f1fc06e14 100644 --- a/indra/newview/llfloatermodeluploadbase.cpp +++ b/indra/newview/llfloatermodeluploadbase.cpp @@ -45,7 +45,7 @@ void LLFloaterModelUploadBase::requestAgentUploadPermissions() if (!url.empty()) { llinfos<< typeid(*this).name() <<"::requestAgentUploadPermissions() requesting for upload model permissions from: "<< url <<llendl; - LLHTTPClient::get(url, new LLUploadModelPremissionsResponder(getPermObserverHandle())); + LLHTTPClient::get(url, new LLUploadModelPermissionsResponder(getPermObserverHandle())); } else { diff --git a/indra/newview/llfloatermodeluploadbase.h b/indra/newview/llfloatermodeluploadbase.h index a52bc28687..d9a8879687 100644 --- a/indra/newview/llfloatermodeluploadbase.h +++ b/indra/newview/llfloatermodeluploadbase.h @@ -37,13 +37,13 @@ public: virtual ~LLFloaterModelUploadBase(){}; - virtual void setPermissonsErrorStatus(U32 status, const std::string& reason) = 0; + virtual void setPermissonsErrorStatus(S32 status, const std::string& reason) = 0; virtual void onPermissionsReceived(const LLSD& result) = 0; virtual void onModelPhysicsFeeReceived(const LLSD& result, std::string upload_url) = 0; - virtual void setModelPhysicsFeeErrorStatus(U32 status, const std::string& reason) = 0; + virtual void setModelPhysicsFeeErrorStatus(S32 status, const std::string& reason) = 0; virtual void onModelUploadSuccess() {}; diff --git a/indra/newview/llfloaterobjectweights.cpp b/indra/newview/llfloaterobjectweights.cpp index 0862cd2897..c11a0568a6 100644 --- a/indra/newview/llfloaterobjectweights.cpp +++ b/indra/newview/llfloaterobjectweights.cpp @@ -123,7 +123,7 @@ void LLFloaterObjectWeights::onWeightsUpdate(const SelectionCost& selection_cost } //virtual -void LLFloaterObjectWeights::setErrorStatus(U32 status, const std::string& reason) +void LLFloaterObjectWeights::setErrorStatus(S32 status, const std::string& reason) { const std::string text = getString("nothing_selected"); diff --git a/indra/newview/llfloaterobjectweights.h b/indra/newview/llfloaterobjectweights.h index 9a244573be..1a2c317bad 100644 --- a/indra/newview/llfloaterobjectweights.h +++ b/indra/newview/llfloaterobjectweights.h @@ -63,7 +63,7 @@ public: /*virtual*/ void onOpen(const LLSD& key); /*virtual*/ void onWeightsUpdate(const SelectionCost& selection_cost); - /*virtual*/ void setErrorStatus(U32 status, const std::string& reason); + /*virtual*/ void setErrorStatus(S32 status, const std::string& reason); void updateLandImpacts(const LLParcel* parcel); void refresh(); diff --git a/indra/newview/llfloaterregiondebugconsole.cpp b/indra/newview/llfloaterregiondebugconsole.cpp index 0cde878055..efc04ac358 100644 --- a/indra/newview/llfloaterregiondebugconsole.cpp +++ b/indra/newview/llfloaterregiondebugconsole.cpp @@ -73,24 +73,29 @@ namespace // called if this request times out. class AsyncConsoleResponder : public LLHTTPClient::Responder { - public: + LOG_CLASS(AsyncConsoleResponder); + protected: /* virtual */ - void errorWithContent(U32 status, const std::string& reason) + void httpFailure() { + LL_WARNS("Console") << dumpResponse() << LL_ENDL; sConsoleReplySignal(UNABLE_TO_SEND_COMMAND); } }; class ConsoleResponder : public LLHTTPClient::Responder { + LOG_CLASS(ConsoleResponder); public: ConsoleResponder(LLTextEditor *output) : mOutput(output) { } + protected: /*virtual*/ - void error(U32 status, const std::string& reason) + void httpFailure() { + LL_WARNS("Console") << dumpResponse() << LL_ENDL; if (mOutput) { mOutput->appendText( @@ -100,8 +105,10 @@ namespace } /*virtual*/ - void result(const LLSD& content) + void httpSuccess() { + const LLSD& content = getContent(); + LL_DEBUGS("Console") << content << LL_ENDL; if (mOutput) { mOutput->appendText( @@ -109,6 +116,7 @@ namespace } } + public: LLTextEditor * mOutput; }; diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 4a9ea5acf0..6c0e91dd2c 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -754,12 +754,12 @@ bool LLPanelRegionGeneralInfo::onMessageCommit(const LLSD& notification, const L class ConsoleRequestResponder : public LLHTTPClient::Responder { -public: + LOG_CLASS(ConsoleRequestResponder); +protected: /*virtual*/ - void errorWithContent(U32 status, const std::string& reason, const LLSD& content) + void httpFailure() { - llwarns << "ConsoleRequestResponder error requesting mesh_rez_enabled [status:" - << status << "]: " << content << llendl; + llwarns << "error requesting mesh_rez_enabled " << dumpResponse() << llendl; } }; @@ -767,12 +767,12 @@ public: // called if this request times out. class ConsoleUpdateResponder : public LLHTTPClient::Responder { -public: + LOG_CLASS(ConsoleUpdateResponder); +protected: /* virtual */ - void errorWithContent(U32 status, const std::string& reason, const LLSD& content) + void httpFailure() { - llwarns << "ConsoleRequestResponder error updating mesh enabled region setting [status:" - << status << "]: " << content << llendl; + llwarns << "error updating mesh enabled region setting " << dumpResponse() << llendl; } }; @@ -2191,14 +2191,16 @@ void LLPanelEstateInfo::getEstateOwner() class LLEstateChangeInfoResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLEstateChangeInfoResponder); public: LLEstateChangeInfoResponder(LLPanelEstateInfo* panel) { mpPanel = panel->getHandle(); } +protected: // if we get a normal response, handle it here - virtual void result(const LLSD& content) + virtual void httpSuccess() { LL_INFOS("Windlight") << "Successfully committed estate info" << llendl; @@ -2209,10 +2211,9 @@ public: } // if we get an error response - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content) + virtual void httpFailure() { - llinfos << "LLEstateChangeInfoResponder::error [status:" - << status << "]: " << content << llendl; + LL_WARNS("Windlight") << dumpResponse() << LL_ENDL; } private: LLHandle<LLPanel> mpPanel; diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 685b566fa8..f7fca90ebd 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -692,16 +692,18 @@ public: class LLUserReportResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLUserReportResponder); public: LLUserReportResponder(): LLHTTPClient::Responder() {} - void errorWithContent(U32 status, const std::string& reason, const LLSD& content) - { - // *TODO do some user messaging here - LLUploadDialog::modalUploadFinished(); - } - void result(const LLSD& content) +private: + void httpCompleted() { + if (!isGoodStatus()) + { + // *TODO do some user messaging here + LL_WARNS("UserReport") << dumpResponse() << LL_ENDL; + } // we don't care about what the server returns LLUploadDialog::modalUploadFinished(); } diff --git a/indra/newview/llfloaterscriptlimits.cpp b/indra/newview/llfloaterscriptlimits.cpp index 17c34f1da0..7e94784751 100644 --- a/indra/newview/llfloaterscriptlimits.cpp +++ b/indra/newview/llfloaterscriptlimits.cpp @@ -183,8 +183,14 @@ void LLPanelScriptLimitsInfo::updateChild(LLUICtrl* child_ctr) // Responders ///---------------------------------------------------------------------------- -void fetchScriptLimitsRegionInfoResponder::result(const LLSD& content) +void fetchScriptLimitsRegionInfoResponder::httpSuccess() { + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } //we don't need to test with a fake respose here (shouldn't anyway) #ifdef DUMP_REPLIES_TO_LLINFOS @@ -221,13 +227,14 @@ void fetchScriptLimitsRegionInfoResponder::result(const LLSD& content) } } -void fetchScriptLimitsRegionInfoResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) +void fetchScriptLimitsRegionInfoResponder::httpFailure() { - llwarns << "fetchScriptLimitsRegionInfoResponder error [status:" << status << "]: " << content << llendl; + llwarns << dumpResponse() << llendl; } -void fetchScriptLimitsRegionSummaryResponder::result(const LLSD& content_ref) +void fetchScriptLimitsRegionSummaryResponder::httpSuccess() { + const LLSD& content_ref = getContent(); #ifdef USE_FAKE_RESPONSES LLSD fake_content; @@ -268,6 +275,12 @@ void fetchScriptLimitsRegionSummaryResponder::result(const LLSD& content_ref) #endif + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } + #ifdef DUMP_REPLIES_TO_LLINFOS @@ -291,7 +304,7 @@ void fetchScriptLimitsRegionSummaryResponder::result(const LLSD& content_ref) LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels"); if(tab) { - LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel"); + LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel"); if(panel_memory) { panel_memory->getChild<LLUICtrl>("loading_text")->setValue(LLSD(std::string(""))); @@ -301,20 +314,21 @@ void fetchScriptLimitsRegionSummaryResponder::result(const LLSD& content_ref) { btn->setEnabled(true); } - - panel_memory->setRegionSummary(content); - } -} + + panel_memory->setRegionSummary(content); + } + } } } -void fetchScriptLimitsRegionSummaryResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) +void fetchScriptLimitsRegionSummaryResponder::httpFailure() { - llwarns << "fetchScriptLimitsRegionSummaryResponder error [status:" << status << "]: " << content << llendl; + llwarns << dumpResponse() << llendl; } -void fetchScriptLimitsRegionDetailsResponder::result(const LLSD& content_ref) +void fetchScriptLimitsRegionDetailsResponder::httpSuccess() { + const LLSD& content_ref = getContent(); #ifdef USE_FAKE_RESPONSES /* Updated detail service, ** denotes field added: @@ -377,6 +391,12 @@ result (map) #endif + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } + #ifdef DUMP_REPLIES_TO_LLINFOS LLSDNotationStreamer notation_streamer(content); @@ -417,13 +437,14 @@ result (map) } } -void fetchScriptLimitsRegionDetailsResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) +void fetchScriptLimitsRegionDetailsResponder::httpFailure() { - llwarns << "fetchScriptLimitsRegionDetailsResponder error [status:" << status << "]: " << content << llendl; + llwarns << dumpResponse() << llendl; } -void fetchScriptLimitsAttachmentInfoResponder::result(const LLSD& content_ref) +void fetchScriptLimitsAttachmentInfoResponder::httpSuccess() { + const LLSD& content_ref = getContent(); #ifdef USE_FAKE_RESPONSES @@ -465,6 +486,12 @@ void fetchScriptLimitsAttachmentInfoResponder::result(const LLSD& content_ref) #endif + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } + #ifdef DUMP_REPLIES_TO_LLINFOS LLSDNotationStreamer notation_streamer(content); @@ -513,9 +540,9 @@ void fetchScriptLimitsAttachmentInfoResponder::result(const LLSD& content_ref) } } -void fetchScriptLimitsAttachmentInfoResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) +void fetchScriptLimitsAttachmentInfoResponder::httpFailure() { - llwarns << "fetchScriptLimitsAttachmentInfoResponder error [status:" << status << "]: " << content << llendl; + llwarns << dumpResponse() << llendl; } ///---------------------------------------------------------------------------- @@ -586,7 +613,7 @@ void LLPanelScriptLimitsRegionMemory::setParcelID(const LLUUID& parcel_id) } // virtual -void LLPanelScriptLimitsRegionMemory::setErrorStatus(U32 status, const std::string& reason) +void LLPanelScriptLimitsRegionMemory::setErrorStatus(S32 status, const std::string& reason) { llwarns << "Can't handle remote parcel request."<< " Http Status: "<< status << ". Reason : "<< reason<<llendl; } diff --git a/indra/newview/llfloaterscriptlimits.h b/indra/newview/llfloaterscriptlimits.h index f8732ef94b..a5cb1b6184 100644 --- a/indra/newview/llfloaterscriptlimits.h +++ b/indra/newview/llfloaterscriptlimits.h @@ -85,49 +85,49 @@ protected: class fetchScriptLimitsRegionInfoResponder: public LLHTTPClient::Responder { - public: - fetchScriptLimitsRegionInfoResponder(const LLSD& info) : mInfo(info) {}; - - void result(const LLSD& content); - void errorWithContent(U32 status, const std::string& reason, const LLSD& content); - public: - protected: - LLSD mInfo; + LOG_CLASS(fetchScriptLimitsRegionInfoResponder); +public: + fetchScriptLimitsRegionInfoResponder(const LLSD& info) : mInfo(info) {}; + +private: + /* virtual */ void httpSuccess(); + /* virtual */ void httpFailure(); + LLSD mInfo; }; class fetchScriptLimitsRegionSummaryResponder: public LLHTTPClient::Responder { - public: - fetchScriptLimitsRegionSummaryResponder(const LLSD& info) : mInfo(info) {}; - - void result(const LLSD& content); - void errorWithContent(U32 status, const std::string& reason, const LLSD& content); - public: - protected: - LLSD mInfo; + LOG_CLASS(fetchScriptLimitsRegionSummaryResponder); +public: + fetchScriptLimitsRegionSummaryResponder(const LLSD& info) : mInfo(info) {}; + +private: + /* virtual */ void httpSuccess(); + /* virtual */ void httpFailure(); + LLSD mInfo; }; class fetchScriptLimitsRegionDetailsResponder: public LLHTTPClient::Responder { - public: - fetchScriptLimitsRegionDetailsResponder(const LLSD& info) : mInfo(info) {}; - - void result(const LLSD& content); - void errorWithContent(U32 status, const std::string& reason, const LLSD& content); - public: - protected: - LLSD mInfo; + LOG_CLASS(fetchScriptLimitsRegionDetailsResponder); +public: + fetchScriptLimitsRegionDetailsResponder(const LLSD& info) : mInfo(info) {}; + +private: + /* virtual */ void httpSuccess(); + /* virtual */ void httpFailure(); + LLSD mInfo; }; class fetchScriptLimitsAttachmentInfoResponder: public LLHTTPClient::Responder { - public: - fetchScriptLimitsAttachmentInfoResponder() {}; + LOG_CLASS(fetchScriptLimitsAttachmentInfoResponder); +public: + fetchScriptLimitsAttachmentInfoResponder() {}; - void result(const LLSD& content); - void errorWithContent(U32 status, const std::string& reason, const LLSD& content); - public: - protected: +private: + /* virtual */ void httpSuccess(); + /* virtual */ void httpFailure(); }; ///////////////////////////////////////////////////////////////////////////// @@ -190,7 +190,7 @@ protected: // LLRemoteParcelInfoObserver interface: /*virtual*/ void processParcelInfo(const LLParcelData& parcel_data); /*virtual*/ void setParcelID(const LLUUID& parcel_id); -/*virtual*/ void setErrorStatus(U32 status, const std::string& reason); +/*virtual*/ void setErrorStatus(S32 status, const std::string& reason); static void onClickRefresh(void* userdata); static void onClickHighlight(void* userdata); diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp index 2a946b1edf..a446b767ac 100644 --- a/indra/newview/llfloatersearch.cpp +++ b/indra/newview/llfloatersearch.cpp @@ -30,6 +30,7 @@ #include "llcommandhandler.h" #include "llfloaterreg.h" #include "llfloatersearch.h" +#include "llhttpconstants.h" #include "llmediactrl.h" #include "llnotificationsutil.h" #include "lllogininstance.h" @@ -200,5 +201,5 @@ void LLFloaterSearch::search(const SearchQuery &p) url = LLWeb::expandURLSubstitutions(url, subs); // and load the URL in the web view - mWebBrowser->navigateTo(url, "text/html"); + mWebBrowser->navigateTo(url, HTTP_CONTENT_TEXT_HTML); } diff --git a/indra/newview/llfloatertos.cpp b/indra/newview/llfloatertos.cpp index a242b224cd..0613ffc94d 100644 --- a/indra/newview/llfloatertos.cpp +++ b/indra/newview/llfloatertos.cpp @@ -36,7 +36,7 @@ #include "llbutton.h" #include "llevents.h" #include "llhttpclient.h" -#include "llhttpstatuscodes.h" // for HTTP_FOUND +#include "llhttpconstants.h" #include "llnotificationsutil.h" #include "llradiogroup.h" #include "lltextbox.h" @@ -62,42 +62,46 @@ LLFloaterTOS::LLFloaterTOS(const LLSD& data) // on parent class indicating if the web server is working or not class LLIamHere : public LLHTTPClient::Responder { - private: - LLIamHere( LLFloaterTOS* parent ) : - mParent( parent ) - {} + LOG_CLASS(LLIamHere); +private: + LLIamHere( LLFloaterTOS* parent ) : + mParent( parent ) + {} - LLFloaterTOS* mParent; + LLFloaterTOS* mParent; - public: - - static LLIamHere* build( LLFloaterTOS* parent ) - { - return new LLIamHere( parent ); - }; - - virtual void setParent( LLFloaterTOS* parentIn ) - { - mParent = parentIn; - }; - - virtual void result( const LLSD& content ) +public: + static LLIamHere* build( LLFloaterTOS* parent ) + { + return new LLIamHere( parent ); + } + + virtual void setParent( LLFloaterTOS* parentIn ) + { + mParent = parentIn; + } + +protected: + virtual void httpSuccess() + { + if ( mParent ) { - if ( mParent ) - mParent->setSiteIsAlive( true ); - }; + mParent->setSiteIsAlive( true ); + } + } - virtual void error( U32 status, const std::string& reason ) + virtual void httpFailure() + { + LL_DEBUGS("LLIamHere") << dumpResponse() << LL_ENDL; + if ( mParent ) { - if ( mParent ) - { - // *HACK: For purposes of this alive check, 302 Found - // (aka Moved Temporarily) is considered alive. The web site - // redirects this link to a "cache busting" temporary URL. JC - bool alive = (status == HTTP_FOUND); - mParent->setSiteIsAlive( alive ); - } - }; + // *HACK: For purposes of this alive check, 302 Found + // (aka Moved Temporarily) is considered alive. The web site + // redirects this link to a "cache busting" temporary URL. JC + bool alive = (getStatus() == HTTP_FOUND); + mParent->setSiteIsAlive( alive ); + } + } }; // this is global and not a class member to keep crud out of the header file diff --git a/indra/newview/llfloaterurlentry.cpp b/indra/newview/llfloaterurlentry.cpp index e85d849c9a..0751c830d5 100644 --- a/indra/newview/llfloaterurlentry.cpp +++ b/indra/newview/llfloaterurlentry.cpp @@ -48,31 +48,31 @@ static LLFloaterURLEntry* sInstance = NULL; // on the Panel Land Media and to discover the MIME type class LLMediaTypeResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLMediaTypeResponder); public: LLMediaTypeResponder( const LLHandle<LLFloater> parent ) : - mParent( parent ) - {} - - LLHandle<LLFloater> mParent; - - - virtual void completedHeader(U32 status, const std::string& reason, const LLSD& content) - { - std::string media_type = content["content-type"].asString(); - std::string::size_type idx1 = media_type.find_first_of(";"); - std::string mime_type = media_type.substr(0, idx1); - completeAny(status, mime_type); - } - - void completeAny(U32 status, const std::string& mime_type) - { - // Set empty type to none/none. Empty string is reserved for legacy parcels - // which have no mime type set. - std::string resolved_mime_type = ! mime_type.empty() ? mime_type : LLMIMETypes::getDefaultMimeType(); - LLFloaterURLEntry* floater_url_entry = (LLFloaterURLEntry*)mParent.get(); - if ( floater_url_entry ) - floater_url_entry->headerFetchComplete( status, resolved_mime_type ); - } + mParent( parent ) + {} + + LLHandle<LLFloater> mParent; + +private: + /* virtual */ void httpCompleted() + { + const bool check_lower = true; + const std::string& media_type = getResponseHeader(HTTP_HEADER_CONTENT_TYPE, check_lower); + std::string::size_type idx1 = media_type.find_first_of(";"); + std::string mime_type = media_type.substr(0, idx1); + + // Set empty type to none/none. Empty string is reserved for legacy parcels + // which have no mime type set. + std::string resolved_mime_type = ! mime_type.empty() ? mime_type : LLMIMETypes::getDefaultMimeType(); + LLFloaterURLEntry* floater_url_entry = (LLFloaterURLEntry*)mParent.get(); + if ( floater_url_entry ) + { + floater_url_entry->headerFetchComplete( getStatus(), resolved_mime_type ); + } + } }; //----------------------------------------------------------------------------- @@ -136,7 +136,7 @@ void LLFloaterURLEntry::buildURLHistory() } } -void LLFloaterURLEntry::headerFetchComplete(U32 status, const std::string& mime_type) +void LLFloaterURLEntry::headerFetchComplete(S32 status, const std::string& mime_type) { LLPanelLandMedia* panel_media = dynamic_cast<LLPanelLandMedia*>(mPanelLandMediaHandle.get()); if (panel_media) diff --git a/indra/newview/llfloaterurlentry.h b/indra/newview/llfloaterurlentry.h index dfb49fe5ac..bdd1ebe592 100644 --- a/indra/newview/llfloaterurlentry.h +++ b/indra/newview/llfloaterurlentry.h @@ -40,7 +40,7 @@ public: // that panel via the handle. static LLHandle<LLFloater> show(LLHandle<LLPanel> panel_land_media_handle, const std::string media_url); /*virtual*/ BOOL postBuild(); - void headerFetchComplete(U32 status, const std::string& mime_type); + void headerFetchComplete(S32 status, const std::string& mime_type); bool addURLToCombobox(const std::string& media_url); diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp index 3fe2518de6..21b171446f 100644 --- a/indra/newview/llfloaterwebcontent.cpp +++ b/indra/newview/llfloaterwebcontent.cpp @@ -29,6 +29,7 @@ #include "llcombobox.h" #include "lliconctrl.h" #include "llfloaterreg.h" +#include "llhttpconstants.h" #include "lllayoutstack.h" #include "llpluginclassmedia.h" #include "llprogressbar.h" @@ -234,9 +235,9 @@ void LLFloaterWebContent::open_media(const Params& p) { // Specifying a mime type of text/html here causes the plugin system to skip the MIME type probe and just open a browser plugin. LLViewerMedia::proxyWindowOpened(p.target(), p.id()); - mWebBrowser->setHomePageUrl(p.url, "text/html"); + mWebBrowser->setHomePageUrl(p.url, HTTP_CONTENT_TEXT_HTML); mWebBrowser->setTarget(p.target); - mWebBrowser->navigateTo(p.url, "text/html"); + mWebBrowser->navigateTo(p.url, HTTP_CONTENT_TEXT_HTML); set_current_url(p.url); @@ -451,7 +452,7 @@ void LLFloaterWebContent::onEnterAddress() std::string url = mAddressCombo->getValue().asString(); if ( url.length() > 0 ) { - mWebBrowser->navigateTo( url, "text/html"); + mWebBrowser->navigateTo(url, HTTP_CONTENT_TEXT_HTML); }; } diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp index cbd844cdac..472e3862ea 100644 --- a/indra/newview/llgroupmgr.cpp +++ b/indra/newview/llgroupmgr.cpp @@ -1843,23 +1843,31 @@ void LLGroupMgr::sendGroupMemberEjects(const LLUUID& group_id, // Responder class for capability group management class GroupMemberDataResponder : public LLHTTPClient::Responder { + LOG_CLASS(GroupMemberDataResponder); public: - GroupMemberDataResponder() {} - virtual ~GroupMemberDataResponder() {} - virtual void result(const LLSD& pContent); - virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent); + GroupMemberDataResponder() {} + virtual ~GroupMemberDataResponder() {} + private: - LLSD mMemberData; + /* virtual */ void httpSuccess(); + /* virtual */ void httpFailure(); + LLSD mMemberData; }; -void GroupMemberDataResponder::errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent) +void GroupMemberDataResponder::httpFailure() { - LL_WARNS("GrpMgr") << "Error receiving group member data [status:" - << pStatus << "]: " << pContent << LL_ENDL; + LL_WARNS("GrpMgr") << "Error receiving group member data " + << dumpResponse() << LL_ENDL; } -void GroupMemberDataResponder::result(const LLSD& content) +void GroupMemberDataResponder::httpSuccess() { + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } LLGroupMgr::processCapGroupMembersRequest(content); } diff --git a/indra/newview/llhomelocationresponder.cpp b/indra/newview/llhomelocationresponder.cpp index 37428c4a44..b1286cccf2 100644 --- a/indra/newview/llhomelocationresponder.cpp +++ b/indra/newview/llhomelocationresponder.cpp @@ -33,71 +33,76 @@ #include "llagent.h" #include "llviewerregion.h" -void LLHomeLocationResponder::result( const LLSD& content ) +void LLHomeLocationResponder::httpSuccess() { + const LLSD& content = getContent(); LLVector3 agent_pos; bool error = true; - + do { - + // was the call to /agent/<agent-id>/home-location successful? // If not, we keep error set to true if( ! content.has("success") ) { break; } - + if( 0 != strncmp("true", content["success"].asString().c_str(), 4 ) ) { break; } - + // did the simulator return a "justified" home location? // If no, we keep error set to true if( ! content.has( "HomeLocation" ) ) { break; } - + if( ! content["HomeLocation"].has("LocationPos") ) { break; } - + if( ! content["HomeLocation"]["LocationPos"].has("X") ) { break; } agent_pos.mV[VX] = content["HomeLocation"]["LocationPos"]["X"].asInteger(); - + if( ! content["HomeLocation"]["LocationPos"].has("Y") ) { break; } agent_pos.mV[VY] = content["HomeLocation"]["LocationPos"]["Y"].asInteger(); - + if( ! content["HomeLocation"]["LocationPos"].has("Z") ) { break; } agent_pos.mV[VZ] = content["HomeLocation"]["LocationPos"]["Z"].asInteger(); - + error = false; } while( 0 ); - - if( ! error ) + + if( error ) + { + failureResult(HTTP_INTERNAL_ERROR, "Invalid server response content", content); + } + else { llinfos << "setting home position" << llendl; - + LLViewerRegion *viewer_region = gAgent.getRegion(); gAgent.setHomePosRegion( viewer_region->getHandle(), agent_pos ); } } -void LLHomeLocationResponder::errorWithContent( U32 status, const std::string& reason, const LLSD& content ) +void LLHomeLocationResponder::httpFailure() { - llwarns << "LLHomeLocationResponder error [status:" << status << "]: " << content << llendl; + llwarns << dumpResponse() << llendl; } diff --git a/indra/newview/llhomelocationresponder.h b/indra/newview/llhomelocationresponder.h index 9bf4b12c4e..adc6c8cb58 100644 --- a/indra/newview/llhomelocationresponder.h +++ b/indra/newview/llhomelocationresponder.h @@ -35,8 +35,10 @@ /* Typedef, Enum, Class, Struct, etc. */ class LLHomeLocationResponder : public LLHTTPClient::Responder { - virtual void result( const LLSD& content ); - virtual void errorWithContent( U32 status, const std::string& reason, const LLSD& content ); + LOG_CLASS(LLHomeLocationResponder); +private: + /* virtual */ void httpSuccess(); + /* virtual */ void httpFailure(); }; #endif diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index fff178f8fe..c933d5428d 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -979,16 +979,17 @@ BOOL LLIMFloater::isInviteAllowed() const class LLSessionInviteResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLSessionInviteResponder); public: LLSessionInviteResponder(const LLUUID& session_id) { mSessionID = session_id; } - void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) +protected: + void httpFailure() { - llwarns << "Error inviting all agents to session [status:" - << statusNum << "]: " << content << llendl; + llwarns << "Error inviting all agents to session " << dumpResponse() << llendl; //throw something back to the viewer here? } diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index 1dab0e67bf..95ede326e6 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -388,16 +388,17 @@ void LLFloaterIMPanel::draw() class LLSessionInviteResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLSessionInviteResponder); public: LLSessionInviteResponder(const LLUUID& session_id) { mSessionID = session_id; } - void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) +protected: + void httpFailure() { - llwarns << "Error inviting all agents to session [status:" - << statusNum << "]: " << content << llendl; + llwarns << "Error inviting all agents to session " << dumpResponse() << llendl; //throw something back to the viewer here? } diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 20b33c5d08..a00de8eb26 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -1214,6 +1214,7 @@ void start_deprecated_conference_chat( class LLStartConferenceChatResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLStartConferenceChatResponder); public: LLStartConferenceChatResponder( const LLUUID& temp_session_id, @@ -1227,10 +1228,12 @@ public: mAgents = agents_to_invite; } - virtual void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) +protected: + virtual void httpFailure() { //try an "old school" way. - if ( statusNum == 400 ) + // *TODO: What about other error status codes? 4xx 5xx? + if ( getStatus() == HTTP_BAD_REQUEST ) { start_deprecated_conference_chat( mTempSessionID, @@ -1239,8 +1242,7 @@ public: mAgents); } - llwarns << "LLStartConferenceChatResponder error [status:" - << statusNum << "]: " << content << llendl; + llwarns << dumpResponse() << llendl; //else throw an error back to the client? //in theory we should have just have these error strings @@ -1332,6 +1334,7 @@ bool LLIMModel::sendStartSession( class LLViewerChatterBoxInvitationAcceptResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLViewerChatterBoxInvitationAcceptResponder); public: LLViewerChatterBoxInvitationAcceptResponder( const LLUUID& session_id, @@ -1341,8 +1344,15 @@ public: mInvitiationType = invitation_type; } - void result(const LLSD& content) +private: + void httpSuccess() { + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } if ( gIMMgr) { LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); @@ -1387,19 +1397,17 @@ public: } } - void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) + void httpFailure() { - llwarns << "LLViewerChatterBoxInvitationAcceptResponder error [status:" - << statusNum << "]: " << content << llendl; + llwarns << dumpResponse() << llendl; //throw something back to the viewer here? if ( gIMMgr ) { gIMMgr->clearPendingAgentListUpdates(mSessionID); gIMMgr->clearPendingInvitation(mSessionID); - if ( 404 == statusNum ) + if ( HTTP_NOT_FOUND == getStatus() ) { - std::string error_string; - error_string = "session_does_not_exist_error"; + static const std::string error_string("session_does_not_exist_error"); gIMMgr->showSessionStartError(error_string, mSessionID); } } diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp index aafc43b02d..1f719a22ef 100644 --- a/indra/newview/llinspectavatar.cpp +++ b/indra/newview/llinspectavatar.cpp @@ -495,21 +495,23 @@ void LLInspectAvatar::toggleSelectedVoice(bool enabled) class MuteVoiceResponder : public LLHTTPClient::Responder { + LOG_CLASS(MuteVoiceResponder); public: MuteVoiceResponder(const LLUUID& session_id) { mSessionID = session_id; } - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content) + protected: + virtual void httpFailure() { - llwarns << "MuteVoiceResponder error [status:" << status << "]: " << content << llendl; + llwarns << dumpResponse() << llendl; if ( gIMMgr ) { //403 == you're not a mod //should be disabled if you're not a moderator - if ( 403 == status ) + if ( HTTP_FORBIDDEN == getStatus() ) { gIMMgr->showSessionEventError( "mute", diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 99e72cdb22..0b2f80403d 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -414,6 +414,7 @@ const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType prefe class LLCreateInventoryCategoryResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLCreateInventoryCategoryResponder); public: LLCreateInventoryCategoryResponder(LLInventoryModel* model, void (*callback)(const LLSD&, void*), @@ -424,16 +425,21 @@ public: { } - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content) +protected: + virtual void httpFailure() { - LL_WARNS("InvAPI") << "CreateInventoryCategory failed [status:" - << status << "]: " << content << LL_ENDL; + LL_WARNS("InvAPI") << dumpResponse() << LL_ENDL; } - virtual void result(const LLSD& content) + virtual void httpSuccess() { //Server has created folder. - + const LLSD& content = getContent(); + if (!content.isMap() || !content.has("folder_id")) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } LLUUID category_id = content["folder_id"].asUUID(); @@ -1340,8 +1346,14 @@ void LLInventoryModel::addChangedMask(U32 mask, const LLUUID& referent) } // If we get back a normal response, handle it here -void LLInventoryModel::fetchInventoryResponder::result(const LLSD& content) -{ +void LLInventoryModel::fetchInventoryResponder::httpSuccess() +{ + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } start_new_inventory_observer(); /*LLUUID agent_id; @@ -1400,9 +1412,9 @@ void LLInventoryModel::fetchInventoryResponder::result(const LLSD& content) } //If we get back an error (not found, etc...), handle it here -void LLInventoryModel::fetchInventoryResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) +void LLInventoryModel::fetchInventoryResponder::httpFailure() { - llwarns << "fetchInventory error [status:" << status << "]: " << content << llendl; + llwarns << dumpResponse() << llendl; gInventory.notifyObservers(); } diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index dfdd237c95..9c2ca8cae9 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -81,11 +81,12 @@ public: class fetchInventoryResponder : public LLHTTPClient::Responder { + LOG_CLASS(fetchInventoryResponder); public: fetchInventoryResponder(const LLSD& request_sd) : mRequestSD(request_sd) {}; - void result(const LLSD& content); - void errorWithContent(U32 status, const std::string& reason, const LLSD& content); protected: + virtual void httpSuccess(); + virtual void httpFailure(); LLSD mRequestSD; }; diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index f2b39e7186..e1537033f9 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -363,35 +363,39 @@ void LLInventoryModelBackgroundFetch::incrFetchCount(S16 fetching) class LLInventoryModelFetchItemResponder : public LLInventoryModel::fetchInventoryResponder { + LOG_CLASS(LLInventoryModelFetchItemResponder); public: LLInventoryModelFetchItemResponder(const LLSD& request_sd) : LLInventoryModel::fetchInventoryResponder(request_sd) {}; - void result(const LLSD& content); - void errorWithContent(U32 status, const std::string& reason, const LLSD& content); +private: + /* virtual */ void httpSuccess(); + /* virtual */ void httpFailure(); }; -void LLInventoryModelFetchItemResponder::result( const LLSD& content ) +void LLInventoryModelFetchItemResponder::httpSuccess() { - LLInventoryModel::fetchInventoryResponder::result(content); + LLInventoryModel::fetchInventoryResponder::httpSuccess(); LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1); } -void LLInventoryModelFetchItemResponder::errorWithContent( U32 status, const std::string& reason, const LLSD& content ) +void LLInventoryModelFetchItemResponder::httpFailure() { - LLInventoryModel::fetchInventoryResponder::errorWithContent(status, reason, content); + LLInventoryModel::fetchInventoryResponder::httpFailure(); LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1); } class LLInventoryModelFetchDescendentsResponder: public LLHTTPClient::Responder { + LOG_CLASS(LLInventoryModelFetchDescendentsResponder); public: LLInventoryModelFetchDescendentsResponder(const LLSD& request_sd, uuid_vec_t recursive_cats) : mRequestSD(request_sd), mRecursiveCatUUIDs(recursive_cats) {}; //LLInventoryModelFetchDescendentsResponder() {}; - void result(const LLSD& content); - void errorWithContent(U32 status, const std::string& reason, const LLSD& content); +private: + /* virtual */ void httpSuccess(); + /* virtual */ void httpFailure(); protected: BOOL getIsRecursive(const LLUUID& cat_id) const; private: @@ -400,8 +404,14 @@ private: }; // If we get back a normal response, handle it here. -void LLInventoryModelFetchDescendentsResponder::result(const LLSD& content) +void LLInventoryModelFetchDescendentsResponder::httpSuccess() { + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } LLInventoryModelBackgroundFetch *fetcher = LLInventoryModelBackgroundFetch::getInstance(); if (content.has("folders")) { @@ -508,11 +518,12 @@ void LLInventoryModelFetchDescendentsResponder::result(const LLSD& content) for(LLSD::array_const_iterator folder_it = content["bad_folders"].beginArray(); folder_it != content["bad_folders"].endArray(); ++folder_it) - { + { + // *TODO: Stop copying data LLSD folder_sd = *folder_it; // These folders failed on the dataserver. We probably don't want to retry them. - llinfos << "Folder " << folder_sd["folder_id"].asString() + llwarns << "Folder " << folder_sd["folder_id"].asString() << "Error: " << folder_sd["error"].asString() << llendl; } } @@ -529,21 +540,19 @@ void LLInventoryModelFetchDescendentsResponder::result(const LLSD& content) } // If we get back an error (not found, etc...), handle it here. -void LLInventoryModelFetchDescendentsResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) +void LLInventoryModelFetchDescendentsResponder::httpFailure() { + llwarns << dumpResponse() << llendl; LLInventoryModelBackgroundFetch *fetcher = LLInventoryModelBackgroundFetch::getInstance(); - llinfos << "LLInventoryModelFetchDescendentsResponder::error [status:" - << status << "]: " << content << llendl; - fetcher->incrFetchCount(-1); - if (status==499) // timed out + if (getStatus()==HTTP_INTERNAL_ERROR) // timed out or curl failure { for(LLSD::array_const_iterator folder_it = mRequestSD["folders"].beginArray(); folder_it != mRequestSD["folders"].endArray(); ++folder_it) - { + { LLSD folder_sd = *folder_it; LLUUID folder_id = folder_sd["folder_id"]; const BOOL recursive = getIsRecursive(folder_id); diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp index 0b009b68f7..bea1d62b93 100644 --- a/indra/newview/llmarketplacefunctions.cpp +++ b/indra/newview/llmarketplacefunctions.cpp @@ -99,7 +99,7 @@ namespace LLMarketplaceImport bool hasSessionCookie(); bool inProgress(); bool resultPending(); - U32 getResultStatus(); + S32 getResultStatus(); const LLSD& getResults(); bool establishMarketplaceSessionCookie(); @@ -113,7 +113,7 @@ namespace LLMarketplaceImport static bool sImportInProgress = false; static bool sImportPostPending = false; static bool sImportGetPending = false; - static U32 sImportResultStatus = 0; + static S32 sImportResultStatus = 0; static LLSD sImportResults = LLSD::emptyMap(); static LLTimer slmGetTimer; @@ -123,22 +123,22 @@ namespace LLMarketplaceImport class LLImportPostResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLImportPostResponder); public: LLImportPostResponder() : LLCurl::Responder() {} - - void completed(U32 status, const std::string& reason, const LLSD& content) + + protected: + /* virtual */ void httpCompleted() { slmPostTimer.stop(); if (gSavedSettings.getBOOL("InventoryOutboxLogging")) { - llinfos << " SLM POST status: " << status << llendl; - llinfos << " SLM POST reason: " << reason << llendl; - llinfos << " SLM POST content: " << content.asString() << llendl; - - llinfos << " SLM POST timer: " << slmPostTimer.getElapsedTimeF32() << llendl; + llinfos << " SLM [timer:" << slmPostTimer.getElapsedTimeF32() << "] " + << dumpResponse() << llendl; } + S32 status = getStatus(); if ((status == MarketplaceErrorCodes::IMPORT_REDIRECT) || (status == MarketplaceErrorCodes::IMPORT_AUTHENTICATION_ERROR) || (status == MarketplaceErrorCodes::IMPORT_JOB_TIMEOUT)) @@ -154,38 +154,36 @@ namespace LLMarketplaceImport sImportInProgress = (status == MarketplaceErrorCodes::IMPORT_DONE); sImportPostPending = false; sImportResultStatus = status; - sImportId = content; + sImportId = getContent(); } }; class LLImportGetResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLImportGetResponder); public: LLImportGetResponder() : LLCurl::Responder() {} - void completedHeader(U32 status, const std::string& reason, const LLSD& content) + protected: + /* virtual */ void httpCompleted() { - const std::string& set_cookie_string = content["set-cookie"].asString(); + const bool check_lower = true; + const std::string& set_cookie_string = getResponseHeader(HTTP_HEADER_SET_COOKIE, check_lower); if (!set_cookie_string.empty()) { sMarketplaceCookie = set_cookie_string; } - } - - void completed(U32 status, const std::string& reason, const LLSD& content) - { + slmGetTimer.stop(); if (gSavedSettings.getBOOL("InventoryOutboxLogging")) { - llinfos << " SLM GET status: " << status << llendl; - llinfos << " SLM GET reason: " << reason << llendl; - llinfos << " SLM GET content: " << content.asString() << llendl; - - llinfos << " SLM GET timer: " << slmGetTimer.getElapsedTimeF32() << llendl; + llinfos << " SLM [timer:" << slmGetTimer.getElapsedTimeF32() << "] " + << dumpResponse() << llendl; } + S32 status = getStatus(); if ((status == MarketplaceErrorCodes::IMPORT_AUTHENTICATION_ERROR) || (status == MarketplaceErrorCodes::IMPORT_JOB_TIMEOUT)) { @@ -200,7 +198,7 @@ namespace LLMarketplaceImport sImportInProgress = (status == MarketplaceErrorCodes::IMPORT_PROCESSING); sImportGetPending = false; sImportResultStatus = status; - sImportResults = content; + sImportResults = getContent(); } }; @@ -221,7 +219,7 @@ namespace LLMarketplaceImport return (sImportPostPending || sImportGetPending); } - U32 getResultStatus() + S32 getResultStatus() { return sImportResultStatus; } @@ -280,10 +278,10 @@ namespace LLMarketplaceImport // Make the headers for the post LLSD headers = LLSD::emptyMap(); - headers["Accept"] = "*/*"; - headers["Cookie"] = sMarketplaceCookie; - headers["Content-Type"] = "application/llsd+xml"; - headers["User-Agent"] = LLViewerMedia::getCurrentUserAgent(); + headers[HTTP_HEADER_ACCEPT] = "*/*"; + headers[HTTP_HEADER_COOKIE] = sMarketplaceCookie; + headers[HTTP_HEADER_CONTENT_TYPE] = HTTP_CONTENT_LLSD_XML; + headers[HTTP_HEADER_USER_AGENT] = LLViewerMedia::getCurrentUserAgent(); if (gSavedSettings.getBOOL("InventoryOutboxLogging")) { @@ -313,11 +311,12 @@ namespace LLMarketplaceImport // Make the headers for the post LLSD headers = LLSD::emptyMap(); - headers["Accept"] = "*/*"; - headers["Connection"] = "Keep-Alive"; - headers["Cookie"] = sMarketplaceCookie; - headers["Content-Type"] = "application/xml"; - headers["User-Agent"] = LLViewerMedia::getCurrentUserAgent(); + headers[HTTP_HEADER_ACCEPT] = "*/*"; + headers[HTTP_HEADER_CONNECTION] = "Keep-Alive"; + headers[HTTP_HEADER_COOKIE] = sMarketplaceCookie; + // *TODO: Should this be 'application/llsd+xml'? + headers[HTTP_HEADER_CONTENT_TYPE] = HTTP_CONTENT_XML; + headers[HTTP_HEADER_USER_AGENT] = LLViewerMedia::getCurrentUserAgent(); if (gSavedSettings.getBOOL("InventoryOutboxLogging")) { diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 2075aeed63..cb5640b4da 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -52,6 +52,7 @@ #include "llsdutil.h" #include "lllayoutstack.h" #include "lliconctrl.h" +#include "llhttpconstants.h" #include "lltextbox.h" #include "llbutton.h" #include "llcheckboxctrl.h" @@ -576,7 +577,7 @@ void LLMediaCtrl::navigateToLocalPage( const std::string& subdir, const std::str { mCurrentNavUrl = expanded_filename; mMediaSource->setSize(mTextureWidth, mTextureHeight); - mMediaSource->navigateTo(expanded_filename, "text/html", false); + mMediaSource->navigateTo(expanded_filename, HTTP_CONTENT_TEXT_HTML, false); } } @@ -948,7 +949,7 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAVIGATE_ERROR_PAGE" << LL_ENDL; if ( mErrorPageURL.length() > 0 ) { - navigateTo(mErrorPageURL, "text/html"); + navigateTo(mErrorPageURL, HTTP_CONTENT_TEXT_HTML); }; }; break; diff --git a/indra/newview/llmediadataclient.cpp b/indra/newview/llmediadataclient.cpp index e3b46d5d2f..bc1aa087e5 100644 --- a/indra/newview/llmediadataclient.cpp +++ b/indra/newview/llmediadataclient.cpp @@ -35,7 +35,7 @@ #include <boost/lexical_cast.hpp> -#include "llhttpstatuscodes.h" +#include "llhttpconstants.h" #include "llsdutil.h" #include "llmediaentry.h" #include "lltextureentry.h" @@ -564,7 +564,7 @@ LLMediaDataClient::Responder::Responder(const request_ptr_t &request) } /*virtual*/ -void LLMediaDataClient::Responder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) +void LLMediaDataClient::Responder::httpFailure() { mRequest->stopTracking(); @@ -574,9 +574,17 @@ void LLMediaDataClient::Responder::errorWithContent(U32 status, const std::strin return; } - if (status == HTTP_SERVICE_UNAVAILABLE) + if (getStatus() == HTTP_SERVICE_UNAVAILABLE) { - F32 retry_timeout = mRequest->getRetryTimerDelay(); + F32 retry_timeout; +#if 0 + // *TODO: Honor server Retry-After header. + if (!hasResponseHeader(HTTP_HEADER_RETRY_AFTER) + || !getSecondsUntilRetryAfter(getResponseHeader(HTTP_HEADER_RETRY_AFTER), retry_timeout)) +#endif + { + retry_timeout = mRequest->getRetryTimerDelay(); + } mRequest->incRetryCount(); @@ -594,15 +602,16 @@ void LLMediaDataClient::Responder::errorWithContent(U32 status, const std::strin << mRequest->getRetryCount() << " exceeds " << mRequest->getMaxNumRetries() << ", not retrying" << LL_ENDL; } } + // *TODO: Redirect on 3xx status codes. else { - LL_WARNS("LLMediaDataClient") << *mRequest << " http error [status:" - << status << "]:" << content << ")" << LL_ENDL; + LL_WARNS("LLMediaDataClient") << *mRequest << " http failure " + << dumpResponse() << LL_ENDL; } } /*virtual*/ -void LLMediaDataClient::Responder::result(const LLSD& content) +void LLMediaDataClient::Responder::httpSuccess() { mRequest->stopTracking(); @@ -612,7 +621,7 @@ void LLMediaDataClient::Responder::result(const LLSD& content) return; } - LL_DEBUGS("LLMediaDataClientResponse") << *mRequest << " result : " << ll_print_sd(content) << LL_ENDL; + LL_DEBUGS("LLMediaDataClientResponse") << *mRequest << " " << dumpResponse() << LL_ENDL; } ////////////////////////////////////////////////////////////////////////////////////// @@ -876,7 +885,7 @@ LLMediaDataClient::Responder *LLObjectMediaDataClient::RequestUpdate::createResp /*virtual*/ -void LLObjectMediaDataClient::Responder::result(const LLSD& content) +void LLObjectMediaDataClient::Responder::httpSuccess() { getRequest()->stopTracking(); @@ -886,10 +895,16 @@ void LLObjectMediaDataClient::Responder::result(const LLSD& content) return; } + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } + // This responder is only used for GET requests, not UPDATE. + LL_DEBUGS("LLMediaDataClientResponse") << *(getRequest()) << " " << dumpResponse() << LL_ENDL; - LL_DEBUGS("LLMediaDataClientResponse") << *(getRequest()) << " GET returned: " << ll_print_sd(content) << LL_ENDL; - // Look for an error if (content.has("error")) { @@ -1003,7 +1018,7 @@ LLMediaDataClient::Responder *LLObjectMediaNavigateClient::RequestNavigate::crea } /*virtual*/ -void LLObjectMediaNavigateClient::Responder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) +void LLObjectMediaNavigateClient::Responder::httpFailure() { getRequest()->stopTracking(); @@ -1015,14 +1030,14 @@ void LLObjectMediaNavigateClient::Responder::errorWithContent(U32 status, const // Bounce back (unless HTTP_SERVICE_UNAVAILABLE, in which case call base // class - if (status == HTTP_SERVICE_UNAVAILABLE) + if (getStatus() == HTTP_SERVICE_UNAVAILABLE) { - LLMediaDataClient::Responder::errorWithContent(status, reason, content); + LLMediaDataClient::Responder::httpFailure(); } else { // bounce the face back - LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error navigating: http code=" << status << LL_ENDL; + LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error navigating: " << dumpResponse() << LL_ENDL; const LLSD &payload = getRequest()->getPayload(); // bounce the face back getRequest()->getObject()->mediaNavigateBounceBack((LLSD::Integer)payload[LLTextureEntry::TEXTURE_INDEX_KEY]); @@ -1030,7 +1045,7 @@ void LLObjectMediaNavigateClient::Responder::errorWithContent(U32 status, const } /*virtual*/ -void LLObjectMediaNavigateClient::Responder::result(const LLSD& content) +void LLObjectMediaNavigateClient::Responder::httpSuccess() { getRequest()->stopTracking(); @@ -1040,8 +1055,9 @@ void LLObjectMediaNavigateClient::Responder::result(const LLSD& content) return; } - LL_INFOS("LLMediaDataClient") << *(getRequest()) << " NAVIGATE returned " << ll_print_sd(content) << LL_ENDL; + LL_INFOS("LLMediaDataClient") << *(getRequest()) << " NAVIGATE returned " << dumpResponse() << LL_ENDL; + const LLSD& content = getContent(); if (content.has("error")) { const LLSD &error = content["error"]; @@ -1065,6 +1081,6 @@ void LLObjectMediaNavigateClient::Responder::result(const LLSD& content) else { // No action required. - LL_DEBUGS("LLMediaDataClientResponse") << *(getRequest()) << " result : " << ll_print_sd(content) << LL_ENDL; + LL_DEBUGS("LLMediaDataClientResponse") << *(getRequest()) << " " << dumpResponse() << LL_ENDL; } } diff --git a/indra/newview/llmediadataclient.h b/indra/newview/llmediadataclient.h index 89e20a28d0..231b883c32 100644 --- a/indra/newview/llmediadataclient.h +++ b/indra/newview/llmediadataclient.h @@ -74,8 +74,9 @@ public: // Abstracts the Cap URL, the request, and the responder class LLMediaDataClient : public LLRefCount { -public: +protected: LOG_CLASS(LLMediaDataClient); +public: const static F32 QUEUE_TIMER_DELAY;// = 1.0; // seconds(s) const static F32 UNAVAILABLE_RETRY_TIMER_DELAY;// = 5.0; // secs @@ -192,14 +193,16 @@ protected: // Responder class Responder : public LLHTTPClient::Responder { + LOG_CLASS(Responder); public: Responder(const request_ptr_t &request); + request_ptr_t &getRequest() { return mRequest; } + + protected: //If we get back an error (not found, etc...), handle it here - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content); + virtual void httpFailure(); //If we get back a normal response, handle it here. Default just logs it. - virtual void result(const LLSD& content); - - request_ptr_t &getRequest() { return mRequest; } + virtual void httpSuccess(); private: request_ptr_t mRequest; @@ -287,8 +290,9 @@ private: // MediaDataClient specific for the ObjectMedia cap class LLObjectMediaDataClient : public LLMediaDataClient { -public: +protected: LOG_CLASS(LLObjectMediaDataClient); +public: LLObjectMediaDataClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY, F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY, U32 max_retries = MAX_RETRIES, @@ -341,10 +345,12 @@ protected: class Responder : public LLMediaDataClient::Responder { + LOG_CLASS(Responder); public: Responder(const request_ptr_t &request) : LLMediaDataClient::Responder(request) {} - virtual void result(const LLSD &content); + protected: + virtual void httpSuccess(); }; private: // The Get/Update data client needs a second queue to avoid object updates starving load-ins. @@ -362,8 +368,9 @@ private: // MediaDataClient specific for the ObjectMediaNavigate cap class LLObjectMediaNavigateClient : public LLMediaDataClient { -public: +protected: LOG_CLASS(LLObjectMediaNavigateClient); +public: // NOTE: from llmediaservice.h static const int ERROR_PERMISSION_DENIED_CODE = 8002; @@ -397,11 +404,13 @@ protected: class Responder : public LLMediaDataClient::Responder { + LOG_CLASS(Responder); public: Responder(const request_ptr_t &request) : LLMediaDataClient::Responder(request) {} - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content); - virtual void result(const LLSD &content); + protected: + virtual void httpFailure(); + virtual void httpSuccess(); private: void mediaNavigateBounceBack(); }; diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 17311dd75e..1469dbc346 100755 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -28,7 +28,7 @@ #include "apr_pools.h" #include "apr_dso.h" -#include "llhttpstatuscodes.h" +#include "llhttpconstants.h" #include "llmeshrepository.h" #include "llagent.h" @@ -202,6 +202,7 @@ U32 LLMeshRepoThread::sMaxConcurrentRequests = 1; class LLMeshHeaderResponder : public LLCurl::Responder { + LOG_CLASS(LLMeshHeaderResponder); public: LLVolumeParams mMeshParams; bool mProcessed; @@ -230,14 +231,14 @@ public: } } - virtual void completedRaw(U32 status, const std::string& reason, - const LLChannelDescriptors& channels, + virtual void completedRaw(const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer); }; class LLMeshLODResponder : public LLCurl::Responder { + LOG_CLASS(LLMeshLODResponder); public: LLVolumeParams mMeshParams; S32 mLOD; @@ -266,14 +267,14 @@ public: } } - virtual void completedRaw(U32 status, const std::string& reason, - const LLChannelDescriptors& channels, + virtual void completedRaw(const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer); }; class LLMeshSkinInfoResponder : public LLCurl::Responder { + LOG_CLASS(LLMeshSkinInfoResponder); public: LLUUID mMeshID; U32 mRequestedBytes; @@ -291,14 +292,14 @@ public: llassert(mProcessed); } - virtual void completedRaw(U32 status, const std::string& reason, - const LLChannelDescriptors& channels, + virtual void completedRaw(const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer); }; class LLMeshDecompositionResponder : public LLCurl::Responder { + LOG_CLASS(LLMeshDecompositionResponder); public: LLUUID mMeshID; U32 mRequestedBytes; @@ -316,14 +317,14 @@ public: llassert(mProcessed); } - virtual void completedRaw(U32 status, const std::string& reason, - const LLChannelDescriptors& channels, + virtual void completedRaw(const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer); }; class LLMeshPhysicsShapeResponder : public LLCurl::Responder { + LOG_CLASS(LLMeshPhysicsShapeResponder); public: LLUUID mMeshID; U32 mRequestedBytes; @@ -341,8 +342,7 @@ public: llassert(mProcessed); } - virtual void completedRaw(U32 status, const std::string& reason, - const LLChannelDescriptors& channels, + virtual void completedRaw(const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer); }; @@ -398,6 +398,7 @@ void log_upload_error(S32 status, const LLSD& content, std::string stage, std::s class LLWholeModelFeeResponder: public LLCurl::Responder { + LOG_CLASS(LLWholeModelFeeResponder); LLMeshUploadThread* mThread; LLSD mModelData; LLHandle<LLWholeModelFeeObserver> mObserverHandle; @@ -421,21 +422,20 @@ public: } } - virtual void completed(U32 status, - const std::string& reason, - const LLSD& content) +protected: + virtual void httpCompleted() { - LLSD cc = content; + LLSD cc = getContent(); if (gSavedSettings.getS32("MeshUploadFakeErrors")&1) { cc = llsd_from_file("fake_upload_error.xml"); } - + dump_llsd_to_file(cc,make_dump_name("whole_model_fee_response_",dump_num)); LLWholeModelFeeObserver* observer = mObserverHandle.get(); - if (isGoodStatus(status) && + if (isGoodStatus() && cc["state"].asString() == "upload") { mThread->mWholeModelUploadURL = cc["uploader"].asString(); @@ -448,13 +448,14 @@ public: } else { - llwarns << "fee request failed" << llendl; + llwarns << "fee request failed " << dumpResponse() << llendl; + S32 status = getStatus(); log_upload_error(status,cc,"fee",mModelData["name"]); mThread->mWholeModelUploadURL = ""; if (observer) { - observer->setModelPhysicsFeeErrorStatus(status, reason); + observer->setModelPhysicsFeeErrorStatus(status, getReason()); } } } @@ -463,6 +464,7 @@ public: class LLWholeModelUploadResponder: public LLCurl::Responder { + LOG_CLASS(LLWholeModelUploadResponder); LLMeshUploadThread* mThread; LLSD mModelData; LLHandle<LLWholeModelUploadObserver> mObserverHandle; @@ -487,11 +489,10 @@ public: } } - virtual void completed(U32 status, - const std::string& reason, - const LLSD& content) +protected: + virtual void httpCompleted() { - LLSD cc = content; + LLSD cc = getContent(); if (gSavedSettings.getS32("MeshUploadFakeErrors")&2) { cc = llsd_from_file("fake_upload_error.xml"); @@ -503,7 +504,7 @@ public: // requested "mesh" asset type isn't actually the type // of the resultant object, fix it up here. - if (isGoodStatus(status) && + if (isGoodStatus() && cc["state"].asString() == "complete") { mModelData["asset_type"] = "object"; @@ -516,9 +517,9 @@ public: } else { - llwarns << "upload failed" << llendl; + llwarns << "upload failed " << dumpResponse() << llendl; std::string model_name = mModelData["name"].asString(); - log_upload_error(status,cc,"upload",model_name); + log_upload_error(getStatus(),cc,"upload",model_name); if (observer) { @@ -807,7 +808,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) //reading from VFS failed for whatever reason, fetch from sim std::vector<std::string> headers; - headers.push_back("Accept: application/octet-stream"); + headers.push_back(HTTP_HEADER_ACCEPT + ": " + HTTP_CONTENT_OCTET_STREAM); std::string http_url = constructUrl(mesh_id); if (!http_url.empty()) @@ -889,7 +890,7 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id) //reading from VFS failed for whatever reason, fetch from sim std::vector<std::string> headers; - headers.push_back("Accept: application/octet-stream"); + headers.push_back(HTTP_HEADER_ACCEPT + ": " + HTTP_CONTENT_OCTET_STREAM); std::string http_url = constructUrl(mesh_id); if (!http_url.empty()) @@ -970,7 +971,7 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id) //reading from VFS failed for whatever reason, fetch from sim std::vector<std::string> headers; - headers.push_back("Accept: application/octet-stream"); + headers.push_back(HTTP_HEADER_ACCEPT + ": " + HTTP_CONTENT_OCTET_STREAM); std::string http_url = constructUrl(mesh_id); if (!http_url.empty()) @@ -1051,7 +1052,7 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params, U32& c //either cache entry doesn't exist or is corrupt, request header from simulator bool retval = true ; std::vector<std::string> headers; - headers.push_back("Accept: application/octet-stream"); + headers.push_back(HTTP_HEADER_ACCEPT + ": " + HTTP_CONTENT_OCTET_STREAM); std::string http_url = constructUrl(mesh_params.getSculptID()); if (!http_url.empty()) @@ -1126,7 +1127,7 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod, //reading from VFS failed for whatever reason, fetch from sim std::vector<std::string> headers; - headers.push_back("Accept: application/octet-stream"); + headers.push_back(HTTP_HEADER_ACCEPT + ": " + HTTP_CONTENT_OCTET_STREAM); std::string http_url = constructUrl(mesh_id); if (!http_url.empty()) @@ -1898,10 +1899,10 @@ void LLMeshRepository::cacheOutgoingMesh(LLMeshUploadData& data, LLSD& header) } -void LLMeshLODResponder::completedRaw(U32 status, const std::string& reason, - const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer) +void LLMeshLODResponder::completedRaw(const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) { + S32 status = getStatus(); mProcessed = true; // thread could have already be destroyed during logout @@ -1912,14 +1913,15 @@ void LLMeshLODResponder::completedRaw(U32 status, const std::string& reason, S32 data_size = buffer->countAfter(channels.in(), NULL); + // *TODO: What about 3xx redirect codes? What about status 400 (Bad Request)? if (status < 200 || status > 400) { - llwarns << status << ": " << reason << llendl; + llwarns << dumpResponse() << llendl; } if (data_size < mRequestedBytes) { - if (status == 499 || status == 503) + if (status == HTTP_INTERNAL_ERROR || status == HTTP_SERVICE_UNAVAILABLE) { //timeout or service unavailable, try again llwarns << "Timeout or service unavailable, retrying." << llendl; LLMeshRepository::sHTTPRetryCount++; @@ -1927,8 +1929,8 @@ void LLMeshLODResponder::completedRaw(U32 status, const std::string& reason, } else { - llassert(status == 499 || status == 503); //intentionally trigger a breakpoint - llwarns << "Unhandled status " << status << llendl; + llassert(status == HTTP_INTERNAL_ERROR || status == HTTP_SERVICE_UNAVAILABLE); //intentionally trigger a breakpoint + llwarns << "Unhandled status " << dumpResponse() << llendl; } return; } @@ -1962,10 +1964,10 @@ void LLMeshLODResponder::completedRaw(U32 status, const std::string& reason, delete [] data; } -void LLMeshSkinInfoResponder::completedRaw(U32 status, const std::string& reason, - const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer) +void LLMeshSkinInfoResponder::completedRaw(const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) { + S32 status = getStatus(); mProcessed = true; // thread could have already be destroyed during logout @@ -1976,14 +1978,15 @@ void LLMeshSkinInfoResponder::completedRaw(U32 status, const std::string& reason S32 data_size = buffer->countAfter(channels.in(), NULL); + // *TODO: What about 3xx redirect codes? What about status 400 (Bad Request)? if (status < 200 || status > 400) { - llwarns << status << ": " << reason << llendl; + llwarns << dumpResponse() << llendl; } if (data_size < mRequestedBytes) { - if (status == 499 || status == 503) + if (status == HTTP_INTERNAL_ERROR || status == HTTP_SERVICE_UNAVAILABLE) { //timeout or service unavailable, try again llwarns << "Timeout or service unavailable, retrying." << llendl; LLMeshRepository::sHTTPRetryCount++; @@ -1991,8 +1994,8 @@ void LLMeshSkinInfoResponder::completedRaw(U32 status, const std::string& reason } else { - llassert(status == 499 || status == 503); //intentionally trigger a breakpoint - llwarns << "Unhandled status " << status << llendl; + llassert(status == HTTP_INTERNAL_ERROR || status == HTTP_SERVICE_UNAVAILABLE); //intentionally trigger a breakpoint + llwarns << "Unhandled status " << dumpResponse() << llendl; } return; } @@ -2026,10 +2029,10 @@ void LLMeshSkinInfoResponder::completedRaw(U32 status, const std::string& reason delete [] data; } -void LLMeshDecompositionResponder::completedRaw(U32 status, const std::string& reason, - const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer) +void LLMeshDecompositionResponder::completedRaw(const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) { + S32 status = getStatus(); mProcessed = true; if( !gMeshRepo.mThread ) @@ -2039,14 +2042,15 @@ void LLMeshDecompositionResponder::completedRaw(U32 status, const std::string& r S32 data_size = buffer->countAfter(channels.in(), NULL); + // *TODO: What about 3xx redirect codes? What about status 400 (Bad Request)? if (status < 200 || status > 400) { - llwarns << status << ": " << reason << llendl; + llwarns << dumpResponse() << llendl; } if (data_size < mRequestedBytes) { - if (status == 499 || status == 503) + if (status == HTTP_INTERNAL_ERROR || status == HTTP_SERVICE_UNAVAILABLE) { //timeout or service unavailable, try again llwarns << "Timeout or service unavailable, retrying." << llendl; LLMeshRepository::sHTTPRetryCount++; @@ -2054,8 +2058,8 @@ void LLMeshDecompositionResponder::completedRaw(U32 status, const std::string& r } else { - llassert(status == 499 || status == 503); //intentionally trigger a breakpoint - llwarns << "Unhandled status " << status << llendl; + llassert(status == HTTP_INTERNAL_ERROR || status == HTTP_SERVICE_UNAVAILABLE); //intentionally trigger a breakpoint + llwarns << "Unhandled status " << dumpResponse() << llendl; } return; } @@ -2089,10 +2093,10 @@ void LLMeshDecompositionResponder::completedRaw(U32 status, const std::string& r delete [] data; } -void LLMeshPhysicsShapeResponder::completedRaw(U32 status, const std::string& reason, - const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer) +void LLMeshPhysicsShapeResponder::completedRaw(const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) { + S32 status = getStatus(); mProcessed = true; // thread could have already be destroyed during logout @@ -2103,14 +2107,15 @@ void LLMeshPhysicsShapeResponder::completedRaw(U32 status, const std::string& re S32 data_size = buffer->countAfter(channels.in(), NULL); + // *TODO: What about 3xx redirect codes? What about status 400 (Bad Request)? if (status < 200 || status > 400) { - llwarns << status << ": " << reason << llendl; + llwarns << dumpResponse() << llendl; } if (data_size < mRequestedBytes) { - if (status == 499 || status == 503) + if (status == HTTP_INTERNAL_ERROR || status == HTTP_SERVICE_UNAVAILABLE) { //timeout or service unavailable, try again llwarns << "Timeout or service unavailable, retrying." << llendl; LLMeshRepository::sHTTPRetryCount++; @@ -2118,8 +2123,8 @@ void LLMeshPhysicsShapeResponder::completedRaw(U32 status, const std::string& re } else { - llassert(status == 499 || status == 503); //intentionally trigger a breakpoint - llwarns << "Unhandled status " << status << llendl; + llassert(status == HTTP_INTERNAL_ERROR || status == HTTP_SERVICE_UNAVAILABLE); //intentionally trigger a breakpoint + llwarns << "Unhandled status " << dumpResponse() << llendl; } return; } @@ -2153,10 +2158,10 @@ void LLMeshPhysicsShapeResponder::completedRaw(U32 status, const std::string& re delete [] data; } -void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason, - const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer) +void LLMeshHeaderResponder::completedRaw(const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) { + S32 status = getStatus(); mProcessed = true; // thread could have already be destroyed during logout @@ -2165,6 +2170,7 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason, return; } + // *TODO: What about 3xx redirect codes? What about status 400 (Bad Request)? if (status < 200 || status > 400) { //llwarns @@ -2178,9 +2184,9 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason, // and (somewhat more optional than the others) retries // again after some set period of time - llassert(status == 503 || status == 499); + llassert(status == HTTP_SERVICE_UNAVAILABLE || status == HTTP_INTERNAL_ERROR); - if (status == 503 || status == 499) + if (status == HTTP_SERVICE_UNAVAILABLE || status == HTTP_INTERNAL_ERROR) { //retry llwarns << "Timeout or service unavailable, retrying." << llendl; LLMeshRepository::sHTTPRetryCount++; @@ -2192,7 +2198,7 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason, } else { - llwarns << "Unhandled status." << llendl; + llwarns << "Unhandled status " << dumpResponse() << llendl; } } @@ -2214,9 +2220,7 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason, if (!success) { - llwarns - << "Unable to parse mesh header: " - << status << ": " << reason << llendl; + llwarns << "Unable to parse mesh header: " << dumpResponse() << llendl; } else if (data && data_size > 0) { diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp index 862e4be203..4f5e07c566 100644 --- a/indra/newview/llpanelclassified.cpp +++ b/indra/newview/llpanelclassified.cpp @@ -95,15 +95,11 @@ class LLClassifiedClickMessageResponder : public LLHTTPClient::Responder { LOG_CLASS(LLClassifiedClickMessageResponder); -public: +protected: // If we get back an error (not found, etc...), handle it here - virtual void errorWithContent( - U32 status, - const std::string& reason, - const LLSD& content) + virtual void httpFailure() { - llwarns << "Sending click message failed (" << status << "): [" << reason << "]" << llendl; - llwarns << "Content: [" << content << "]" << llendl; + llwarns << "Sending click message failed " << dumpResponse() << llendl; } }; diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index d6fccb9705..21b58dfbbf 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -529,7 +529,7 @@ void LLLandmarksPanel::setParcelID(const LLUUID& parcel_id) } // virtual -void LLLandmarksPanel::setErrorStatus(U32 status, const std::string& reason) +void LLLandmarksPanel::setErrorStatus(S32 status, const std::string& reason) { llwarns << "Can't handle remote parcel request."<< " Http Status: "<< status << ". Reason : "<< reason<<llendl; } diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h index 4e787317ba..14709b267e 100644 --- a/indra/newview/llpanellandmarks.h +++ b/indra/newview/llpanellandmarks.h @@ -104,7 +104,7 @@ protected: //LLRemoteParcelInfoObserver interface /*virtual*/ void processParcelInfo(const LLParcelData& parcel_data); /*virtual*/ void setParcelID(const LLUUID& parcel_id); - /*virtual*/ void setErrorStatus(U32 status, const std::string& reason); + /*virtual*/ void setErrorStatus(S32 status, const std::string& reason); private: void initFavoritesInventoryPanel(); diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index bcb90bcb56..c4ba097914 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -437,7 +437,7 @@ void LLPanelLogin::showLoginWidgets() sInstance->reshapeBrowser(); // *TODO: Append all the usual login parameters, like first_login=Y etc. std::string splash_screen_url = LLGridManager::getInstance()->getLoginPage(); - web_browser->navigateTo( splash_screen_url, "text/html" ); + web_browser->navigateTo( splash_screen_url, HTTP_CONTENT_TEXT_HTML ); LLUICtrl* username_combo = sInstance->getChild<LLUICtrl>("username_combo"); username_combo->setFocus(TRUE); } @@ -791,7 +791,7 @@ void LLPanelLogin::loadLoginPage() if (web_browser->getCurrentNavUrl() != login_uri.asString()) { LL_DEBUGS("AppInit") << "loading: " << login_uri << LL_ENDL; - web_browser->navigateTo( login_uri.asString(), "text/html" ); + web_browser->navigateTo( login_uri.asString(), HTTP_CONTENT_TEXT_HTML ); } } diff --git a/indra/newview/llpanelpick.h b/indra/newview/llpanelpick.h index 3c1f14759c..7a8bd66fcf 100644 --- a/indra/newview/llpanelpick.h +++ b/indra/newview/llpanelpick.h @@ -86,7 +86,7 @@ public: //This stuff we got from LLRemoteParcelObserver, in the last one we intentionally do nothing /*virtual*/ void processParcelInfo(const LLParcelData& parcel_data); /*virtual*/ void setParcelID(const LLUUID& parcel_id) { mParcelId = parcel_id; } - /*virtual*/ void setErrorStatus(U32 status, const std::string& reason) {}; + /*virtual*/ void setErrorStatus(S32 status, const std::string& reason) {}; protected: diff --git a/indra/newview/llpanelplaceinfo.cpp b/indra/newview/llpanelplaceinfo.cpp index 4ae0c0eb12..4e7c5f6ed2 100644 --- a/indra/newview/llpanelplaceinfo.cpp +++ b/indra/newview/llpanelplaceinfo.cpp @@ -169,15 +169,15 @@ void LLPanelPlaceInfo::displayParcelInfo(const LLUUID& region_id, } // virtual -void LLPanelPlaceInfo::setErrorStatus(U32 status, const std::string& reason) +void LLPanelPlaceInfo::setErrorStatus(S32 status, const std::string& reason) { // We only really handle 404 and 499 errors std::string error_text; - if(status == 404) + if(status == HTTP_NOT_FOUND) { error_text = getString("server_error_text"); } - else if(status == 499) + else if(status == HTTP_INTERNAL_ERROR) { error_text = getString("server_forbidden_text"); } diff --git a/indra/newview/llpanelplaceinfo.h b/indra/newview/llpanelplaceinfo.h index 64f0b6b550..30327378ef 100644 --- a/indra/newview/llpanelplaceinfo.h +++ b/indra/newview/llpanelplaceinfo.h @@ -86,7 +86,7 @@ public: void displayParcelInfo(const LLUUID& region_id, const LLVector3d& pos_global); - /*virtual*/ void setErrorStatus(U32 status, const std::string& reason); + /*virtual*/ void setErrorStatus(S32 status, const std::string& reason); /*virtual*/ void processParcelInfo(const LLParcelData& parcel_data); diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index 6c2a01fc82..730df2ea23 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -217,7 +217,7 @@ public: LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(parcel_id); } } - /*virtual*/ void setErrorStatus(U32 status, const std::string& reason) + /*virtual*/ void setErrorStatus(S32 status, const std::string& reason) { llerrs << "Can't complete remote parcel request. Http Status: " << status << ". Reason : " << reason << llendl; diff --git a/indra/newview/llpathfindingmanager.cpp b/indra/newview/llpathfindingmanager.cpp index c277359133..a9c755de35 100644 --- a/indra/newview/llpathfindingmanager.cpp +++ b/indra/newview/llpathfindingmanager.cpp @@ -103,17 +103,16 @@ LLHTTPRegistration<LLAgentStateChangeNode> gHTTPRegistrationAgentStateChangeNode class NavMeshStatusResponder : public LLHTTPClient::Responder { + LOG_CLASS(NavMeshStatusResponder); public: - NavMeshStatusResponder(const std::string &pCapabilityURL, LLViewerRegion *pRegion, bool pIsGetStatusOnly); + NavMeshStatusResponder(LLViewerRegion *pRegion, bool pIsGetStatusOnly); virtual ~NavMeshStatusResponder(); - virtual void result(const LLSD &pContent); - virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent); - protected: + virtual void httpSuccess(); + virtual void httpFailure(); private: - std::string mCapabilityURL; LLViewerRegion *mRegion; LLUUID mRegionUUID; bool mIsGetStatusOnly; @@ -125,17 +124,16 @@ private: class NavMeshResponder : public LLHTTPClient::Responder { + LOG_CLASS(NavMeshResponder); public: - NavMeshResponder(const std::string &pCapabilityURL, U32 pNavMeshVersion, LLPathfindingNavMeshPtr pNavMeshPtr); + NavMeshResponder(U32 pNavMeshVersion, LLPathfindingNavMeshPtr pNavMeshPtr); virtual ~NavMeshResponder(); - virtual void result(const LLSD &pContent); - virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent); - protected: + virtual void httpSuccess(); + virtual void httpFailure(); private: - std::string mCapabilityURL; U32 mNavMeshVersion; LLPathfindingNavMeshPtr mNavMeshPtr; }; @@ -146,17 +144,14 @@ private: class AgentStateResponder : public LLHTTPClient::Responder { + LOG_CLASS(AgentStateResponder); public: - AgentStateResponder(const std::string &pCapabilityURL); + AgentStateResponder(); virtual ~AgentStateResponder(); - virtual void result(const LLSD &pContent); - virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent); - protected: - -private: - std::string mCapabilityURL; + virtual void httpSuccess(); + virtual void httpFailure(); }; @@ -165,17 +160,16 @@ private: //--------------------------------------------------------------------------- class NavMeshRebakeResponder : public LLHTTPClient::Responder { + LOG_CLASS(NavMeshRebakeResponder); public: - NavMeshRebakeResponder(const std::string &pCapabilityURL, LLPathfindingManager::rebake_navmesh_callback_t pRebakeNavMeshCallback); + NavMeshRebakeResponder(LLPathfindingManager::rebake_navmesh_callback_t pRebakeNavMeshCallback); virtual ~NavMeshRebakeResponder(); - virtual void result(const LLSD &pContent); - virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent); - protected: + virtual void httpSuccess(); + virtual void httpFailure(); private: - std::string mCapabilityURL; LLPathfindingManager::rebake_navmesh_callback_t mRebakeNavMeshCallback; }; @@ -190,11 +184,9 @@ public: virtual ~LinksetsResponder(); void handleObjectLinksetsResult(const LLSD &pContent); - void handleObjectLinksetsError(U32 pStatus, const std::string &pReason, - const LLSD& pContent, const std::string &pURL); + void handleObjectLinksetsError(); void handleTerrainLinksetsResult(const LLSD &pContent); - void handleTerrainLinksetsError(U32 pStatus, const std::string &pReason, - const LLSD& pContent, const std::string &pURL); + void handleTerrainLinksetsError(); protected: @@ -227,17 +219,16 @@ typedef boost::shared_ptr<LinksetsResponder> LinksetsResponderPtr; class ObjectLinksetsResponder : public LLHTTPClient::Responder { + LOG_CLASS(ObjectLinksetsResponder); public: - ObjectLinksetsResponder(const std::string &pCapabilityURL, LinksetsResponderPtr pLinksetsResponsderPtr); + ObjectLinksetsResponder(LinksetsResponderPtr pLinksetsResponsderPtr); virtual ~ObjectLinksetsResponder(); - virtual void result(const LLSD &pContent); - virtual void errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent); - protected: + virtual void httpSuccess(); + virtual void httpFailure(); private: - std::string mCapabilityURL; LinksetsResponderPtr mLinksetsResponsderPtr; }; @@ -247,17 +238,16 @@ private: class TerrainLinksetsResponder : public LLHTTPClient::Responder { + LOG_CLASS(TerrainLinksetsResponder); public: - TerrainLinksetsResponder(const std::string &pCapabilityURL, LinksetsResponderPtr pLinksetsResponsderPtr); + TerrainLinksetsResponder(LinksetsResponderPtr pLinksetsResponsderPtr); virtual ~TerrainLinksetsResponder(); - virtual void result(const LLSD &pContent); - virtual void errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent); - protected: + virtual void httpSuccess(); + virtual void httpFailure(); private: - std::string mCapabilityURL; LinksetsResponderPtr mLinksetsResponsderPtr; }; @@ -267,17 +257,16 @@ private: class CharactersResponder : public LLHTTPClient::Responder { + LOG_CLASS(TerrainLinksetsResponder); public: - CharactersResponder(const std::string &pCapabilityURL, LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::object_request_callback_t pCharactersCallback); + CharactersResponder(LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::object_request_callback_t pCharactersCallback); virtual ~CharactersResponder(); - virtual void result(const LLSD &pContent); - virtual void errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent); - protected: + virtual void httpSuccess(); + virtual void httpFailure(); private: - std::string mCapabilityURL; LLPathfindingManager::request_id_t mRequestId; LLPathfindingManager::object_request_callback_t mCharactersCallback; }; @@ -364,7 +353,7 @@ void LLPathfindingManager::requestGetNavMeshForRegion(LLViewerRegion *pRegion, b std::string navMeshStatusURL = getNavMeshStatusURLForRegion(pRegion); llassert(!navMeshStatusURL.empty()); navMeshPtr->handleNavMeshCheckVersion(); - LLHTTPClient::ResponderPtr navMeshStatusResponder = new NavMeshStatusResponder(navMeshStatusURL, pRegion, pIsGetStatusOnly); + LLHTTPClient::ResponderPtr navMeshStatusResponder = new NavMeshStatusResponder(pRegion, pIsGetStatusOnly); LLHTTPClient::get(navMeshStatusURL, navMeshStatusResponder); } } @@ -398,12 +387,12 @@ void LLPathfindingManager::requestGetLinksets(request_id_t pRequestId, object_re bool doRequestTerrain = isAllowViewTerrainProperties(); LinksetsResponderPtr linksetsResponderPtr(new LinksetsResponder(pRequestId, pLinksetsCallback, true, doRequestTerrain)); - LLHTTPClient::ResponderPtr objectLinksetsResponder = new ObjectLinksetsResponder(objectLinksetsURL, linksetsResponderPtr); + LLHTTPClient::ResponderPtr objectLinksetsResponder = new ObjectLinksetsResponder(linksetsResponderPtr); LLHTTPClient::get(objectLinksetsURL, objectLinksetsResponder); if (doRequestTerrain) { - LLHTTPClient::ResponderPtr terrainLinksetsResponder = new TerrainLinksetsResponder(terrainLinksetsURL, linksetsResponderPtr); + LLHTTPClient::ResponderPtr terrainLinksetsResponder = new TerrainLinksetsResponder(linksetsResponderPtr); LLHTTPClient::get(terrainLinksetsURL, terrainLinksetsResponder); } } @@ -447,13 +436,13 @@ void LLPathfindingManager::requestSetLinksets(request_id_t pRequestId, const LLP if (!objectPostData.isUndefined()) { - LLHTTPClient::ResponderPtr objectLinksetsResponder = new ObjectLinksetsResponder(objectLinksetsURL, linksetsResponderPtr); + LLHTTPClient::ResponderPtr objectLinksetsResponder = new ObjectLinksetsResponder(linksetsResponderPtr); LLHTTPClient::put(objectLinksetsURL, objectPostData, objectLinksetsResponder); } if (!terrainPostData.isUndefined()) { - LLHTTPClient::ResponderPtr terrainLinksetsResponder = new TerrainLinksetsResponder(terrainLinksetsURL, linksetsResponderPtr); + LLHTTPClient::ResponderPtr terrainLinksetsResponder = new TerrainLinksetsResponder(linksetsResponderPtr); LLHTTPClient::put(terrainLinksetsURL, terrainPostData, terrainLinksetsResponder); } } @@ -486,7 +475,7 @@ void LLPathfindingManager::requestGetCharacters(request_id_t pRequestId, object_ { pCharactersCallback(pRequestId, kRequestStarted, emptyCharacterListPtr); - LLHTTPClient::ResponderPtr charactersResponder = new CharactersResponder(charactersURL, pRequestId, pCharactersCallback); + LLHTTPClient::ResponderPtr charactersResponder = new CharactersResponder(pRequestId, pCharactersCallback); LLHTTPClient::get(charactersURL, charactersResponder); } } @@ -519,7 +508,7 @@ void LLPathfindingManager::requestGetAgentState() { std::string agentStateURL = getAgentStateURLForRegion(currentRegion); llassert(!agentStateURL.empty()); - LLHTTPClient::ResponderPtr responder = new AgentStateResponder(agentStateURL); + LLHTTPClient::ResponderPtr responder = new AgentStateResponder(); LLHTTPClient::get(agentStateURL, responder); } } @@ -543,7 +532,7 @@ void LLPathfindingManager::requestRebakeNavMesh(rebake_navmesh_callback_t pRebak llassert(!navMeshStatusURL.empty()); LLSD postData; postData["command"] = "rebuild"; - LLHTTPClient::ResponderPtr responder = new NavMeshRebakeResponder(navMeshStatusURL, pRebakeNavMeshCallback); + LLHTTPClient::ResponderPtr responder = new NavMeshRebakeResponder(pRebakeNavMeshCallback); LLHTTPClient::post(navMeshStatusURL, postData, responder); } } @@ -565,7 +554,7 @@ void LLPathfindingManager::sendRequestGetNavMeshForRegion(LLPathfindingNavMeshPt else { navMeshPtr->handleNavMeshStart(pNavMeshStatus); - LLHTTPClient::ResponderPtr responder = new NavMeshResponder(navMeshURL, pNavMeshStatus.getVersion(), navMeshPtr); + LLHTTPClient::ResponderPtr responder = new NavMeshResponder(pNavMeshStatus.getVersion(), navMeshPtr); LLSD postData; LLHTTPClient::post(navMeshURL, postData, responder); @@ -779,9 +768,8 @@ void LLAgentStateChangeNode::post(ResponsePtr pResponse, const LLSD &pContext, c // NavMeshStatusResponder //--------------------------------------------------------------------------- -NavMeshStatusResponder::NavMeshStatusResponder(const std::string &pCapabilityURL, LLViewerRegion *pRegion, bool pIsGetStatusOnly) +NavMeshStatusResponder::NavMeshStatusResponder(LLViewerRegion *pRegion, bool pIsGetStatusOnly) : LLHTTPClient::Responder(), - mCapabilityURL(pCapabilityURL), mRegion(pRegion), mRegionUUID(), mIsGetStatusOnly(pIsGetStatusOnly) @@ -796,15 +784,15 @@ NavMeshStatusResponder::~NavMeshStatusResponder() { } -void NavMeshStatusResponder::result(const LLSD &pContent) +void NavMeshStatusResponder::httpSuccess() { - LLPathfindingNavMeshStatus navMeshStatus(mRegionUUID, pContent); + LLPathfindingNavMeshStatus navMeshStatus(mRegionUUID, getContent()); LLPathfindingManager::getInstance()->handleNavMeshStatusRequest(navMeshStatus, mRegion, mIsGetStatusOnly); } -void NavMeshStatusResponder::errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent) +void NavMeshStatusResponder::httpFailure() { - llwarns << "NavMeshStatusResponder error [status:" << pStatus << "]: " << pContent << llendl; + llwarns << dumpResponse() << llendl; LLPathfindingNavMeshStatus navMeshStatus(mRegionUUID); LLPathfindingManager::getInstance()->handleNavMeshStatusRequest(navMeshStatus, mRegion, mIsGetStatusOnly); } @@ -813,9 +801,8 @@ void NavMeshStatusResponder::errorWithContent(U32 pStatus, const std::string& pR // NavMeshResponder //--------------------------------------------------------------------------- -NavMeshResponder::NavMeshResponder(const std::string &pCapabilityURL, U32 pNavMeshVersion, LLPathfindingNavMeshPtr pNavMeshPtr) +NavMeshResponder::NavMeshResponder(U32 pNavMeshVersion, LLPathfindingNavMeshPtr pNavMeshPtr) : LLHTTPClient::Responder(), - mCapabilityURL(pCapabilityURL), mNavMeshVersion(pNavMeshVersion), mNavMeshPtr(pNavMeshPtr) { @@ -825,23 +812,23 @@ NavMeshResponder::~NavMeshResponder() { } -void NavMeshResponder::result(const LLSD &pContent) +void NavMeshResponder::httpSuccess() { - mNavMeshPtr->handleNavMeshResult(pContent, mNavMeshVersion); + mNavMeshPtr->handleNavMeshResult(getContent(), mNavMeshVersion); } -void NavMeshResponder::errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent) +void NavMeshResponder::httpFailure() { - mNavMeshPtr->handleNavMeshError(pStatus, pReason, pContent, mCapabilityURL, mNavMeshVersion); + llwarns << dumpResponse() << llendl; + mNavMeshPtr->handleNavMeshError(mNavMeshVersion); } //--------------------------------------------------------------------------- // AgentStateResponder //--------------------------------------------------------------------------- -AgentStateResponder::AgentStateResponder(const std::string &pCapabilityURL) +AgentStateResponder::AgentStateResponder() : LLHTTPClient::Responder() -, mCapabilityURL(pCapabilityURL) { } @@ -849,17 +836,18 @@ AgentStateResponder::~AgentStateResponder() { } -void AgentStateResponder::result(const LLSD &pContent) +void AgentStateResponder::httpSuccess() { + const LLSD& pContent = getContent(); llassert(pContent.has(AGENT_STATE_CAN_REBAKE_REGION_FIELD)); llassert(pContent.get(AGENT_STATE_CAN_REBAKE_REGION_FIELD).isBoolean()); BOOL canRebakeRegion = pContent.get(AGENT_STATE_CAN_REBAKE_REGION_FIELD).asBoolean(); LLPathfindingManager::getInstance()->handleAgentState(canRebakeRegion); } -void AgentStateResponder::errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent) +void AgentStateResponder::httpFailure() { - llwarns << "AgentStateResponder error [status:" << pStatus << "]: " << pContent << llendl; + llwarns << dumpResponse() << llendl; LLPathfindingManager::getInstance()->handleAgentState(FALSE); } @@ -867,9 +855,8 @@ void AgentStateResponder::errorWithContent(U32 pStatus, const std::string &pReas //--------------------------------------------------------------------------- // navmesh rebake responder //--------------------------------------------------------------------------- -NavMeshRebakeResponder::NavMeshRebakeResponder(const std::string &pCapabilityURL, LLPathfindingManager::rebake_navmesh_callback_t pRebakeNavMeshCallback) +NavMeshRebakeResponder::NavMeshRebakeResponder(LLPathfindingManager::rebake_navmesh_callback_t pRebakeNavMeshCallback) : LLHTTPClient::Responder(), - mCapabilityURL(pCapabilityURL), mRebakeNavMeshCallback(pRebakeNavMeshCallback) { } @@ -878,14 +865,14 @@ NavMeshRebakeResponder::~NavMeshRebakeResponder() { } -void NavMeshRebakeResponder::result(const LLSD &pContent) +void NavMeshRebakeResponder::httpSuccess() { mRebakeNavMeshCallback(true); } -void NavMeshRebakeResponder::errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent) +void NavMeshRebakeResponder::httpFailure() { - llwarns << "NavMeshRebakeResponder error [status:" << pStatus << "]: " << pContent << llendl; + llwarns << dumpResponse() << llendl; mRebakeNavMeshCallback(false); } @@ -918,11 +905,8 @@ void LinksetsResponder::handleObjectLinksetsResult(const LLSD &pContent) } } -void LinksetsResponder::handleObjectLinksetsError(U32 pStatus, const std::string &pReason, - const LLSD& pContent, const std::string &pURL) +void LinksetsResponder::handleObjectLinksetsError() { - llwarns << "LinksetsResponder object linksets error with request to URL '" << pURL << "' [status:" - << pStatus << "]: " << pContent << llendl; mObjectMessagingState = kReceivedError; if (mTerrainMessagingState != kWaiting) { @@ -941,11 +925,8 @@ void LinksetsResponder::handleTerrainLinksetsResult(const LLSD &pContent) } } -void LinksetsResponder::handleTerrainLinksetsError(U32 pStatus, const std::string &pReason, - const LLSD& pContent, const std::string &pURL) +void LinksetsResponder::handleTerrainLinksetsError() { - llwarns << "LinksetsResponder terrain linksets error with request to URL '" << pURL << "' [status:" - << pStatus << "]: " << pContent << llendl; mTerrainMessagingState = kReceivedError; if (mObjectMessagingState != kWaiting) { @@ -979,9 +960,8 @@ void LinksetsResponder::sendCallback() // ObjectLinksetsResponder //--------------------------------------------------------------------------- -ObjectLinksetsResponder::ObjectLinksetsResponder(const std::string &pCapabilityURL, LinksetsResponderPtr pLinksetsResponsderPtr) +ObjectLinksetsResponder::ObjectLinksetsResponder(LinksetsResponderPtr pLinksetsResponsderPtr) : LLHTTPClient::Responder(), - mCapabilityURL(pCapabilityURL), mLinksetsResponsderPtr(pLinksetsResponsderPtr) { } @@ -990,23 +970,23 @@ ObjectLinksetsResponder::~ObjectLinksetsResponder() { } -void ObjectLinksetsResponder::result(const LLSD &pContent) +void ObjectLinksetsResponder::httpSuccess() { - mLinksetsResponsderPtr->handleObjectLinksetsResult(pContent); + mLinksetsResponsderPtr->handleObjectLinksetsResult(getContent()); } -void ObjectLinksetsResponder::errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent) +void ObjectLinksetsResponder::httpFailure() { - mLinksetsResponsderPtr->handleObjectLinksetsError(pStatus, pReason, pContent, mCapabilityURL); + llwarns << dumpResponse() << llendl; + mLinksetsResponsderPtr->handleObjectLinksetsError(); } //--------------------------------------------------------------------------- // TerrainLinksetsResponder //--------------------------------------------------------------------------- -TerrainLinksetsResponder::TerrainLinksetsResponder(const std::string &pCapabilityURL, LinksetsResponderPtr pLinksetsResponsderPtr) +TerrainLinksetsResponder::TerrainLinksetsResponder(LinksetsResponderPtr pLinksetsResponsderPtr) : LLHTTPClient::Responder(), - mCapabilityURL(pCapabilityURL), mLinksetsResponsderPtr(pLinksetsResponsderPtr) { } @@ -1015,23 +995,23 @@ TerrainLinksetsResponder::~TerrainLinksetsResponder() { } -void TerrainLinksetsResponder::result(const LLSD &pContent) +void TerrainLinksetsResponder::httpSuccess() { - mLinksetsResponsderPtr->handleTerrainLinksetsResult(pContent); + mLinksetsResponsderPtr->handleTerrainLinksetsResult(getContent()); } -void TerrainLinksetsResponder::errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent) +void TerrainLinksetsResponder::httpFailure() { - mLinksetsResponsderPtr->handleTerrainLinksetsError(pStatus, pReason, pContent, mCapabilityURL); + llwarns << dumpResponse() << llendl; + mLinksetsResponsderPtr->handleTerrainLinksetsError(); } //--------------------------------------------------------------------------- // CharactersResponder //--------------------------------------------------------------------------- -CharactersResponder::CharactersResponder(const std::string &pCapabilityURL, LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::object_request_callback_t pCharactersCallback) +CharactersResponder::CharactersResponder(LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::object_request_callback_t pCharactersCallback) : LLHTTPClient::Responder(), - mCapabilityURL(pCapabilityURL), mRequestId(pRequestId), mCharactersCallback(pCharactersCallback) { @@ -1041,15 +1021,15 @@ CharactersResponder::~CharactersResponder() { } -void CharactersResponder::result(const LLSD &pContent) +void CharactersResponder::httpSuccess() { - LLPathfindingObjectListPtr characterListPtr = LLPathfindingObjectListPtr(new LLPathfindingCharacterList(pContent)); + LLPathfindingObjectListPtr characterListPtr = LLPathfindingObjectListPtr(new LLPathfindingCharacterList(getContent())); mCharactersCallback(mRequestId, LLPathfindingManager::kRequestCompleted, characterListPtr); } -void CharactersResponder::errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent) +void CharactersResponder::httpFailure() { - llwarns << "CharactersResponder error [status:" << pStatus << "]: " << pContent << llendl; + llwarns << dumpResponse() << llendl; LLPathfindingObjectListPtr characterListPtr = LLPathfindingObjectListPtr(new LLPathfindingCharacterList()); mCharactersCallback(mRequestId, LLPathfindingManager::kRequestError, characterListPtr); diff --git a/indra/newview/llpathfindingnavmesh.cpp b/indra/newview/llpathfindingnavmesh.cpp index 0c23e5ac92..555105cf40 100644 --- a/indra/newview/llpathfindingnavmesh.cpp +++ b/indra/newview/llpathfindingnavmesh.cpp @@ -184,10 +184,8 @@ void LLPathfindingNavMesh::handleNavMeshError() setRequestStatus(kNavMeshRequestError); } -void LLPathfindingNavMesh::handleNavMeshError(U32 pStatus, const std::string &pReason, const LLSD& pContent, const std::string &pURL, U32 pNavMeshVersion) +void LLPathfindingNavMesh::handleNavMeshError(U32 pNavMeshVersion) { - llwarns << "LLPathfindingNavMesh error with request to URL '" << pURL << "' [status:" - << pStatus << "]: " << pContent << llendl; if (mNavMeshStatus.getVersion() == pNavMeshVersion) { handleNavMeshError(); diff --git a/indra/newview/llpathfindingnavmesh.h b/indra/newview/llpathfindingnavmesh.h index b872ccad7c..87f32b8d56 100644 --- a/indra/newview/llpathfindingnavmesh.h +++ b/indra/newview/llpathfindingnavmesh.h @@ -74,7 +74,7 @@ public: void handleNavMeshResult(const LLSD &pContent, U32 pNavMeshVersion); void handleNavMeshNotEnabled(); void handleNavMeshError(); - void handleNavMeshError(U32 pStatus, const std::string &pReason, const LLSD& pContent, const std::string &pURL, U32 pNavMeshVersion); + void handleNavMeshError(U32 pNavMeshVersion); protected: diff --git a/indra/newview/llproductinforequest.cpp b/indra/newview/llproductinforequest.cpp index 1390000fc5..94a6389f8a 100644 --- a/indra/newview/llproductinforequest.cpp +++ b/indra/newview/llproductinforequest.cpp @@ -35,18 +35,24 @@ class LLProductInfoRequestResponder : public LLHTTPClient::Responder { -public: + LOG_CLASS(LLProductInfoRequestResponder); +private: //If we get back a normal response, handle it here - virtual void result(const LLSD& content) + /* virtual */ void httpSuccess() { - LLProductInfoRequestManager::instance().setSkuDescriptions(content); + const LLSD& content = getContent(); + if (!content.isArray()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } + LLProductInfoRequestManager::instance().setSkuDescriptions(getContent()); } //If we get back an error (not found, etc...), handle it here - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content) + /* virtual */ void httpFailure() { - llwarns << "LLProductInfoRequest error [status:" - << status << ":] " << content << llendl; + llwarns << dumpResponse() << llendl; } }; diff --git a/indra/newview/llremoteparcelrequest.cpp b/indra/newview/llremoteparcelrequest.cpp index 500dec7ee5..7418bbf615 100644 --- a/indra/newview/llremoteparcelrequest.cpp +++ b/indra/newview/llremoteparcelrequest.cpp @@ -47,9 +47,15 @@ LLRemoteParcelRequestResponder::LLRemoteParcelRequestResponder(LLHandle<LLRemote //If we get back a normal response, handle it here //virtual -void LLRemoteParcelRequestResponder::result(const LLSD& content) +void LLRemoteParcelRequestResponder::httpSuccess() { - LLUUID parcel_id = content["parcel_id"]; + const LLSD& content = getContent(); + if (!content.isMap() || !content.has("parcel_id")) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } + LLUUID parcel_id = getContent()["parcel_id"]; // Panel inspecting the information may be closed and destroyed // before this response is received. @@ -62,17 +68,16 @@ void LLRemoteParcelRequestResponder::result(const LLSD& content) //If we get back an error (not found, etc...), handle it here //virtual -void LLRemoteParcelRequestResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) +void LLRemoteParcelRequestResponder::httpFailure() { - llwarns << "LLRemoteParcelRequest error [status:" - << status << "]: " << content << llendl; + llwarns << dumpResponse() << llendl; // Panel inspecting the information may be closed and destroyed // before this response is received. LLRemoteParcelInfoObserver* observer = mObserverHandle.get(); if (observer) { - observer->setErrorStatus(status, reason); + observer->setErrorStatus(getStatus(), getReason()); } } diff --git a/indra/newview/llremoteparcelrequest.h b/indra/newview/llremoteparcelrequest.h index b87056573b..0f8ae41d76 100644 --- a/indra/newview/llremoteparcelrequest.h +++ b/indra/newview/llremoteparcelrequest.h @@ -37,16 +37,17 @@ class LLRemoteParcelInfoObserver; class LLRemoteParcelRequestResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLRemoteParcelRequestResponder); public: LLRemoteParcelRequestResponder(LLHandle<LLRemoteParcelInfoObserver> observer_handle); +private: //If we get back a normal response, handle it here - /*virtual*/ void result(const LLSD& content); + /*virtual*/ void httpSuccess(); //If we get back an error (not found, etc...), handle it here - /*virtual*/ void errorWithContent(U32 status, const std::string& reason, const LLSD& content); + /*virtual*/ void httpFailure(); -protected: LLHandle<LLRemoteParcelInfoObserver> mObserverHandle; }; @@ -78,7 +79,7 @@ public: virtual ~LLRemoteParcelInfoObserver() {} virtual void processParcelInfo(const LLParcelData& parcel_data) = 0; virtual void setParcelID(const LLUUID& parcel_id) = 0; - virtual void setErrorStatus(U32 status, const std::string& reason) = 0; + virtual void setErrorStatus(S32 status, const std::string& reason) = 0; LLHandle<LLRemoteParcelInfoObserver> getObserverHandle() const { return mObserverHandle; } protected: diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 890bc0f42d..1065b744b9 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -720,21 +720,23 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update) class ModerationResponder : public LLHTTPClient::Responder { + LOG_CLASS(ModerationResponder); public: ModerationResponder(const LLUUID& session_id) { mSessionID = session_id; } - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content) +protected: + virtual void httpFailure() { - llwarns << "ModerationResponder error [status:" << status << "]: " << content << llendl; + llwarns << dumpResponse() << llendl; if ( gIMMgr ) { //403 == you're not a mod //should be disabled if you're not a moderator - if ( 403 == status ) + if ( HTTP_FORBIDDEN == getStatus() ) { gIMMgr->showSessionEventError( "mute", diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 81bc70906d..d61a87c031 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -36,7 +36,7 @@ #include "lldir.h" #include "llhttpclient.h" -#include "llhttpstatuscodes.h" +#include "llhttpconstants.h" #include "llimage.h" #include "llimagej2c.h" #include "llimageworker.h" @@ -2350,9 +2350,10 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image mHttpRequest = new LLCore::HttpRequest; mHttpOptions = new LLCore::HttpOptions; mHttpHeaders = new LLCore::HttpHeaders; - mHttpHeaders->mHeaders.push_back("Accept: image/x-j2c"); + // *TODO: Should this be 'image/j2c' instead of 'image/x-j2c' ? + mHttpHeaders->mHeaders.push_back(HTTP_HEADER_ACCEPT + ": " + HTTP_CONTENT_IMAGE_X_J2C); mHttpMetricsHeaders = new LLCore::HttpHeaders; - mHttpMetricsHeaders->mHeaders.push_back("Content-Type: application/llsd+xml"); + mHttpMetricsHeaders->mHeaders.push_back(HTTP_HEADER_CONTENT_TYPE + ": " + HTTP_CONTENT_LLSD_XML); mHttpPolicyClass = LLAppViewer::instance()->getAppCoreHttp().getPolicyDefault(); } @@ -3950,7 +3951,8 @@ void LLTextureFetchDebugger::init() if (! mHttpHeaders) { mHttpHeaders = new LLCore::HttpHeaders; - mHttpHeaders->mHeaders.push_back("Accept: image/x-j2c"); + // *TODO: Should this be 'image/j2c' instead of 'image/x-j2c' ? + mHttpHeaders->mHeaders.push_back(HTTP_HEADER_ACCEPT + ": " + HTTP_CONTENT_IMAGE_X_J2C); } } diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp index f3d8de1904..b9840fa3e4 100755 --- a/indra/newview/lltranslate.cpp +++ b/indra/newview/lltranslate.cpp @@ -84,7 +84,7 @@ bool LLGoogleTranslationHandler::parseResponse( return false; } - if (status != STATUS_OK) + if (status != HTTP_OK) { // Request failed. Extract error message from the response. parseErrorResponse(root, status, err_msg); @@ -186,7 +186,7 @@ bool LLBingTranslationHandler::parseResponse( std::string& detected_lang, std::string& err_msg) const { - if (status != STATUS_OK) + if (status != HTTP_OK) { static const std::string MSG_BEGIN_MARKER = "Message: "; size_t begin = body.find(MSG_BEGIN_MARKER); @@ -251,8 +251,6 @@ LLTranslate::TranslationReceiver::TranslationReceiver(const std::string& from_la // virtual void LLTranslate::TranslationReceiver::completedRaw( - U32 http_status, - const std::string& reason, const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer) { @@ -262,8 +260,8 @@ void LLTranslate::TranslationReceiver::completedRaw( const std::string body = strstrm.str(); std::string translation, detected_lang, err_msg; - int status = http_status; - LL_DEBUGS("Translate") << "HTTP status: " << status << " " << reason << LL_ENDL; + int status = getStatus(); + LL_DEBUGS("Translate") << "HTTP status: " << status << " " << getReason() << LL_ENDL; LL_DEBUGS("Translate") << "Response body: " << body << LL_ENDL; if (mHandler.parseResponse(status, body, translation, detected_lang, err_msg)) { @@ -301,12 +299,10 @@ LLTranslate::EService LLTranslate::KeyVerificationReceiver::getService() const // virtual void LLTranslate::KeyVerificationReceiver::completedRaw( - U32 http_status, - const std::string& reason, const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer) { - bool ok = (http_status == 200); + bool ok = (getStatus() == HTTP_OK); setVerificationStatus(ok); } @@ -398,8 +394,8 @@ void LLTranslate::sendRequest(const std::string& url, LLHTTPClient::ResponderPtr LLVersionInfo::getPatch(), LLVersionInfo::getBuild()); - sHeader.insert("Accept", "text/plain"); - sHeader.insert("User-Agent", user_agent); + sHeader.insert(HTTP_HEADER_ACCEPT, HTTP_CONTENT_TEXT_PLAIN); + sHeader.insert(HTTP_HEADER_USER_AGENT, user_agent); } LLHTTPClient::get(url, responder, sHeader, REQUEST_TIMEOUT); diff --git a/indra/newview/lltranslate.h b/indra/newview/lltranslate.h index db5ad9479c..972274714a 100755 --- a/indra/newview/lltranslate.h +++ b/indra/newview/lltranslate.h @@ -95,9 +95,6 @@ public: virtual bool isConfigured() const = 0; virtual ~LLTranslationAPIHandler() {} - -protected: - static const int STATUS_OK = 200; }; /// Google Translate v2 API handler. @@ -201,8 +198,6 @@ public : * @see mHandler */ /*virtual*/ void completedRaw( - U32 http_status, - const std::string& reason, const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer); @@ -250,8 +245,6 @@ public : * @see setVerificationStatus() */ /*virtual*/ void completedRaw( - U32 http_status, - const std::string& reason, const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer); diff --git a/indra/newview/lluploadfloaterobservers.cpp b/indra/newview/lluploadfloaterobservers.cpp index 1d777b3f7f..88c48ba0a3 100644 --- a/indra/newview/lluploadfloaterobservers.cpp +++ b/indra/newview/lluploadfloaterobservers.cpp @@ -1,6 +1,6 @@ /** * @file lluploadfloaterobservers.cpp - * @brief LLUploadModelPremissionsResponder definition + * @brief LLUploadModelPermissionsResponder definition * * $LicenseInfo:firstyear=2011&license=viewerlgpl$ * Second Life Viewer Source Code @@ -28,26 +28,31 @@ #include "lluploadfloaterobservers.h" -LLUploadModelPremissionsResponder::LLUploadModelPremissionsResponder(const LLHandle<LLUploadPermissionsObserver>& observer) +LLUploadModelPermissionsResponder::LLUploadModelPermissionsResponder(const LLHandle<LLUploadPermissionsObserver>& observer) :mObserverHandle(observer) { } -void LLUploadModelPremissionsResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) +void LLUploadModelPermissionsResponder::httpFailure() { - llwarns << "LLUploadModelPremissionsResponder error [status:" - << status << "]: " << content << llendl; + llwarns << dumpResponse() << llendl; LLUploadPermissionsObserver* observer = mObserverHandle.get(); if (observer) { - observer->setPermissonsErrorStatus(status, reason); + observer->setPermissonsErrorStatus(getStatus(), getReason()); } } -void LLUploadModelPremissionsResponder::result(const LLSD& content) +void LLUploadModelPermissionsResponder::httpSuccess() { + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } LLUploadPermissionsObserver* observer = mObserverHandle.get(); if (observer) @@ -55,3 +60,4 @@ void LLUploadModelPremissionsResponder::result(const LLSD& content) observer->onPermissionsReceived(content); } } + diff --git a/indra/newview/lluploadfloaterobservers.h b/indra/newview/lluploadfloaterobservers.h index b43ddb44d9..4ff4a827a5 100644 --- a/indra/newview/lluploadfloaterobservers.h +++ b/indra/newview/lluploadfloaterobservers.h @@ -1,6 +1,6 @@ /** * @file lluploadfloaterobservers.h - * @brief LLUploadModelPremissionsResponder declaration + * @brief LLUploadModelPermissionsResponder declaration * * $LicenseInfo:firstyear=2011&license=viewerlgpl$ * Second Life Viewer Source Code @@ -39,7 +39,7 @@ public: virtual ~LLUploadPermissionsObserver() {} virtual void onPermissionsReceived(const LLSD& result) = 0; - virtual void setPermissonsErrorStatus(U32 status, const std::string& reason) = 0; + virtual void setPermissonsErrorStatus(S32 status, const std::string& reason) = 0; LLHandle<LLUploadPermissionsObserver> getPermObserverHandle() const {return mUploadPermObserverHandle;} @@ -54,7 +54,7 @@ public: virtual ~LLWholeModelFeeObserver() {} virtual void onModelPhysicsFeeReceived(const LLSD& result, std::string upload_url) = 0; - virtual void setModelPhysicsFeeErrorStatus(U32 status, const std::string& reason) = 0; + virtual void setModelPhysicsFeeErrorStatus(S32 status, const std::string& reason) = 0; LLHandle<LLWholeModelFeeObserver> getWholeModelFeeObserverHandle() const { return mWholeModelFeeObserverHandle; } @@ -80,17 +80,16 @@ protected: }; -class LLUploadModelPremissionsResponder : public LLHTTPClient::Responder +class LLUploadModelPermissionsResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLUploadModelPermissionsResponder); public: - - LLUploadModelPremissionsResponder(const LLHandle<LLUploadPermissionsObserver>& observer); - - void errorWithContent(U32 status, const std::string& reason, const LLSD& content); - - void result(const LLSD& content); + LLUploadModelPermissionsResponder(const LLHandle<LLUploadPermissionsObserver>& observer); private: + /* virtual */ void httpSuccess(); + /* virtual */ void httpFailure(); + LLHandle<LLUploadPermissionsObserver> mObserverHandle; }; diff --git a/indra/newview/llviewerdisplayname.cpp b/indra/newview/llviewerdisplayname.cpp index 1ac6a90894..07fceefde0 100644 --- a/indra/newview/llviewerdisplayname.cpp +++ b/indra/newview/llviewerdisplayname.cpp @@ -57,12 +57,12 @@ namespace LLViewerDisplayName class LLSetDisplayNameResponder : public LLHTTPClient::Responder { -public: + LOG_CLASS(LLSetDisplayNameResponder); +private: // only care about errors - /*virtual*/ void errorWithContent(U32 status, const std::string& reason, const LLSD& content) + /*virtual*/ void httpFailure() { - llwarns << "LLSetDisplayNameResponder error [status:" - << status << "]: " << content << llendl; + llwarns << dumpResponse() << llendl; LLViewerDisplayName::sSetDisplayNameSignal(false, "", LLSD()); LLViewerDisplayName::sSetDisplayNameSignal.disconnect_all_slots(); } @@ -85,7 +85,7 @@ void LLViewerDisplayName::set(const std::string& display_name, const set_name_sl // People API can return localized error messages. Indicate our // language preference via header. LLSD headers; - headers["Accept-Language"] = LLUI::getLanguage(); + headers[HTTP_HEADER_ACCEPT_LANGUAGE] = LLUI::getLanguage(); // People API requires both the old and new value to change a variable. // Our display name will be in cache before the viewer's UI is available @@ -127,7 +127,7 @@ public: LLSD body = input["body"]; S32 status = body["status"].asInteger(); - bool success = (status == 200); + bool success = (status == HTTP_OK); std::string reason = body["reason"].asString(); LLSD content = body["content"]; @@ -136,7 +136,7 @@ public: // If viewer's concept of display name is out-of-date, the set request // will fail with 409 Conflict. If that happens, fetch up-to-date // name information. - if (status == 409) + if (status == HTTP_CONFLICT) { LLUUID agent_id = gAgent.getID(); // Flush stale data diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 2df028de69..8c29a03176 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -158,7 +158,7 @@ LLViewerMediaObserver::~LLViewerMediaObserver() // on the Panel Land Media and to discover the MIME type class LLMimeDiscoveryResponder : public LLHTTPClient::Responder { -LOG_CLASS(LLMimeDiscoveryResponder); + LOG_CLASS(LLMimeDiscoveryResponder); public: LLMimeDiscoveryResponder( viewer_media_t media_impl) : mMediaImpl(media_impl), @@ -177,13 +177,20 @@ public: disconnectOwner(); } - virtual void completedHeader(U32 status, const std::string& reason, const LLSD& content) +private: + /* virtual */ void httpCompleted() { - std::string media_type = content["content-type"].asString(); + if (!isGoodStatus()) + { + llwarns << dumpResponse() + << " [headers:" << getResponseHeaders() << "]" << llendl; + } + const bool check_lower = true; + const std::string& media_type = getResponseHeader(HTTP_HEADER_CONTENT_TYPE, check_lower); std::string::size_type idx1 = media_type.find_first_of(";"); std::string mime_type = media_type.substr(0, idx1); - lldebugs << "status is " << status << ", media type \"" << media_type << "\"" << llendl; + lldebugs << "status is " << getStatus() << ", media type \"" << media_type << "\"" << llendl; // 2xx status codes indicate success. // Most 4xx status codes are successful enough for our purposes. @@ -200,32 +207,27 @@ public: // ) // We now no longer check the error code returned from the probe. // If we have a mime type, use it. If not, default to the web plugin and let it handle error reporting. - if(1) + //if(1) { // The probe was successful. if(mime_type.empty()) { // Some sites don't return any content-type header at all. // Treat an empty mime type as text/html. - mime_type = "text/html"; + mime_type = HTTP_CONTENT_TEXT_HTML; } - - completeAny(status, mime_type); } - else - { - llwarns << "responder failed with status " << status << ", reason " << reason << llendl; - - if(mMediaImpl) - { - mMediaImpl->mMediaSourceFailed = true; - } - } - - } + //else + //{ + // llwarns << "responder failed with status " << dumpResponse() << llendl; + // + // if(mMediaImpl) + // { + // mMediaImpl->mMediaSourceFailed = true; + // } + // return; + //} - void completeAny(U32 status, const std::string& mime_type) - { // the call to initializeMedia may disconnect the responder, which will clear mMediaImpl. // Make a local copy so we can call loadURI() afterwards. LLViewerMediaImpl *impl = mMediaImpl; @@ -241,6 +243,7 @@ public: } } +public: void cancelRequest() { disconnectOwner(); @@ -269,7 +272,7 @@ public: class LLViewerMediaOpenIDResponder : public LLHTTPClient::Responder { -LOG_CLASS(LLViewerMediaOpenIDResponder); + LOG_CLASS(LLViewerMediaOpenIDResponder); public: LLViewerMediaOpenIDResponder( ) { @@ -279,23 +282,18 @@ public: { } - /* virtual */ void completedHeader(U32 status, const std::string& reason, const LLSD& content) - { - LL_DEBUGS("MediaAuth") << "status = " << status << ", reason = " << reason << LL_ENDL; - LL_DEBUGS("MediaAuth") << content << LL_ENDL; - std::string cookie = content["set-cookie"].asString(); - - LLViewerMedia::openIDCookieResponse(cookie); - } - /* virtual */ void completedRaw( - U32 status, - const std::string& reason, const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer) { - // This is just here to disable the default behavior (attempting to parse the response as llsd). - // We don't care about the content of the response, only the set-cookie header. + // We don't care about the content of the response, only the Set-Cookie header. + LL_DEBUGS("MediaAuth") << dumpResponse() + << " [headers:" << getResponseHeaders() << "]" << LL_ENDL; + const bool check_lower = true; + const std::string& cookie = getResponseHeader(HTTP_HEADER_SET_COOKIE, check_lower); + + // *TODO: What about bad status codes? Does this destroy previous cookies? + LLViewerMedia::openIDCookieResponse(cookie); } }; @@ -313,17 +311,25 @@ public: { } - /* virtual */ void completedHeader(U32 status, const std::string& reason, const LLSD& content) + void completedRaw( + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) { - LL_WARNS("MediaAuth") << "status = " << status << ", reason = " << reason << LL_ENDL; + // We don't care about the content of the response, only the set-cookie header. + LL_WARNS("MediaAuth") << dumpResponse() + << " [headers:" << getResponseHeaders() << "]" << LL_ENDL; - LLSD stripped_content = content; + LLSD stripped_content = getResponseHeaders(); + // *TODO: Check that this works. + stripped_content.erase(HTTP_HEADER_SET_COOKIE); stripped_content.erase("set-cookie"); LL_WARNS("MediaAuth") << stripped_content << LL_ENDL; - std::string cookie = content["set-cookie"].asString(); + const bool check_lower = true; + const std::string& cookie = getResponseHeader(HTTP_HEADER_SET_COOKIE, check_lower); LL_DEBUGS("MediaAuth") << "cookie = " << cookie << LL_ENDL; + // *TODO: What about bad status codes? Does this destroy previous cookies? LLViewerMedia::getCookieStore()->setCookiesFromHost(cookie, mHost); // Set cookie for snapshot publishing. @@ -331,16 +337,6 @@ public: LLWebProfile::setAuthCookie(auth_cookie); } - void completedRaw( - U32 status, - const std::string& reason, - const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer) - { - // This is just here to disable the default behavior (attempting to parse the response as llsd). - // We don't care about the content of the response, only the set-cookie header. - } - std::string mHost; }; @@ -1387,10 +1383,12 @@ void LLViewerMedia::removeCookie(const std::string &name, const std::string &dom LLSD LLViewerMedia::getHeaders() { LLSD headers = LLSD::emptyMap(); - headers["Accept"] = "*/*"; - headers["Content-Type"] = "application/xml"; - headers["Cookie"] = sOpenIDCookie; - headers["User-Agent"] = getCurrentUserAgent(); + headers[HTTP_HEADER_ACCEPT] = "*/*"; + // *TODO: Should this be 'application/llsd+xml' ? + // *TODO: Should this even be set at all? This header is only not overridden in 'GET' methods. + headers[HTTP_HEADER_CONTENT_TYPE] = HTTP_CONTENT_XML; + headers[HTTP_HEADER_COOKIE] = sOpenIDCookie; + headers[HTTP_HEADER_USER_AGENT] = getCurrentUserAgent(); return headers; } @@ -1431,9 +1429,9 @@ void LLViewerMedia::setOpenIDCookie() // Do a web profile get so we can store the cookie LLSD headers = LLSD::emptyMap(); - headers["Accept"] = "*/*"; - headers["Cookie"] = sOpenIDCookie; - headers["User-Agent"] = getCurrentUserAgent(); + headers[HTTP_HEADER_ACCEPT] = "*/*"; + headers[HTTP_HEADER_COOKIE] = sOpenIDCookie; + headers[HTTP_HEADER_USER_AGENT] = getCurrentUserAgent(); std::string profile_url = getProfileURL(""); LLURL raw_profile_url( profile_url.c_str() ); @@ -1463,9 +1461,9 @@ void LLViewerMedia::openIDSetup(const std::string &openid_url, const std::string LLSD headers = LLSD::emptyMap(); // Keep LLHTTPClient from adding an "Accept: application/llsd+xml" header - headers["Accept"] = "*/*"; + headers[HTTP_HEADER_ACCEPT] = "*/*"; // and use the expected content-type for a post, instead of the LLHTTPClient::postRaw() default of "application/octet-stream" - headers["Content-Type"] = "application/x-www-form-urlencoded"; + headers[HTTP_HEADER_CONTENT_TYPE] = "application/x-www-form-urlencoded"; // postRaw() takes ownership of the buffer and releases it later, so we need to allocate a new buffer here. size_t size = openid_token.size(); @@ -1537,7 +1535,7 @@ void LLViewerMedia::createSpareBrowserMediaSource() // The null owner will keep the browser plugin from fully initializing // (specifically, it keeps LLPluginClassMedia from negotiating a size change, // which keeps MediaPluginWebkit::initBrowserWindow from doing anything until we have some necessary data, like the background color) - sSpareBrowserMediaSource = LLViewerMediaImpl::newSourceFromMediaType("text/html", NULL, 0, 0); + sSpareBrowserMediaSource = LLViewerMediaImpl::newSourceFromMediaType(HTTP_CONTENT_TEXT_HTML, NULL, 0, 0); } } @@ -2633,16 +2631,16 @@ void LLViewerMediaImpl::navigateInternal() // Accept: application/llsd+xml // which is really not what we want. LLSD headers = LLSD::emptyMap(); - headers["Accept"] = "*/*"; + headers[HTTP_HEADER_ACCEPT] = "*/*"; // Allow cookies in the response, to prevent a redirect loop when accessing join.secondlife.com - headers["Cookie"] = ""; + headers[HTTP_HEADER_COOKIE] = ""; LLHTTPClient::getHeaderOnly( mMediaURL, new LLMimeDiscoveryResponder(this), headers, 10.0f); } else if("data" == scheme || "file" == scheme || "about" == scheme) { // FIXME: figure out how to really discover the type for these schemes // We use "data" internally for a text/html url for loading the login screen - if(initializeMedia("text/html")) + if(initializeMedia(HTTP_CONTENT_TEXT_HTML)) { loadURI(); } diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 0561e731e7..576b801d5b 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -671,6 +671,7 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent) class LLObjectCostResponder : public LLCurl::Responder { + LOG_CLASS(LLObjectCostResponder); public: LLObjectCostResponder(const LLSD& object_ids) : mObjectIDs(object_ids) @@ -691,20 +692,19 @@ public: } } - void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) +private: + /* virtual */ void httpFailure() { - llwarns - << "Transport error requesting object cost " - << "[status: " << statusNum << "]: " - << content << llendl; + llwarns << dumpResponse() << llendl; // TODO*: Error message to user // For now just clear the request from the pending list clear_object_list_pending_requests(); } - void result(const LLSD& content) + /* virtual */ void httpSuccess() { + const LLSD& content = getContent(); if ( !content.isMap() || content.has("error") ) { // Improper response or the request had an error, @@ -760,6 +760,7 @@ private: class LLPhysicsFlagsResponder : public LLCurl::Responder { + LOG_CLASS(LLPhysicsFlagsResponder); public: LLPhysicsFlagsResponder(const LLSD& object_ids) : mObjectIDs(object_ids) @@ -780,20 +781,19 @@ public: } } - void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) +private: + /* virtual */ void httpFailure() { - llwarns - << "Transport error requesting object physics flags " - << "[status: " << statusNum << "]: " - << content << llendl; + llwarns << dumpResponse() << llendl; // TODO*: Error message to user // For now just clear the request from the pending list clear_object_list_pending_requests(); } - void result(const LLSD& content) + /* virtual void */ void httpSuccess() { + const LLSD& content = getContent(); if ( !content.isMap() || content.has("error") ) { // Improper response or the request had an error, diff --git a/indra/newview/llviewerparcelmedia.cpp b/indra/newview/llviewerparcelmedia.cpp index 386b2fd400..d7e14ac6f5 100644 --- a/indra/newview/llviewerparcelmedia.cpp +++ b/indra/newview/llviewerparcelmedia.cpp @@ -99,7 +99,7 @@ void LLViewerParcelMedia::update(LLParcel* parcel) std::string mediaCurrentUrl = std::string( parcel->getMediaCurrentURL()); // if we have a current (link sharing) url, use it instead - if (mediaCurrentUrl != "" && parcel->getMediaType() == "text/html") + if (mediaCurrentUrl != "" && parcel->getMediaType() == HTTP_CONTENT_TEXT_HTML) { mediaUrl = mediaCurrentUrl; } diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index b8b53aa6e4..2286bb09e1 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -204,24 +204,30 @@ class BaseCapabilitiesComplete : public LLHTTPClient::Responder { LOG_CLASS(BaseCapabilitiesComplete); public: - BaseCapabilitiesComplete(U64 region_handle, S32 id) + BaseCapabilitiesComplete(U64 region_handle, S32 id) : mRegionHandle(region_handle), mID(id) - { } + { } virtual ~BaseCapabilitiesComplete() { } - void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) - { - LL_WARNS2("AppInit", "Capabilities") << "[status:" << statusNum << ":] " << content << LL_ENDL; + static BaseCapabilitiesComplete* build( U64 region_handle, S32 id ) + { + return new BaseCapabilitiesComplete(region_handle, id); + } + +private: + /* virtual */void httpFailure() + { + LL_WARNS2("AppInit", "Capabilities") << dumpResponse() << LL_ENDL; LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); if (regionp) { regionp->failedSeedCapability(); } - } + } - void result(const LLSD& content) - { + /* virtual */ void httpSuccess() + { LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); if(!regionp) //region was removed { @@ -234,11 +240,17 @@ public: return ; } + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } LLSD::map_const_iterator iter; for(iter = content.beginMap(); iter != content.endMap(); ++iter) { regionp->setCapability(iter->first, iter->second); - + LL_DEBUGS2("AppInit", "Capabilities") << "got capability for " << iter->first << LL_ENDL; @@ -257,11 +269,6 @@ public: } } - static BaseCapabilitiesComplete* build( U64 region_handle, S32 id ) - { - return new BaseCapabilitiesComplete(region_handle, id); - } - private: U64 mRegionHandle; S32 mID; @@ -278,19 +285,32 @@ public: virtual ~BaseCapabilitiesCompleteTracker() { } - void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) + static BaseCapabilitiesCompleteTracker* build( U64 region_handle ) + { + return new BaseCapabilitiesCompleteTracker( region_handle ); + } + +private: + /* virtual */ void httpFailure() { - llwarns << "BaseCapabilitiesCompleteTracker error [status:" - << statusNum << "]: " << content << llendl; + llwarns << dumpResponse() << llendl; } - void result(const LLSD& content) + /* virtual */ void httpSuccess() { LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); if( !regionp ) { + LL_WARNS2("AppInit", "Capabilities") << "Received results for region that no longer exists!" << LL_ENDL; return ; - } + } + + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } LLSD::map_const_iterator iter; for(iter = content.beginMap(); iter != content.endMap(); ++iter) { @@ -300,7 +320,8 @@ public: if ( regionp->getRegionImpl()->mCapabilities.size() != regionp->getRegionImpl()->mSecondCapabilitiesTracker.size() ) { - llinfos<<"BaseCapabilitiesCompleteTracker "<<"Sim sent duplicate seed caps that differs in size - most likely content."<<llendl; + LL_WARNS2("AppInit", "Capabilities") + << "Sim sent duplicate seed caps that differs in size - most likely content." << LL_ENDL; //todo#add cap debug versus original check? /*CapabilityMap::const_iterator iter = regionp->getRegionImpl()->mCapabilities.begin(); while (iter!=regionp->getRegionImpl()->mCapabilities.end() ) @@ -311,16 +332,11 @@ public: */ regionp->getRegionImplNC()->mSecondCapabilitiesTracker.clear(); } - } - static BaseCapabilitiesCompleteTracker* build( U64 region_handle ) - { - return new BaseCapabilitiesCompleteTracker( region_handle ); - } private: - U64 mRegionHandle; + U64 mRegionHandle; }; @@ -1728,31 +1744,37 @@ class SimulatorFeaturesReceived : public LLHTTPClient::Responder { LOG_CLASS(SimulatorFeaturesReceived); public: - SimulatorFeaturesReceived(const std::string& retry_url, U64 region_handle, + SimulatorFeaturesReceived(const std::string& retry_url, U64 region_handle, S32 attempt = 0, S32 max_attempts = MAX_CAP_REQUEST_ATTEMPTS) - : mRetryURL(retry_url), mRegionHandle(region_handle), mAttempt(attempt), mMaxAttempts(max_attempts) - { } - - - void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) - { - LL_WARNS2("AppInit", "SimulatorFeatures") << "[status:" << statusNum << "]: " << content << LL_ENDL; + : mRetryURL(retry_url), mRegionHandle(region_handle), mAttempt(attempt), mMaxAttempts(max_attempts) + { } + +private: + /* virtual */ void httpFailure() + { + LL_WARNS2("AppInit", "SimulatorFeatures") << dumpResponse() << LL_ENDL; retry(); - } + } - void result(const LLSD& content) - { + /* virtual */ void httpSuccess() + { LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); if(!regionp) //region is removed or responder is not created. { - LL_WARNS2("AppInit", "SimulatorFeatures") << "Received results for region that no longer exists!" << LL_ENDL; + LL_WARNS2("AppInit", "SimulatorFeatures") + << "Received results for region that no longer exists!" << LL_ENDL; return ; } - + + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } regionp->setSimulatorFeatures(content); } -private: void retry() { if (mAttempt < mMaxAttempts) @@ -1762,7 +1784,7 @@ private: LLHTTPClient::get(mRetryURL, new SimulatorFeaturesReceived(*this), LLSD(), CAP_REQUEST_TIMEOUT); } } - + std::string mRetryURL; U64 mRegionHandle; S32 mAttempt; diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index 4ed01f36ab..a9256ed5ea 100755 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -527,18 +527,19 @@ void update_statistics() class ViewerStatsResponder : public LLHTTPClient::Responder { + LOG_CLASS(ViewerStatsResponder); public: - ViewerStatsResponder() { } + ViewerStatsResponder() { } - void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) - { - llwarns << "ViewerStatsResponder error [status:" << statusNum << "]: " - << content << llendl; - } +private: + /* virtual */ void httpFailure() + { + llwarns << dumpResponse() << llendl; + } - void result(const LLSD& content) - { - llinfos << "ViewerStatsResponder::result" << llendl; + /* virtual */ void httpSuccess() + { + llinfos << "OK" << llendl; } }; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index a98e9ce511..7e95263f4b 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1914,7 +1914,7 @@ void LLViewerWindow::initWorldUI() destinations->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL")); std::string url = gSavedSettings.getString("DestinationGuideURL"); url = LLWeb::expandURLSubstitutions(url, LLSD()); - destinations->navigateTo(url, "text/html"); + destinations->navigateTo(url, HTTP_CONTENT_TEXT_HTML); } LLMediaCtrl* avatar_picker = LLFloaterReg::getInstance("avatar")->findChild<LLMediaCtrl>("avatar_picker_contents"); if (avatar_picker) @@ -1922,7 +1922,7 @@ void LLViewerWindow::initWorldUI() avatar_picker->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL")); std::string url = gSavedSettings.getString("AvatarPickerURL"); url = LLWeb::expandURLSubstitutions(url, LLSD()); - avatar_picker->navigateTo(url, "text/html"); + avatar_picker->navigateTo(url, HTTP_CONTENT_TEXT_HTML); } } diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 9be1de4f0e..81454f5da4 100755 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -2241,6 +2241,7 @@ LLSD LLVOAvatarSelf::metricsData() class ViewerAppearanceChangeMetricsResponder: public LLCurl::Responder { + LOG_CLASS(ViewerAppearanceChangeMetricsResponder); public: ViewerAppearanceChangeMetricsResponder( S32 expected_sequence, volatile const S32 & live_sequence, @@ -2251,32 +2252,25 @@ public: { } - virtual void completed(U32 status, - const std::string& reason, - const LLSD& content) +private: + /* virtual */ void httpSuccess() { - gPendingMetricsUploads--; // if we add retry, this should be moved to the isGoodStatus case. - if (isGoodStatus(status)) - { - LL_DEBUGS("Avatar") << "OK" << LL_ENDL; - result(content); - } - else - { - LL_WARNS("Avatar") << "Failed " << status << " reason " << reason << LL_ENDL; - errorWithContent(status,reason,content); - } - } + LL_DEBUGS("Avatar") << "OK" << LL_ENDL; - // virtual - void result(const LLSD & content) - { + gPendingMetricsUploads--; if (mLiveSequence == mExpectedSequence) { mReportingStarted = true; } } + /* virtual */ void httpFailure() + { + // if we add retry, this should be removed from the httpFailure case + LL_WARNS("Avatar") << dumpResponse() << LL_ENDL; + gPendingMetricsUploads--; + } + private: S32 mExpectedSequence; volatile const S32 & mLiveSequence; @@ -2425,6 +2419,7 @@ void LLVOAvatarSelf::sendViewerAppearanceChangeMetrics() class CheckAgentAppearanceServiceResponder: public LLHTTPClient::Responder { + LOG_CLASS(CheckAgentAppearanceServiceResponder); public: CheckAgentAppearanceServiceResponder() { @@ -2434,22 +2429,24 @@ public: { } - /* virtual */ void result(const LLSD& content) +private: + /* virtual */ void httpSuccess() { - LL_DEBUGS("Avatar") << "status OK" << llendl; + LL_DEBUGS("Avatar") << "OK" << llendl; } // Error - /*virtual*/ void errorWithContent(U32 status, const std::string& reason, const LLSD& content) + /*virtual*/ void httpFailure() { if (isAgentAvatarValid()) { - LL_DEBUGS("Avatar") << "failed, will rebake [status:" - << status << "]: " << content << llendl; + LL_DEBUGS("Avatar") << "failed, will rebake " + << dumpResponse() << LL_ENDL; forceAppearanceUpdate(); } - } + } +public: static void forceAppearanceUpdate() { // Trying to rebake immediately after crossing region boundary diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp index 181735ee30..be836d7752 100644 --- a/indra/newview/llvoicechannel.cpp +++ b/indra/newview/llvoicechannel.cpp @@ -53,26 +53,27 @@ const U32 DEFAULT_RETRIES_COUNT = 3; class LLVoiceCallCapResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLVoiceCallCapResponder); public: LLVoiceCallCapResponder(const LLUUID& session_id) : mSessionID(session_id) {}; +protected: // called with bad status codes - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content); - virtual void result(const LLSD& content); + virtual void httpFailure(); + virtual void httpSuccess(); private: LLUUID mSessionID; }; -void LLVoiceCallCapResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) +void LLVoiceCallCapResponder::httpFailure() { - LL_WARNS("Voice") << "LLVoiceCallCapResponder error [status:" - << status << "]: " << content << LL_ENDL; + LL_WARNS("Voice") << dumpResponse() << LL_ENDL; LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID); if ( channelp ) { - if ( 403 == status ) + if ( HTTP_FORBIDDEN == getStatus() ) { //403 == no ability LLNotificationsUtil::add( @@ -89,12 +90,18 @@ void LLVoiceCallCapResponder::errorWithContent(U32 status, const std::string& re } } -void LLVoiceCallCapResponder::result(const LLSD& content) +void LLVoiceCallCapResponder::httpSuccess() { LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID); if (channelp) { //*TODO: DEBUG SPAM + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } LLSD::map_const_iterator iter; for(iter = content.beginMap(); iter != content.endMap(); ++iter) { diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index e112c589e9..360f8f15a3 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -120,17 +120,19 @@ static int scale_speaker_volume(float volume) class LLVivoxVoiceAccountProvisionResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLVivoxVoiceAccountProvisionResponder); public: LLVivoxVoiceAccountProvisionResponder(int retries) { mRetries = retries; } - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content) +private: + /* virtual */ void httpFailure() { LL_WARNS("Voice") << "ProvisionVoiceAccountRequest returned an error, " << ( (mRetries > 0) ? "retrying" : "too many retries (giving up)" ) - << status << "]: " << content << LL_ENDL; + << " " << dumpResponse() << LL_ENDL; if ( mRetries > 0 ) { @@ -142,14 +144,19 @@ public: } } - virtual void result(const LLSD& content) + /* virtual */ void httpSuccess() { - std::string voice_sip_uri_hostname; std::string voice_account_server_uri; - LL_DEBUGS("Voice") << "ProvisionVoiceAccountRequest response:" << ll_pretty_print_sd(content) << LL_ENDL; + LL_DEBUGS("Voice") << "ProvisionVoiceAccountRequest response:" << dumpResponse() << LL_ENDL; + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } if(content.has("voice_sip_uri_hostname")) voice_sip_uri_hostname = content["voice_sip_uri_hostname"].asString(); @@ -162,7 +169,6 @@ public: content["password"].asString(), voice_sip_uri_hostname, voice_account_server_uri); - } private: @@ -193,33 +199,34 @@ static LLVivoxVoiceClientFriendsObserver *friendslist_listener = NULL; class LLVivoxVoiceClientCapResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLVivoxVoiceClientCapResponder); public: LLVivoxVoiceClientCapResponder(LLVivoxVoiceClient::state requesting_state) : mRequestingState(requesting_state) {}; +private: // called with bad status codes - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content); - virtual void result(const LLSD& content); + /* virtual */ void httpFailure(); + /* virtual */ void httpSuccess(); -private: LLVivoxVoiceClient::state mRequestingState; // state }; -void LLVivoxVoiceClientCapResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) +void LLVivoxVoiceClientCapResponder::httpFailure() { - LL_WARNS("Voice") << "LLVivoxVoiceClientCapResponder error [status:" - << status << "]: " << content << LL_ENDL; + LL_WARNS("Voice") << dumpResponse() << LL_ENDL; LLVivoxVoiceClient::getInstance()->sessionTerminate(); } -void LLVivoxVoiceClientCapResponder::result(const LLSD& content) +void LLVivoxVoiceClientCapResponder::httpSuccess() { LLSD::map_const_iterator iter; - LL_DEBUGS("Voice") << "ParcelVoiceInfoRequest response:" << ll_pretty_print_sd(content) << LL_ENDL; + LL_DEBUGS("Voice") << "ParcelVoiceInfoRequest response:" << dumpResponse() << LL_ENDL; std::string uri; std::string credentials; + const LLSD& content = getContent(); if ( content.has("voice_credentials") ) { LLSD voice_credentials = content["voice_credentials"]; @@ -2982,7 +2989,7 @@ void LLVivoxVoiceClient::loginResponse(int statusCode, std::string &statusString // Status code of 20200 means "bad password". We may want to special-case that at some point. - if ( statusCode == 401 ) + if ( statusCode == HTTP_UNAUTHORIZED ) { // Login failure which is probably caused by the delay after a user's password being updated. LL_INFOS("Voice") << "Account.Login response failure (" << statusCode << "): " << statusString << LL_ENDL; @@ -3484,7 +3491,7 @@ void LLVivoxVoiceClient::mediaStreamUpdatedEvent( switch(statusCode) { case 0: - case 200: + case HTTP_OK: // generic success // Don't change the saved error code (it may have been set elsewhere) break; @@ -3835,7 +3842,7 @@ void LLVivoxVoiceClient::messageEvent( LL_DEBUGS("Voice") << "Message event, session " << sessionHandle << " from " << uriString << LL_ENDL; // LL_DEBUGS("Voice") << " header " << messageHeader << ", body: \n" << messageBody << LL_ENDL; - if(messageHeader.find("text/html") != std::string::npos) + if(messageHeader.find(HTTP_CONTENT_TEXT_HTML) != std::string::npos) { std::string message; @@ -6119,9 +6126,10 @@ void LLVivoxVoiceClient::notifyStatusObservers(LLVoiceClientStatusObserver::ESta { switch(mAudioSession->mErrorStatusCode) { - case 404: // NOT_FOUND + case HTTP_NOT_FOUND: // NOT_FOUND + // *TODO: Should this be 503? case 480: // TEMPORARILY_UNAVAILABLE - case 408: // REQUEST_TIMEOUT + case HTTP_REQUEST_TIME_OUT: // REQUEST_TIMEOUT // call failed because other user was not available // treat this as an error case status = LLVoiceClientStatusObserver::ERROR_NOT_AVAILABLE; diff --git a/indra/newview/llwebprofile.cpp b/indra/newview/llwebprofile.cpp index 641f338f2c..ee78ba20cb 100644 --- a/indra/newview/llwebprofile.cpp +++ b/indra/newview/llwebprofile.cpp @@ -67,9 +67,8 @@ public: { } + // *TODO: Check for 'application/json' content type, and parse json at the base class. /*virtual*/ void completedRaw( - U32 status, - const std::string& reason, const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer) { @@ -78,9 +77,9 @@ public: strstrm << istr.rdbuf(); const std::string body = strstrm.str(); - if (status != 200) + if (getStatus() != HTTP_OK) { - llwarns << "Failed to get upload config (" << status << ")" << llendl; + llwarns << "Failed to get upload config " << dumpResponse() << llendl; LLWebProfile::reportImageUploadStatus(false); return; } @@ -128,14 +127,12 @@ class LLWebProfileResponders::PostImageRedirectResponder : public LLHTTPClient:: public: /*virtual*/ void completedRaw( - U32 status, - const std::string& reason, const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer) { - if (status != 200) + if (getStatus() != HTTP_OK) { - llwarns << "Failed to upload image: " << status << " " << reason << llendl; + llwarns << "Failed to upload image " << dumpResponse() << llendl; LLWebProfile::reportImageUploadStatus(false); return; } @@ -161,33 +158,37 @@ class LLWebProfileResponders::PostImageResponder : public LLHTTPClient::Responde LOG_CLASS(LLWebProfileResponders::PostImageResponder); public: - /*virtual*/ void completedHeader(U32 status, const std::string& reason, const LLSD& content) + /*virtual*/ void completedRaw(const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) { // Viewer seems to fail to follow a 303 redirect on POST request // (URLRequest Error: 65, Send failed since rewinding of the data stream failed). // Handle it manually. - if (status == 303) + if (getStatus() == HTTP_SEE_OTHER) { LLSD headers = LLViewerMedia::getHeaders(); - headers["Cookie"] = LLWebProfile::getAuthCookie(); - const std::string& redir_url = content["location"]; - LL_DEBUGS("Snapshots") << "Got redirection URL: " << redir_url << llendl; - LLHTTPClient::get(redir_url, new LLWebProfileResponders::PostImageRedirectResponder, headers); + headers[HTTP_HEADER_COOKIE] = LLWebProfile::getAuthCookie(); + const bool check_lower=true; + const std::string& redir_url = getResponseHeader(HTTP_HEADER_LOCATION, check_lower); + if (redir_url.empty()) + { + llwarns << "Received empty redirection URL " << dumpResponse() << llendl; + LL_DEBUGS("Snapshots") << "[headers:" << getResponseHeaders() << "]" << LL_ENDL; + LLWebProfile::reportImageUploadStatus(false); + } + else + { + LL_DEBUGS("Snapshots") << "Got redirection URL: " << redir_url << llendl; + LLHTTPClient::get(redir_url, new LLWebProfileResponders::PostImageRedirectResponder, headers); + } } else { - llwarns << "Unexpected POST status: " << status << " " << reason << llendl; - LL_DEBUGS("Snapshots") << "headers: [" << content << "]" << llendl; + llwarns << "Unexpected POST response " << dumpResponse() << llendl; + LL_DEBUGS("Snapshots") << "[headers:" << getResponseHeaders() << "]" << LL_ENDL; LLWebProfile::reportImageUploadStatus(false); } } - - // Override just to suppress warnings. - /*virtual*/ void completedRaw(U32 status, const std::string& reason, - const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer) - { - } }; /////////////////////////////////////////////////////////////////////////////// @@ -206,7 +207,7 @@ void LLWebProfile::uploadImage(LLPointer<LLImageFormatted> image, const std::str LL_DEBUGS("Snapshots") << "Requesting " << config_url << llendl; LLSD headers = LLViewerMedia::getHeaders(); - headers["Cookie"] = getAuthCookie(); + headers[HTTP_HEADER_COOKIE] = getAuthCookie(); LLHTTPClient::get(config_url, new LLWebProfileResponders::ConfigResponder(image), headers); } @@ -230,8 +231,8 @@ void LLWebProfile::post(LLPointer<LLImageFormatted> image, const LLSD& config, c const std::string boundary = "----------------------------0123abcdefab"; LLSD headers = LLViewerMedia::getHeaders(); - headers["Cookie"] = getAuthCookie(); - headers["Content-Type"] = "multipart/form-data; boundary=" + boundary; + headers[HTTP_HEADER_COOKIE] = getAuthCookie(); + headers[HTTP_HEADER_CONTENT_TYPE] = "multipart/form-data; boundary=" + boundary; std::ostringstream body; diff --git a/indra/newview/llwebsharing.cpp b/indra/newview/llwebsharing.cpp index 3a80051b9b..ba536ac582 100644 --- a/indra/newview/llwebsharing.cpp +++ b/indra/newview/llwebsharing.cpp @@ -32,7 +32,7 @@ #include "llagentui.h" #include "llbufferstream.h" #include "llhttpclient.h" -#include "llhttpstatuscodes.h" +#include "llhttpconstants.h" #include "llsdserialize.h" #include "llsdutil.h" #include "llurl.h" @@ -45,36 +45,57 @@ /////////////////////////////////////////////////////////////////////////////// // -class LLWebSharingConfigResponder : public LLHTTPClient::Responder + +class LLWebSharingJSONResponder : public LLHTTPClient::Responder { - LOG_CLASS(LLWebSharingConfigResponder); + LOG_CLASS(LLWebSharingJSONResponder); public: /// Overrides the default LLSD parsing behaviour, to allow parsing a JSON response. - virtual void completedRaw(U32 status, const std::string& reason, - const LLChannelDescriptors& channels, + virtual void completedRaw(const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer) { - LLSD content; LLBufferStream istr(channels, buffer.get()); LLPointer<LLSDParser> parser = new LLSDNotationParser(); - if (parser->parse(istr, content, LLSDSerialize::SIZE_UNLIMITED) == LLSDParser::PARSE_FAILURE) - { - LL_WARNS("WebSharing") << "Failed to deserialize LLSD from JSON response. " << " [" << status << "]: " << reason << LL_ENDL; - } - else + if (parser->parse(istr, mContent, LLSDSerialize::SIZE_UNLIMITED) == LLSDParser::PARSE_FAILURE) { - completed(status, reason, content); + if (HTTP_CONTENT_JSON == getResponseHeader(HTTP_HEADER_CONTENT_TYPE)) + { + mStatus = HTTP_INTERNAL_ERROR; + mReason = "Failed to deserialize LLSD from JSON response."; + char body[1025]; + body[1024] = '\0'; + istr.seekg(0, std::ios::beg); + istr.get(body,1024); + if (strlen(body) > 0) + { + mContent["body"] = body; + } + } } + + httpCompleted(); } +}; + +class LLWebSharingConfigResponder : public LLWebSharingJSONResponder +{ + LOG_CLASS(LLWebSharingConfigResponder); +private: - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content) + virtual void httpFailure() { - LL_WARNS("WebSharing") << "Error [status:" << status << "]: " << content << LL_ENDL; + LL_WARNS("WebSharing") << dumpResponse() << LL_ENDL; } - virtual void result(const LLSD& content) + virtual void httpSuccess() { + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } LLWebSharing::instance().receiveConfig(content); } }; @@ -87,39 +108,35 @@ class LLWebSharingOpenIDAuthResponder : public LLHTTPClient::Responder { LOG_CLASS(LLWebSharingOpenIDAuthResponder); public: - /* virtual */ void completedHeader(U32 status, const std::string& reason, const LLSD& content) - { - completed(status, reason, content); - } - - /* virtual */ void completedRaw(U32 status, const std::string& reason, - const LLChannelDescriptors& channels, + /* virtual */ void completedRaw(const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer) { /// Left empty to override the default LLSD parsing behaviour. + httpCompleted(); } - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content) +private: + virtual void httpFailure() { - if (HTTP_UNAUTHORIZED == status) + if (HTTP_UNAUTHORIZED == getStatus()) { LL_WARNS("WebSharing") << "AU account not authenticated." << LL_ENDL; // *TODO: No account found on AU, so start the account creation process here. } else { - LL_WARNS("WebSharing") << "Error [status:" << status << "]: " << content << LL_ENDL; + LL_WARNS("WebSharing") << dumpResponse() << LL_ENDL; LLWebSharing::instance().retryOpenIDAuth(); } - } - virtual void result(const LLSD& content) + virtual void httpSuccess() { - if (content.has("set-cookie")) + const bool check_lower=true; + if (hasResponseHeader(HTTP_HEADER_SET_COOKIE, check_lower)) { // OpenID request succeeded and returned a session cookie. - LLWebSharing::instance().receiveSessionCookie(content["set-cookie"].asString()); + LLWebSharing::instance().receiveSessionCookie(getResponseHeader(HTTP_HEADER_SET_COOKIE, check_lower)); } } }; @@ -128,38 +145,19 @@ public: /////////////////////////////////////////////////////////////////////////////// // -class LLWebSharingSecurityTokenResponder : public LLHTTPClient::Responder +class LLWebSharingSecurityTokenResponder : public LLWebSharingJSONResponder { LOG_CLASS(LLWebSharingSecurityTokenResponder); -public: - /// Overrides the default LLSD parsing behaviour, to allow parsing a JSON response. - virtual void completedRaw(U32 status, const std::string& reason, - const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer) +private: + virtual void httpFailure() { - LLSD content; - LLBufferStream istr(channels, buffer.get()); - LLPointer<LLSDParser> parser = new LLSDNotationParser(); - - if (parser->parse(istr, content, LLSDSerialize::SIZE_UNLIMITED) == LLSDParser::PARSE_FAILURE) - { - LL_WARNS("WebSharing") << "Failed to deserialize LLSD from JSON response. " << " [" << status << "]: " << reason << LL_ENDL; - LLWebSharing::instance().retryOpenIDAuth(); - } - else - { - completed(status, reason, content); - } - } - - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content) - { - LL_WARNS("WebSharing") << "Error [status:" << status << "]: " << content << LL_ENDL; + LL_WARNS("WebSharing") << dumpResponse() << LL_ENDL; LLWebSharing::instance().retryOpenIDAuth(); } - virtual void result(const LLSD& content) + virtual void httpSuccess() { + const LLSD& content = getContent(); if (content[0].has("st") && content[0].has("expires")) { const std::string& token = content[0]["st"].asString(); @@ -172,7 +170,8 @@ public: } else { - LL_WARNS("WebSharing") << "No security token received." << LL_ENDL; + failureResult(HTTP_INTERNAL_ERROR, "No security token received.", content); + return; } LLWebSharing::instance().retryOpenIDAuth(); @@ -183,51 +182,18 @@ public: /////////////////////////////////////////////////////////////////////////////// // -class LLWebSharingUploadResponder : public LLHTTPClient::Responder +class LLWebSharingUploadResponder : public LLWebSharingJSONResponder { LOG_CLASS(LLWebSharingUploadResponder); -public: - /// Overrides the default LLSD parsing behaviour, to allow parsing a JSON response. - virtual void completedRaw(U32 status, const std::string& reason, - const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer) - { -/* - // Dump the body, for debugging. - - LLBufferStream istr1(channels, buffer.get()); - std::ostringstream ostr; - std::string body; - - while (istr1.good()) - { - char buf[1024]; - istr1.read(buf, sizeof(buf)); - body.append(buf, istr1.gcount()); - } - LL_DEBUGS("WebSharing") << body << LL_ENDL; -*/ - LLSD content; - LLBufferStream istr(channels, buffer.get()); - LLPointer<LLSDParser> parser = new LLSDNotationParser(); - - if (parser->parse(istr, content, LLSDSerialize::SIZE_UNLIMITED) == LLSDParser::PARSE_FAILURE) - { - LL_WARNS("WebSharing") << "Failed to deserialize LLSD from JSON response. " << " [" << status << "]: " << reason << LL_ENDL; - } - else - { - completed(status, reason, content); - } - } - - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content) +private: + virtual void httpFailure() { - LL_WARNS("WebSharing") << "Error [status:" << status << "]: " << content << LL_ENDL; + LL_WARNS("WebSharing") << dumpResponse() << LL_ENDL; } - virtual void result(const LLSD& content) + virtual void httpSuccess() { + const LLSD& content = getContent(); if (content[0].has("result") && content[0].has("id") && content[0]["id"].asString() == "newMediaItem") { @@ -235,8 +201,8 @@ public: } else { - LL_WARNS("WebSharing") << "Error [" << content[0]["code"].asString() - << "]: " << content[0]["message"].asString() << LL_ENDL; + failureResult(HTTP_INTERNAL_ERROR, "Invalid response content", content); + return; } } }; @@ -333,7 +299,7 @@ void LLWebSharing::sendConfigRequest() LL_DEBUGS("WebSharing") << "Requesting Snapshot Sharing config data from: " << config_url << LL_ENDL; LLSD headers = LLSD::emptyMap(); - headers["Accept"] = "application/json"; + headers[HTTP_HEADER_ACCEPT] = HTTP_CONTENT_JSON; LLHTTPClient::get(config_url, new LLWebSharingConfigResponder(), headers); } @@ -344,8 +310,8 @@ void LLWebSharing::sendOpenIDAuthRequest() LL_DEBUGS("WebSharing") << "Starting OpenID Auth: " << auth_url << LL_ENDL; LLSD headers = LLSD::emptyMap(); - headers["Cookie"] = mOpenIDCookie; - headers["Accept"] = "*/*"; + headers[HTTP_HEADER_COOKIE] = mOpenIDCookie; + headers[HTTP_HEADER_ACCEPT] = "*/*"; // Send request, successful login will trigger fetching a security token. LLHTTPClient::get(auth_url, new LLWebSharingOpenIDAuthResponder(), headers); @@ -371,10 +337,10 @@ void LLWebSharing::sendSecurityTokenRequest() LL_DEBUGS("WebSharing") << "Fetching security token from: " << token_url << LL_ENDL; LLSD headers = LLSD::emptyMap(); - headers["Cookie"] = mSessionCookie; + headers[HTTP_HEADER_COOKIE] = mSessionCookie; - headers["Accept"] = "application/json"; - headers["Content-Type"] = "application/json"; + headers[HTTP_HEADER_ACCEPT] = HTTP_CONTENT_JSON; + headers[HTTP_HEADER_CONTENT_TYPE] = HTTP_CONTENT_JSON; std::ostringstream body; body << "{ \"gadgets\": [{ \"url\":\"" @@ -400,10 +366,10 @@ void LLWebSharing::sendUploadRequest() static const std::string BOUNDARY("------------abcdef012345xyZ"); LLSD headers = LLSD::emptyMap(); - headers["Cookie"] = mSessionCookie; + headers[HTTP_HEADER_COOKIE] = mSessionCookie; - headers["Accept"] = "application/json"; - headers["Content-Type"] = "multipart/form-data; boundary=" + BOUNDARY; + headers[HTTP_HEADER_ACCEPT] = HTTP_CONTENT_JSON; + headers[HTTP_HEADER_CONTENT_TYPE] = "multipart/form-data; boundary=" + BOUNDARY; std::ostringstream body; body << "--" << BOUNDARY << "\r\n" diff --git a/indra/newview/llwlhandlers.cpp b/indra/newview/llwlhandlers.cpp index 93eba5b604..3bedfbe502 100644 --- a/indra/newview/llwlhandlers.cpp +++ b/indra/newview/llwlhandlers.cpp @@ -95,8 +95,9 @@ LLEnvironmentRequestResponder::LLEnvironmentRequestResponder() { mID = ++sCount; } -/*virtual*/ void LLEnvironmentRequestResponder::result(const LLSD& unvalidated_content) +/*virtual*/ void LLEnvironmentRequestResponder::httpSuccess() { + const LLSD& unvalidated_content = getContent(); LL_INFOS("WindlightCaps") << "Received region windlight settings" << LL_ENDL; if (mID != sCount) @@ -122,10 +123,10 @@ LLEnvironmentRequestResponder::LLEnvironmentRequestResponder() LLEnvManagerNew::getInstance()->onRegionSettingsResponse(unvalidated_content); } /*virtual*/ -void LLEnvironmentRequestResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) +void LLEnvironmentRequestResponder::httpFailure() { - LL_INFOS("WindlightCaps") << "Got an error, not using region windlight... [status:" - << status << "]: " << content << LL_ENDL; + LL_WARNS("WindlightCaps") << "Got an error, not using region windlight... " + << dumpResponse() << LL_ENDL; LLEnvManagerNew::getInstance()->onRegionSettingsResponse(LLSD()); } @@ -169,8 +170,14 @@ bool LLEnvironmentApply::initiateRequest(const LLSD& content) /**** * LLEnvironmentApplyResponder ****/ -/*virtual*/ void LLEnvironmentApplyResponder::result(const LLSD& content) +/*virtual*/ void LLEnvironmentApplyResponder::httpSuccess() { + const LLSD& content = getContent(); + if (!content.isMap() || !content.has("regionID")) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } if (content["regionID"].asUUID() != gAgent.getRegion()->getRegionID()) { LL_WARNS("WindlightCaps") << "No longer in the region where data was sent (currently " @@ -185,7 +192,7 @@ bool LLEnvironmentApply::initiateRequest(const LLSD& content) } else { - LL_WARNS("WindlightCaps") << "Region couldn't apply windlight settings! Reason from sim: " << content["fail_reason"].asString() << LL_ENDL; + LL_WARNS("WindlightCaps") << "Region couldn't apply windlight settings! " << dumpResponse() << LL_ENDL; LLSD args(LLSD::emptyMap()); args["FAIL_REASON"] = content["fail_reason"].asString(); LLNotificationsUtil::add("WLRegionApplyFail", args); @@ -193,14 +200,14 @@ bool LLEnvironmentApply::initiateRequest(const LLSD& content) } } /*virtual*/ -void LLEnvironmentApplyResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) +void LLEnvironmentApplyResponder::httpFailure() { - LL_WARNS("WindlightCaps") << "Couldn't apply windlight settings to region! [status:" - << status << "]: " << content << LL_ENDL; + LL_WARNS("WindlightCaps") << "Couldn't apply windlight settings to region! " + << dumpResponse() << LL_ENDL; LLSD args(LLSD::emptyMap()); std::stringstream msg; - msg << reason << " (Code " << status << ")"; + msg << getReason() << " (Code " << getStatus() << ")"; args["FAIL_REASON"] = msg.str(); LLNotificationsUtil::add("WLRegionApplyFail", args); } diff --git a/indra/newview/llwlhandlers.h b/indra/newview/llwlhandlers.h index 598ce6d52a..089c799da7 100644 --- a/indra/newview/llwlhandlers.h +++ b/indra/newview/llwlhandlers.h @@ -45,9 +45,9 @@ private: class LLEnvironmentRequestResponder: public LLHTTPClient::Responder { LOG_CLASS(LLEnvironmentRequestResponder); -public: - virtual void result(const LLSD& content); - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content); +private: + /* virtual */ void httpSuccess(); + /* virtual */ void httpFailure(); private: friend class LLEnvironmentRequest; @@ -72,7 +72,7 @@ private: class LLEnvironmentApplyResponder: public LLHTTPClient::Responder { LOG_CLASS(LLEnvironmentApplyResponder); -public: +private: /* * Expecting reply from sim in form of: * { @@ -87,10 +87,10 @@ public: * fail_reason : string * } */ - virtual void result(const LLSD& content); + /* virtual */ void httpSuccess(); - // non-200 errors only - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content); + // non-2xx errors only + /* virtual */ void httpFailure(); private: friend class LLEnvironmentApply; diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp index 0da70d398b..604e08161e 100644 --- a/indra/newview/llxmlrpctransaction.cpp +++ b/indra/newview/llxmlrpctransaction.cpp @@ -331,7 +331,7 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip) This might help with bug #503 */ mCurlRequest->setopt(CURLOPT_DNS_CACHE_TIMEOUT, -1); - mCurlRequest->slist_append("Content-Type: text/xml"); + mCurlRequest->slist_append(HTTP_HEADER_CONTENT_TYPE, HTTP_CONTENT_TEXT_XML); if (useGzip) { diff --git a/indra/newview/tests/llmediadataclient_test.cpp b/indra/newview/tests/llmediadataclient_test.cpp index 41cb344808..01195d1269 100644 --- a/indra/newview/tests/llmediadataclient_test.cpp +++ b/indra/newview/tests/llmediadataclient_test.cpp @@ -33,7 +33,7 @@ #include "llsdserialize.h" #include "llsdutil.h" #include "llerrorcontrol.h" -#include "llhttpstatuscodes.h" +#include "llhttpconstants.h" #include "../llmediadataclient.h" #include "../llvovolume.h" @@ -128,7 +128,7 @@ void LLHTTPClient::post( { LLSD content; content["reason"] = "fake reason"; - responder->errorWithContent(HTTP_SERVICE_UNAVAILABLE, "fake reason", content); + responder->failureResult(HTTP_SERVICE_UNAVAILABLE, "fake reason", content); return; } else if (url == FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR) @@ -136,8 +136,8 @@ void LLHTTPClient::post( LLSD error; error["code"] = LLObjectMediaNavigateClient::ERROR_PERMISSION_DENIED_CODE; result["error"] = error; - } - responder->result(result); + } + responder->successResult(result); } const F32 HTTP_REQUEST_EXPIRY_SECS = 60.0f; diff --git a/indra/newview/tests/llremoteparcelrequest_test.cpp b/indra/newview/tests/llremoteparcelrequest_test.cpp index ed66066b0a..c49b0350e9 100644 --- a/indra/newview/tests/llremoteparcelrequest_test.cpp +++ b/indra/newview/tests/llremoteparcelrequest_test.cpp @@ -40,12 +40,14 @@ namespace { LLCurl::Responder::Responder() { } LLCurl::Responder::~Responder() { } -void LLCurl::Responder::error(U32,std::string const &) { } -void LLCurl::Responder::result(LLSD const &) { } -void LLCurl::Responder::errorWithContent(U32 status,std::string const &,LLSD const &) { } -void LLCurl::Responder::completedRaw(U32 status, std::string const &, LLChannelDescriptors const &,boost::shared_ptr<LLBufferArray> const &) { } -void LLCurl::Responder::completed(U32 status, std::string const &, LLSD const &) { } -void LLCurl::Responder::completedHeader(U32 status, std::string const &, LLSD const &) { } +void LLCurl::Responder::httpFailure() { } +void LLCurl::Responder::httpSuccess() { } +void LLCurl::Responder::httpCompleted() { } +void LLCurl::Responder::failureResult(S32 status, const std::string& reason, const LLSD& content) { } +void LLCurl::Responder::successResult(const LLSD& content) { } +void LLCurl::Responder::completeResult(S32 status, const std::string& reason, const LLSD& content) { } +std::string LLCurl::Responder::dumpResponse() const { return "(failure)"; } +void LLCurl::Responder::completedRaw(LLChannelDescriptors const &,boost::shared_ptr<LLBufferArray> const &) { } void LLMessageSystem::getF32(char const *,char const *,F32 &,S32) { } void LLMessageSystem::getU8(char const *,char const *,U8 &,S32) { } void LLMessageSystem::getS32(char const *,char const *,S32 &,S32) { } @@ -85,7 +87,7 @@ namespace tut virtual void setParcelID(const LLUUID& parcel_id) { } - virtual void setErrorStatus(U32 status, const std::string& reason) { } + virtual void setErrorStatus(S32 status, const std::string& reason) { } bool mProcessed; }; diff --git a/indra/newview/tests/lltranslate_test.cpp b/indra/newview/tests/lltranslate_test.cpp index fd9527d631..b28eb5db43 100644 --- a/indra/newview/tests/lltranslate_test.cpp +++ b/indra/newview/tests/lltranslate_test.cpp @@ -34,6 +34,8 @@ #include "lltrans.h" #include "llui.h" +#include "../../llmessage/llhttpconstants.cpp" + static const std::string GOOGLE_VALID_RESPONSE1 = "{\ \"data\": {\ @@ -300,12 +302,10 @@ std::string LLControlGroup::getString(const std::string& name) { return "dummy"; LLControlGroup::~LLControlGroup() {} LLCurl::Responder::Responder() {} -void LLCurl::Responder::completedHeader(U32, std::string const&, LLSD const&) {} -void LLCurl::Responder::completedRaw(U32, const std::string&, const LLChannelDescriptors&, const LLIOPipe::buffer_ptr_t& buffer) {} -void LLCurl::Responder::completed(U32, std::string const&, LLSD const&) {} -void LLCurl::Responder::error(U32, std::string const&) {} -void LLCurl::Responder::errorWithContent(U32, std::string const&, LLSD const&) {} -void LLCurl::Responder::result(LLSD const&) {} +void LLCurl::Responder::httpFailure() { } +void LLCurl::Responder::httpSuccess() { } +void LLCurl::Responder::httpCompleted() { } +void LLCurl::Responder::completedRaw(LLChannelDescriptors const &,boost::shared_ptr<LLBufferArray> const &) { } LLCurl::Responder::~Responder() {} void LLHTTPClient::get(const std::string&, const LLSD&, ResponderPtr, const LLSD&, const F32) {} diff --git a/indra/test/llassetuploadqueue_tut.cpp b/indra/test/llassetuploadqueue_tut.cpp index ec952e0058..25efe63d3f 100644 --- a/indra/test/llassetuploadqueue_tut.cpp +++ b/indra/test/llassetuploadqueue_tut.cpp @@ -45,11 +45,11 @@ LLAssetUploadResponder::~LLAssetUploadResponder() { } -void LLAssetUploadResponder::error(U32 statusNum, const std::string& reason) +void LLAssetUploadResponder::httpFailure() { } -void LLAssetUploadResponder::result(const LLSD& content) +void LLAssetUploadResponder::httpSuccess() { } diff --git a/indra/test/llblowfish_tut.cpp b/indra/test/llblowfish_tut.cpp index 2573cab81f..20e7960829 100644 --- a/indra/test/llblowfish_tut.cpp +++ b/indra/test/llblowfish_tut.cpp @@ -65,7 +65,7 @@ namespace tut } if (!fp) { - llwarns << "unabled to open " << filename << llendl; + llwarns << "unable to open " << filename << llendl; return false; } diff --git a/indra/test/llhttpnode_tut.cpp b/indra/test/llhttpnode_tut.cpp index 216c59d766..d580263103 100644 --- a/indra/test/llhttpnode_tut.cpp +++ b/indra/test/llhttpnode_tut.cpp @@ -81,6 +81,7 @@ namespace tut void result(const LLSD& result) { mResult = result; } void status(S32 code, const std::string& message) { } void extendedResult(S32 code, const std::string& message, const LLSD& headers) { } + void extendedResult(S32 code, const LLSD& result, const LLSD& headers) { } private: Response() {;} // Must be accessed through LLPointer. diff --git a/indra/test/llsd_new_tut.cpp b/indra/test/llsd_new_tut.cpp index f928a1bad0..03df1d339b 100644 --- a/indra/test/llsd_new_tut.cpp +++ b/indra/test/llsd_new_tut.cpp @@ -93,6 +93,18 @@ namespace tut ensure( s + " type", traits.checkType(actual)); ensure_equals( s + " value", traits.get(actual), expectedValue); } + + template<class T> + static void ensureTypeAndRefValue(const char* msg, const LLSD& actual, + const T& expectedValue) + { + LLSDTraits<const T&> traits; + + std::string s(msg); + + ensure( s + " type", traits.checkType(actual)); + ensure_equals( s + " value", traits.get(actual), expectedValue); + } }; typedef test_group<SDTestData> SDTestGroup; @@ -162,7 +174,7 @@ namespace tut std::vector<U8> data; copy(&source[0], &source[sizeof(source)], back_inserter(data)); - v = data; ensureTypeAndValue("set to data", v, data); + v = data; ensureTypeAndRefValue("set to data", v, data); v.clear(); ensure("reset to undefined", v.type() == LLSD::TypeUndefined); @@ -213,8 +225,8 @@ namespace tut const char source[] = "once in a blue moon"; std::vector<U8> data; copy(&source[0], &source[sizeof(source)], back_inserter(data)); - LLSD x1(data); ensureTypeAndValue("construct vector<U8>", x1, data); - LLSD x2 = data; ensureTypeAndValue("initialize vector<U8>", x2, data); + LLSD x1(data); ensureTypeAndRefValue("construct vector<U8>", x1, data); + LLSD x2 = data; ensureTypeAndRefValue("initialize vector<U8>", x2, data); } void checkConversions(const char* msg, const LLSD& v, @@ -757,42 +769,6 @@ namespace tut { SDAllocationCheck check("shared values test for threaded work", 9); - //U32 start_llsd_count = llsd::outstandingCount(); - - LLSD m = LLSD::emptyMap(); - - m["one"] = 1; - m["two"] = 2; - m["one_copy"] = m["one"]; // 3 (m, "one" and "two") - - m["undef_one"] = LLSD(); - m["undef_two"] = LLSD(); - m["undef_one_copy"] = m["undef_one"]; - - { // Ensure first_array gets freed to avoid counting it - LLSD first_array = LLSD::emptyArray(); - first_array.append(1.0f); - first_array.append(2.0f); - first_array.append(3.0f); // 7 - - m["array"] = first_array; - m["array_clone"] = first_array; - m["array_copy"] = m["array"]; // 7 - } - - m["string_one"] = "string one value"; - m["string_two"] = "string two value"; - m["string_one_copy"] = m["string_one"]; // 9 - - //U32 llsd_object_count = llsd::outstandingCount(); - //std::cout << "Using " << (llsd_object_count - start_llsd_count) << " LLSD objects" << std::endl; - - //m.dumpStats(); - } - - { - SDAllocationCheck check("shared values test for threaded work", 9); - //U32 start_llsd_count = LLSD::outstandingCount(); LLSD m = LLSD::emptyMap(); @@ -852,3 +828,4 @@ namespace tut test serializations */ } + diff --git a/indra/test/llsdtraits.h b/indra/test/llsdtraits.h index 8144aaee94..07f6193ce2 100644 --- a/indra/test/llsdtraits.h +++ b/indra/test/llsdtraits.h @@ -93,7 +93,7 @@ LLSDTraits<LLSD::URI>::LLSDTraits() { } template<> inline -LLSDTraits<LLSD::Binary>::LLSDTraits() +LLSDTraits<const LLSD::Binary&>::LLSDTraits() : type(LLSD::TypeBinary), getter(&LLSD::asBinary) { } diff --git a/indra/test/message_tut.cpp b/indra/test/message_tut.cpp index d971b33475..0dae5178be 100644 --- a/indra/test/message_tut.cpp +++ b/indra/test/message_tut.cpp @@ -46,6 +46,7 @@ namespace mStatus = code; } virtual void extendedResult(S32 code, const std::string& message, const LLSD& headers) { } + virtual void extendedResult(S32 code, const LLSD& result, const LLSD& headers) { } S32 mStatus; }; } @@ -142,7 +143,7 @@ namespace tut const LLSD message; const LLPointer<Response> response = new Response(); gMessageSystem->dispatch(name, message, response); - ensure_equals(response->mStatus, 404); + ensure_equals(response->mStatus, HTTP_NOT_FOUND); } } diff --git a/indra/test/mock_http_client.h b/indra/test/mock_http_client.h index 7668a43fdf..a2b9b435fb 100644 --- a/indra/test/mock_http_client.h +++ b/indra/test/mock_http_client.h @@ -98,7 +98,7 @@ namespace tut if (mSawError) { std::string msg = - llformat("error() called when not expected, status %d", + llformat("httpFailure() called when not expected, status %d", mStatus); fail(msg); } @@ -108,7 +108,7 @@ namespace tut { if (!mSawError) { - fail("error() wasn't called"); + fail("httpFailure() wasn't called"); } } @@ -119,7 +119,7 @@ namespace tut protected: bool mSawError; - U32 mStatus; + S32 mStatus; std::string mReason; bool mSawCompleted; LLSD mResult; @@ -144,23 +144,22 @@ namespace tut mClient.mResultDeleted = true; } - virtual void error(U32 status, const std::string& reason) + protected: + virtual void httpFailure() { mClient.mSawError = true; - mClient.mStatus = status; - mClient.mReason = reason; + mClient.mStatus = getStatus(); + mClient.mReason = getReason(); } - virtual void result(const LLSD& content) + virtual void httpSuccess() { - mClient.mResult = content; + mClient.mResult = getContent(); } - virtual void completed( - U32 status, const std::string& reason, - const LLSD& content) + virtual void httpCompleted() { - LLHTTPClient::Responder::completed(status, reason, content); + LLHTTPClient::Responder::httpCompleted(); mClient.mSawCompleted = true; } diff --git a/indra/viewer_components/updater/llupdatechecker.cpp b/indra/viewer_components/updater/llupdatechecker.cpp index 5edbbf9914..49b404a7ad 100644 --- a/indra/viewer_components/updater/llupdatechecker.cpp +++ b/indra/viewer_components/updater/llupdatechecker.cpp @@ -106,15 +106,14 @@ void LLUpdateChecker::Implementation::checkVersion(std::string const & protocolV mHttpClient.get(checkUrl, this); } -void LLUpdateChecker::Implementation::completed(U32 status, - const std::string & reason, - const LLSD & content) +void LLUpdateChecker::Implementation::httpCompleted() { - mInProgress = false; - - if(status != 200) { - LL_WARNS("UpdateCheck") << "html error " << status << " (" << reason << ")" << llendl; - mClient.error(reason); + mInProgress = false; + + const LLSD& content = getContent(); + if(getStatus() != HTTP_OK) { + LL_WARNS("UpdateCheck") << "html error " << dumpResponse() << LL_ENDL; + mClient.error(getReason()); } else if(!content.asBoolean()) { LL_INFOS("UpdateCheck") << "up to date" << llendl; mClient.upToDate(); @@ -130,8 +129,9 @@ void LLUpdateChecker::Implementation::completed(U32 status, } -void LLUpdateChecker::Implementation::error(U32 status, const std::string & reason) +void LLUpdateChecker::Implementation::httpFailure() { + const std::string& reason = getReason(); mInProgress = false; LL_WARNS("UpdateCheck") << "update check failed; " << reason << llendl; mClient.error(reason); diff --git a/indra/viewer_components/updater/llupdatechecker.h b/indra/viewer_components/updater/llupdatechecker.h index 23f62a7c5e..3ecd6230be 100644 --- a/indra/viewer_components/updater/llupdatechecker.h +++ b/indra/viewer_components/updater/llupdatechecker.h @@ -47,11 +47,10 @@ public: void checkVersion(std::string const & protocolVersion, std::string const & hostUrl, std::string const & servicePath, std::string channel, std::string version); + protected: // Responder: - virtual void completed(U32 status, - const std::string & reason, - const LLSD& content); - virtual void error(U32 status, const std::string & reason); + virtual void httpCompleted(); + virtual void httpFailure(); private: static const char * sProtocolVersion; |