diff options
Diffstat (limited to 'indra/llmessage')
30 files changed, 1093 insertions, 750 deletions
| 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); -	} -} - | 
