diff options
| author | Rider Linden <rider@lindenlab.com> | 2015-05-27 17:15:01 -0700 | 
|---|---|---|
| committer | Rider Linden <rider@lindenlab.com> | 2015-05-27 17:15:01 -0700 | 
| commit | 83543e556cba8753077c9f004bb0dc71b4509007 (patch) | |
| tree | db3a0f30e486475f72ddf945a5a6263b1219a4a0 /indra | |
| parent | 9134a3a097607e427b18af010774eb842be893f2 (diff) | |
Memory leak (extra ref) in webprofile
Viewer media routines to coroutine.
Post with raw respons in llcorehttputil
LLCore::Http added headers only option (applies only on get)
Diffstat (limited to 'indra')
| -rwxr-xr-x | indra/llcorehttp/_httpoprequest.cpp | 8 | ||||
| -rwxr-xr-x | indra/llcorehttp/httpoptions.cpp | 29 | ||||
| -rwxr-xr-x | indra/llcorehttp/httpoptions.h | 10 | ||||
| -rw-r--r-- | indra/llmessage/llcorehttputil.cpp | 12 | ||||
| -rw-r--r-- | indra/llmessage/llcorehttputil.h | 13 | ||||
| -rwxr-xr-x | indra/newview/llviewermedia.cpp | 483 | ||||
| -rwxr-xr-x | indra/newview/llviewermedia.h | 14 | ||||
| -rwxr-xr-x | indra/newview/llwebprofile.cpp | 2 | 
8 files changed, 282 insertions, 289 deletions
| diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp index b1b05dc285..3b6647882e 100755 --- a/indra/llcorehttp/_httpoprequest.cpp +++ b/indra/llcorehttp/_httpoprequest.cpp @@ -532,6 +532,7 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)  	long sslPeerV(0L);  	long sslHostV(0L);      long dnsCacheTimeout(-1L); +    long nobody(0L);  	if (mReqOptions)  	{ @@ -539,6 +540,7 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)  		sslPeerV = mReqOptions->getSSLVerifyPeer() ? 1L : 0L;  		sslHostV = mReqOptions->getSSLVerifyHost() ? 2L : 0L;  		dnsCacheTimeout = mReqOptions->getDNSCacheTimeout(); +        nobody = mReqOptions->getHeadersOnly() ? 1L : 0L;  	}  	code = curl_easy_setopt(mCurlHandle, CURLOPT_FOLLOWLOCATION, follow_redirect);  	check_curl_easy_code(code, CURLOPT_FOLLOWLOCATION); @@ -548,6 +550,9 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)  	code = curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYHOST, sslHostV);  	check_curl_easy_code(code, CURLOPT_SSL_VERIFYHOST); +    code = curl_easy_setopt(mCurlHandle, CURLOPT_NOBODY, nobody); +    check_curl_easy_code(code, CURLOPT_NOBODY); +  	// The Linksys WRT54G V5 router has an issue with frequent  	// DNS lookups from LAN machines.  If they happen too often,  	// like for every HTTP request, the router gets annoyed after @@ -587,7 +592,8 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)  	switch (mReqMethod)  	{  	case HOR_GET: -		code = curl_easy_setopt(mCurlHandle, CURLOPT_HTTPGET, 1); +        if (nobody == 0) +            code = curl_easy_setopt(mCurlHandle, CURLOPT_HTTPGET, 1);  		check_curl_easy_code(code, CURLOPT_HTTPGET);  		break; diff --git a/indra/llcorehttp/httpoptions.cpp b/indra/llcorehttp/httpoptions.cpp index a4d08a80df..2b42bcaf6d 100755 --- a/indra/llcorehttp/httpoptions.cpp +++ b/indra/llcorehttp/httpoptions.cpp @@ -34,16 +34,17 @@ namespace LLCore  HttpOptions::HttpOptions() : RefCounted(true), -	mWantHeaders(false), -	mTracing(HTTP_TRACE_OFF), -	mTimeout(HTTP_REQUEST_TIMEOUT_DEFAULT), -	mTransferTimeout(HTTP_REQUEST_XFER_TIMEOUT_DEFAULT), -	mRetries(HTTP_RETRY_COUNT_DEFAULT), -	mUseRetryAfter(HTTP_USE_RETRY_AFTER_DEFAULT), -	mFollowRedirects(false), -	mVerifyPeer(false), -	mVerifyHost(false), -    mDNSCacheTimeout(-1L) +    mWantHeaders(false), +    mTracing(HTTP_TRACE_OFF), +    mTimeout(HTTP_REQUEST_TIMEOUT_DEFAULT), +    mTransferTimeout(HTTP_REQUEST_XFER_TIMEOUT_DEFAULT), +    mRetries(HTTP_RETRY_COUNT_DEFAULT), +    mUseRetryAfter(HTTP_USE_RETRY_AFTER_DEFAULT), +    mFollowRedirects(false), +    mVerifyPeer(false), +    mVerifyHost(false), +    mDNSCacheTimeout(-1L), +    mNoBody(false)  {} @@ -104,4 +105,12 @@ void HttpOptions::setDNSCacheTimeout(int timeout)  {  	mDNSCacheTimeout = timeout;  } + +void HttpOptions::setHeadersOnly(bool nobody) +{ +    mNoBody = nobody; +    if (mNoBody) +        setWantHeaders(true); +} +  }   // end namespace LLCore diff --git a/indra/llcorehttp/httpoptions.h b/indra/llcorehttp/httpoptions.h index 765d2431bb..21ecff85af 100755 --- a/indra/llcorehttp/httpoptions.h +++ b/indra/llcorehttp/httpoptions.h @@ -149,6 +149,15 @@ public:  	{  		return mDNSCacheTimeout;  	} + +    /// Retrieve only the headers and status from the request. Setting this  +    /// to true implies setWantHeaders(true) as well. +    /// Default: false +    void                setHeadersOnly(bool nobody); +    bool                getHeadersOnly() const +    { +        return mNoBody; +    }  protected:  	bool				mWantHeaders; @@ -161,6 +170,7 @@ protected:  	bool				mVerifyPeer;  	bool        		mVerifyHost;  	int					mDNSCacheTimeout; +    bool                mNoBody;  }; // end class HttpOptions diff --git a/indra/llmessage/llcorehttputil.cpp b/indra/llmessage/llcorehttputil.cpp index 001df9e385..c4a7e9040a 100644 --- a/indra/llmessage/llcorehttputil.cpp +++ b/indra/llmessage/llcorehttputil.cpp @@ -256,7 +256,7 @@ void HttpCoroHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRespons      buildStatusEntry(response, status, result); -#if 0 +#if 1      // commenting out, but keeping since this can be useful for debugging      if (!status)      { @@ -608,6 +608,16 @@ LLSD HttpCoroutineAdapter::postAndYield(LLCoros::self & self, LLCore::HttpReques      return postAndYield_(self, request, url, rawbody, options, headers, httpHandler);  } +LLSD HttpCoroutineAdapter::postRawAndYield(LLCoros::self & self, LLCore::HttpRequest::ptr_t request, +    const std::string & url, LLCore::BufferArray::ptr_t rawbody, +    LLCore::HttpOptions::ptr_t options, LLCore::HttpHeaders::ptr_t headers) +{ +    LLEventStream  replyPump(mAdapterName, true); +    HttpCoroHandler::ptr_t httpHandler = HttpCoroHandler::ptr_t(new HttpCoroRawHandler(replyPump)); + +    return postAndYield_(self, request, url, rawbody, options, headers, httpHandler); +} +  LLSD HttpCoroutineAdapter::postAndYield_(LLCoros::self & self, LLCore::HttpRequest::ptr_t &request,      const std::string & url, LLCore::BufferArray::ptr_t &rawbody,      LLCore::HttpOptions::ptr_t &options, LLCore::HttpHeaders::ptr_t &headers, diff --git a/indra/llmessage/llcorehttputil.h b/indra/llmessage/llcorehttputil.h index d6219318f9..213610e58e 100644 --- a/indra/llmessage/llcorehttputil.h +++ b/indra/llmessage/llcorehttputil.h @@ -334,6 +334,19 @@ public:              LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions(), false), headers);      } +    LLSD postRawAndYield(LLCoros::self & self, LLCore::HttpRequest::ptr_t request, +        const std::string & url, LLCore::BufferArray::ptr_t rawbody, +        LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions(), false), +        LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders(), false)); + +    LLSD postRawAndYield(LLCoros::self & self, LLCore::HttpRequest::ptr_t &request, +        const std::string & url, LLCore::BufferArray::ptr_t &rawbody, +        LLCore::HttpHeaders::ptr_t &headers) +    { +        return postRawAndYield(self, request, url, rawbody, +            LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions(), false), headers); +    } +      /// Execute a Put transaction on the supplied URL and yield execution of       /// the coroutine until a result is available.      ///  diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 509227c683..02167b099e 100755 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -69,6 +69,7 @@  #include "llwebprofile.h"  #include "llwindow.h"  #include "llvieweraudio.h" +#include "llcorehttputil.h"  #include "llfloaterwebcontent.h"	// for handling window close requests and geometry change requests in media browser windows. @@ -152,190 +153,6 @@ LLViewerMediaObserver::~LLViewerMediaObserver()  } -// Move this to its own file. -// helper class that tries to download a URL from a web site and calls a method -// on the Panel Land Media and to discover the MIME type -class LLMimeDiscoveryResponder : public LLHTTPClient::Responder -{ -	LOG_CLASS(LLMimeDiscoveryResponder); -public: -	LLMimeDiscoveryResponder( viewer_media_t media_impl) -		: mMediaImpl(media_impl), -		  mInitialized(false) -	{ -		if(mMediaImpl->mMimeTypeProbe != NULL) -		{ -			LL_ERRS() << "impl already has an outstanding responder" << LL_ENDL; -		} -		 -		mMediaImpl->mMimeTypeProbe = this; -	} - -	~LLMimeDiscoveryResponder() -	{ -		disconnectOwner(); -	} - -private: -	/* virtual */ void httpCompleted() -	{ -		if (!isGoodStatus()) -		{ -			LL_WARNS() << dumpResponse() -					<< " [headers:" << getResponseHeaders() << "]" << LL_ENDL; -		} -		const std::string& media_type = getResponseHeader(HTTP_IN_HEADER_CONTENT_TYPE); -		std::string::size_type idx1 = media_type.find_first_of(";"); -		std::string mime_type = media_type.substr(0, idx1); - -		LL_DEBUGS() << "status is " << getStatus() << ", media type \"" << media_type << "\"" << LL_ENDL; -		 -		// 2xx status codes indicate success. -		// Most 4xx status codes are successful enough for our purposes. -		// 499 is the error code for host not found, timeout, etc. -		// 500 means "Internal Server error" but we decided it's okay to  -		//     accept this and go past it in the MIME type probe -		// 302 means the resource can be found temporarily in a different place - added this for join.secondlife.com -		// 499 is a code specifc to join.secondlife.com (?) apparently safe to ignore -//		if(	((status >= 200) && (status < 300))	|| -//			((status >= 400) && (status < 499))	||  -//			(status == 500) || -//			(status == 302) || -//			(status == 499)  -//			) -		// We now no longer check the error code returned from the probe. -		// If we have a mime type, use it.  If not, default to the web plugin and let it handle error reporting. -		//if(1) -		{ -			// The probe was successful. -			if(mime_type.empty()) -			{ -				// Some sites don't return any content-type header at all. -				// Treat an empty mime type as text/html. -				mime_type = HTTP_CONTENT_TEXT_HTML; -			} -		} -		//else -		//{ -		//	LL_WARNS() << "responder failed with status " << dumpResponse() << LL_ENDL; -		// -		//	if(mMediaImpl) -		//	{ -		//		mMediaImpl->mMediaSourceFailed = true; -		//	} -		//	return; -		//} - -		// the call to initializeMedia may disconnect the responder, which will clear mMediaImpl. -		// Make a local copy so we can call loadURI() afterwards. -		LLViewerMediaImpl *impl = mMediaImpl; -		 -		if(impl && !mInitialized && ! mime_type.empty()) -		{ -			if(impl->initializeMedia(mime_type)) -			{ -				mInitialized = true; -				impl->loadURI(); -				disconnectOwner(); -			} -		} -	} -	 -public: -	void cancelRequest() -	{ -		disconnectOwner(); -	} -	 -private: -	void disconnectOwner() -	{ -		if(mMediaImpl) -		{ -			if(mMediaImpl->mMimeTypeProbe != this) -			{ -				LL_ERRS() << "internal error: mMediaImpl->mMimeTypeProbe != this" << LL_ENDL; -			} - -			mMediaImpl->mMimeTypeProbe = NULL; -		} -		mMediaImpl = NULL; -	} -	 -	 -public: -		LLViewerMediaImpl *mMediaImpl; -		bool mInitialized; -}; - -class LLViewerMediaOpenIDResponder : public LLHTTPClient::Responder -{ -	LOG_CLASS(LLViewerMediaOpenIDResponder); -public: -	LLViewerMediaOpenIDResponder( ) -	{ -	} - -	~LLViewerMediaOpenIDResponder() -	{ -	} - -	/* virtual */ void completedRaw( -		const LLChannelDescriptors& channels, -		const LLIOPipe::buffer_ptr_t& buffer) -	{ -		// We don't care about the content of the response, only the Set-Cookie header. -		LL_DEBUGS("MediaAuth") << dumpResponse()  -				<< " [headers:" << getResponseHeaders() << "]" << LL_ENDL; -		const std::string& cookie = getResponseHeader(HTTP_IN_HEADER_SET_COOKIE); -		 -		// *TODO: What about bad status codes?  Does this destroy previous cookies? -		LLViewerMedia::openIDCookieResponse(cookie); -	} - -}; - -class LLViewerMediaWebProfileResponder : public LLHTTPClient::Responder -{ -LOG_CLASS(LLViewerMediaWebProfileResponder); -public: -	LLViewerMediaWebProfileResponder(std::string host) -	{ -		mHost = host; -	} - -	~LLViewerMediaWebProfileResponder() -	{ -	} - -	 void completedRaw( -		const LLChannelDescriptors& channels, -		const LLIOPipe::buffer_ptr_t& buffer) -	{ -		// We don't care about the content of the response, only the set-cookie header. -		LL_WARNS("MediaAuth") << dumpResponse()  -				<< " [headers:" << getResponseHeaders() << "]" << LL_ENDL; - -		LLSD stripped_content = getResponseHeaders(); -		// *TODO: Check that this works. -		stripped_content.erase(HTTP_IN_HEADER_SET_COOKIE); -		LL_WARNS("MediaAuth") << stripped_content << LL_ENDL; - -		const std::string& cookie = getResponseHeader(HTTP_IN_HEADER_SET_COOKIE); -		LL_DEBUGS("MediaAuth") << "cookie = " << cookie << LL_ENDL; - -		// *TODO: What about bad status codes?  Does this destroy previous cookies? -		LLViewerMedia::getCookieStore()->setCookiesFromHost(cookie, mHost); - -		// Set cookie for snapshot publishing. -		std::string auth_cookie = cookie.substr(0, cookie.find(";")); // strip path -		LLWebProfile::setAuthCookie(auth_cookie); -	} - -	std::string mHost; -}; - -  LLPluginCookieStore *LLViewerMedia::sCookieStore = NULL;  LLURL LLViewerMedia::sOpenIDURL;  std::string LLViewerMedia::sOpenIDCookie; @@ -1394,81 +1211,154 @@ void LLViewerMedia::setOpenIDCookie()  {  	if(!sOpenIDCookie.empty())  	{ -		// The LLURL can give me the 'authority', which is of the form: [username[:password]@]hostname[:port] -		// We want just the hostname for the cookie code, but LLURL doesn't seem to have a way to extract that. -		// We therefore do it here. -		std::string authority = sOpenIDURL.mAuthority; -		std::string::size_type host_start = authority.find('@');  -		if(host_start == std::string::npos) -		{ -			// no username/password -			host_start = 0; -		} -		else -		{ -			// Hostname starts after the @.  -			// (If the hostname part is empty, this may put host_start at the end of the string.  In that case, it will end up passing through an empty hostname, which is correct.) -			++host_start; -		} -		std::string::size_type host_end = authority.rfind(':');  -		if((host_end == std::string::npos) || (host_end < host_start)) -		{ -			// no port -			host_end = authority.size(); -		} -		 -		getCookieStore()->setCookiesFromHost(sOpenIDCookie, authority.substr(host_start, host_end - host_start)); +        std::string profileUrl = getProfileURL(""); + +        LLCoros::instance().launch("LLViewerMedia::getOpenIDCookieCoro", +            boost::bind(&LLViewerMedia::getOpenIDCookieCoro, _1, profileUrl)); +	} +} -		// Do a web profile get so we can store the cookie  -		LLSD headers = LLSD::emptyMap(); -		headers[HTTP_OUT_HEADER_ACCEPT] = "*/*"; -		headers[HTTP_OUT_HEADER_COOKIE] = sOpenIDCookie; -		headers[HTTP_OUT_HEADER_USER_AGENT] = getCurrentUserAgent(); +/*static*/ +void LLViewerMedia::getOpenIDCookieCoro(LLCoros::self& self, std::string url) +{ +    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); +    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t +        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getOpenIDCookieCoro", httpPolicy)); +    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); +    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); +    LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders); +     +    httpOpts->setFollowRedirects(true); +    httpOpts->setWantHeaders(true); + +    LLURL hostUrl(url.c_str()); +    std::string hostAuth = hostUrl.getAuthority(); + +    // *TODO: Expand LLURL to split and extract this information better.  +    // The structure of a URL is well defined and needing to retrieve parts of it are common. +    // original comment: +    // The LLURL can give me the 'authority', which is of the form: [username[:password]@]hostname[:port] +    // We want just the hostname for the cookie code, but LLURL doesn't seem to have a way to extract that. +    // We therefore do it here. +    std::string authority = sOpenIDURL.mAuthority; +    std::string::size_type hostStart = authority.find('@'); +    if (hostStart == std::string::npos) +    {   // no username/password +        hostStart = 0; +    } +    else +    {   // Hostname starts after the @.  +        // (If the hostname part is empty, this may put host_start at the end of the string.  In that case, it will end up passing through an empty hostname, which is correct.) +        ++hostStart; +    } +    std::string::size_type hostEnd = authority.rfind(':'); +    if ((hostEnd == std::string::npos) || (hostEnd < hostStart)) +    {   // no port +        hostEnd = authority.size(); +    } -		std::string profile_url = getProfileURL(""); -		LLURL raw_profile_url( profile_url.c_str() ); +    getCookieStore()->setCookiesFromHost(sOpenIDCookie, authority.substr(hostStart, hostEnd - hostStart)); + +    // Do a web profile get so we can store the cookie  +    httpHeaders->append(HTTP_OUT_HEADER_ACCEPT, "*/*"); +    httpHeaders->append(HTTP_OUT_HEADER_COOKIE, sOpenIDCookie); +    httpHeaders->append(HTTP_OUT_HEADER_USER_AGENT, getCurrentUserAgent()); + + +    LL_DEBUGS("MediaAuth") << "Requesting " << url << LL_ENDL; +    LL_DEBUGS("MediaAuth") << "sOpenIDCookie = [" << sOpenIDCookie << "]" << LL_ENDL; +     +    LLSD result = httpAdapter->getRawAndYield(self, httpRequest, url, httpOpts, httpHeaders); + +    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; +    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + +    if (!status) +    { +        LL_WARNS("MediaAuth") << "Error getting web profile." << LL_ENDL; +        return; +    } + +    LLSD resultHeaders = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS]; +    if (!resultHeaders.has(HTTP_IN_HEADER_SET_COOKIE)) +    { +        LL_WARNS("MediaAuth") << "No cookie in response." << LL_ENDL; +        return; +    } + +    const std::string& cookie = resultHeaders[HTTP_IN_HEADER_SET_COOKIE].asStringRef(); +    LL_DEBUGS("MediaAuth") << "cookie = " << cookie << LL_ENDL; + +    // *TODO: What about bad status codes?  Does this destroy previous cookies? +    LLViewerMedia::getCookieStore()->setCookiesFromHost(cookie, hostAuth); + +    // Set cookie for snapshot publishing. +    std::string authCookie = cookie.substr(0, cookie.find(";")); // strip path +    LLWebProfile::setAuthCookie(authCookie); -		LL_DEBUGS("MediaAuth") << "Requesting " << profile_url << LL_ENDL; -		LL_DEBUGS("MediaAuth") << "sOpenIDCookie = [" << sOpenIDCookie << "]" << LL_ENDL; -		LLHTTPClient::get(profile_url,   -			new LLViewerMediaWebProfileResponder(raw_profile_url.getAuthority()), -			headers); -	}  }  /////////////////////////////////////////////////////////////////////////////////////////  // static -void LLViewerMedia::openIDSetup(const std::string &openid_url, const std::string &openid_token) +void LLViewerMedia::openIDSetup(const std::string &openidUrl, const std::string &openidToken)  { -	LL_DEBUGS("MediaAuth") << "url = \"" << openid_url << "\", token = \"" << openid_token << "\"" << LL_ENDL; +	LL_DEBUGS("MediaAuth") << "url = \"" << openidUrl << "\", token = \"" << openidToken << "\"" << LL_ENDL; -	// post the token to the url  -	// the responder will need to extract the cookie(s). +    LLCoros::instance().launch("LLViewerMedia::openIDSetupCoro", +        boost::bind(&LLViewerMedia::openIDSetupCoro, _1, openidUrl, openidToken)); +} -	// Save the OpenID URL for later -- we may need the host when adding the cookie. -	sOpenIDURL.init(openid_url.c_str()); -	 -	// We shouldn't ever do this twice, but just in case this code gets repurposed later, clear existing cookies. -	sOpenIDCookie.clear(); +/*static*/ +void LLViewerMedia::openIDSetupCoro(LLCoros::self& self, std::string openidUrl, std::string openidToken) +{ +    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); +    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t +        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("openIDSetupCoro", httpPolicy)); +    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); +    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); +    LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders); -	LLSD headers = LLSD::emptyMap(); -	// Keep LLHTTPClient from adding an "Accept: application/llsd+xml" header -	headers[HTTP_OUT_HEADER_ACCEPT] = "*/*"; -	// and use the expected content-type for a post, instead of the LLHTTPClient::postRaw() default of "application/octet-stream" -	headers[HTTP_OUT_HEADER_CONTENT_TYPE] = "application/x-www-form-urlencoded"; - -	// postRaw() takes ownership of the buffer and releases it later, so we need to allocate a new buffer here. -	size_t size = openid_token.size(); -	U8 *data = new U8[size]; -	memcpy(data, openid_token.data(), size); - -	LLHTTPClient::postRaw(  -		openid_url,  -		data,  -		size,  -		new LLViewerMediaOpenIDResponder(), -		headers); -			 +    httpOpts->setWantHeaders(true); + +    // post the token to the url  +    // the responder will need to extract the cookie(s). +    // Save the OpenID URL for later -- we may need the host when adding the cookie. +    sOpenIDURL.init(openidUrl.c_str()); +    // We shouldn't ever do this twice, but just in case this code gets repurposed later, clear existing cookies. +    sOpenIDCookie.clear(); + +    httpHeaders->append(HTTP_OUT_HEADER_ACCEPT, "*/*"); +    httpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, "application/x-www-form-urlencoded"); + +    LLCore::BufferArray::ptr_t rawbody(new LLCore::BufferArray, false); +    LLCore::BufferArrayStream bas(rawbody.get()); + +    bas << std::noskipws << openidToken; + +    LLSD result = httpAdapter->postRawAndYield(self, httpRequest, openidUrl, rawbody, httpOpts, httpHeaders); + +    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; +    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + +    if (!status) +    { +        LL_WARNS("MediaAuth") << "Error getting Open ID cookie" << LL_ENDL; +        return; +    } + +    LLSD resultHeaders = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS]; +    if (!resultHeaders.has(HTTP_IN_HEADER_SET_COOKIE)) +    { +        LL_WARNS("MediaAuth") << "No cookie in response." << LL_ENDL; +        return; +    } + +    // We don't care about the content of the response, only the Set-Cookie header. +    const std::string &cookie = resultHeaders[HTTP_IN_HEADER_SET_COOKIE]; + +    // *TODO: What about bad status codes?  Does this destroy previous cookies? +    LLViewerMedia::openIDCookieResponse(cookie); +    LL_DEBUGS("MediaAuth") << "OpenID cookie set." << LL_ENDL;  }  ///////////////////////////////////////////////////////////////////////////////////////// @@ -1661,7 +1551,6 @@ LLViewerMediaImpl::LLViewerMediaImpl(	  const LLUUID& texture_id,  	mIsParcelMedia(false),  	mProximity(-1),  	mProximityDistance(0.0f), -	mMimeTypeProbe(NULL),  	mMediaAutoPlay(false),  	mInNearbyMediaList(false),  	mClearCache(false), @@ -1671,8 +1560,10 @@ LLViewerMediaImpl::LLViewerMediaImpl(	  const LLUUID& texture_id,  	mIsUpdated(false),  	mTrustedBrowser(false),  	mZoomFactor(1.0), -    mCleanBrowser(false) -{  +    mCleanBrowser(false), +    mMimeProbe(), +    mCanceling(false) +{  	// Set up the mute list observer if it hasn't been set up already.  	if(!sViewerMediaMuteListObserverInitialized) @@ -2610,7 +2501,8 @@ void LLViewerMediaImpl::navigateInternal()  		return;  	} -	if(mMimeTypeProbe != NULL) +     +    if (!mMimeProbe.expired())  	{  		LL_WARNS() << "MIME type probe already in progress -- bailing out." << LL_ENDL;  		return; @@ -2648,14 +2540,8 @@ void LLViewerMediaImpl::navigateInternal()  		if(scheme.empty() || "http" == scheme || "https" == scheme)  		{ -			// If we don't set an Accept header, LLHTTPClient will add one like this: -			//    Accept: application/llsd+xml -			// which is really not what we want. -			LLSD headers = LLSD::emptyMap(); -			headers[HTTP_OUT_HEADER_ACCEPT] = "*/*"; -			// Allow cookies in the response, to prevent a redirect loop when accessing join.secondlife.com -			headers[HTTP_OUT_HEADER_COOKIE] = ""; -			LLHTTPClient::getHeaderOnly( mMediaURL, new LLMimeDiscoveryResponder(this), headers, 10.0f); +            LLCoros::instance().launch("LLViewerMediaImpl::mimeDiscoveryCoro", +                boost::bind(&LLViewerMediaImpl::mimeDiscoveryCoro, this, _1, mMediaURL));  		}  		else if("data" == scheme || "file" == scheme || "about" == scheme)  		{ @@ -2685,6 +2571,65 @@ void LLViewerMediaImpl::navigateInternal()  	}  } +void LLViewerMediaImpl::mimeDiscoveryCoro(LLCoros::self& self, std::string url) +{ +    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); +    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t +        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("mimeDiscoveryCoro", httpPolicy)); +    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); +    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); +    LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders); + +    mMimeProbe = httpAdapter; + +    httpOpts->setHeadersOnly(true); + +    httpHeaders->append(HTTP_OUT_HEADER_ACCEPT, "*/*"); +    httpHeaders->append(HTTP_OUT_HEADER_COOKIE, ""); + +    LLSD result = httpAdapter->getRawAndYield(self, httpRequest, url, httpOpts, httpHeaders); + +    mMimeProbe.reset(); + +    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; +    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + +    if (!status) +    { +        LL_WARNS() << "Error retrieving media headers." << LL_ENDL; +    } + +    LLSD resultHeaders = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS]; +     +    const std::string& mediaType = resultHeaders[HTTP_IN_HEADER_CONTENT_TYPE].asStringRef(); + +    std::string::size_type idx1 = mediaType.find_first_of(";"); +    std::string mimeType = mediaType.substr(0, idx1); + +    // We now no longer need to check the error code returned from the probe. +    // If we have a mime type, use it.  If not, default to the web plugin and let it handle error reporting. +    // The probe was successful. +    if (mimeType.empty()) +    { +        // Some sites don't return any content-type header at all. +        // Treat an empty mime type as text/html. +        mimeType = HTTP_CONTENT_TEXT_HTML; +    } + +    LL_DEBUGS() << "Media type \"" << mediaType << "\", mime type is \"" << mimeType << "\"" << LL_ENDL; + +    // the call to initializeMedia may disconnect the responder, which will clear mMediaImpl. +    // Make a local copy so we can call loadURI() afterwards. + +    if (!mimeType.empty()) +    { +        if (initializeMedia(mimeType)) +        { +            loadURI(); +        } +    } +} +  //////////////////////////////////////////////////////////////////////////////////////////  void LLViewerMediaImpl::navigateStop()  { @@ -2783,7 +2728,7 @@ void LLViewerMediaImpl::update()  		{  			// Don't load new instances that are at PRIORITY_SLIDESHOW or below.  They're just kept around to preserve state.  		} -		else if(mMimeTypeProbe != NULL) +        else if (!mMimeProbe.expired())  		{  			// this media source is doing a MIME type probe -- don't try loading it again.  		} @@ -3673,18 +3618,10 @@ void LLViewerMediaImpl::setNavigateSuspended(bool suspend)  void LLViewerMediaImpl::cancelMimeTypeProbe()  { -	if(mMimeTypeProbe != NULL) -	{ -		// There doesn't seem to be a way to actually cancel an outstanding request. -		// Simulate it by telling the LLMimeDiscoveryResponder not to write back any results. -		mMimeTypeProbe->cancelRequest(); -		 -		// The above should already have set mMimeTypeProbe to NULL. -		if(mMimeTypeProbe != NULL) -		{ -			LL_ERRS() << "internal error: mMimeTypeProbe is not NULL after cancelling request." << LL_ENDL; -		} -	} +    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t probeAdapter = mMimeProbe.lock(); + +    if (probeAdapter) +        probeAdapter->cancelYieldingOperation();  }  void LLViewerMediaImpl::addObject(LLVOVolume* obj)  diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 6803adfaa2..5658651c6e 100755 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -40,6 +40,9 @@  #include "llnotificationptr.h"  #include "llurl.h" +#include "lleventcoro.h" +#include "llcoros.h" +#include "llcorehttputil.h"  class LLViewerMediaImpl;  class LLUUID; @@ -165,7 +168,10 @@ public:  private:  	static void setOpenIDCookie();  	static void onTeleportFinished(); -	 + +    static void openIDSetupCoro(LLCoros::self& self, std::string openidUrl, std::string openidToken); +    static void getOpenIDCookieCoro(LLCoros::self& self, std::string url); +  	static LLPluginCookieStore *sCookieStore;  	static LLURL sOpenIDURL;  	static std::string sOpenIDCookie; @@ -180,7 +186,6 @@ class LLViewerMediaImpl  public:  	friend class LLViewerMedia; -	friend class LLMimeDiscoveryResponder;  	LLViewerMediaImpl(  		const LLUUID& texture_id, @@ -453,7 +458,6 @@ private:  	S32 mProximity;  	F64 mProximityDistance;  	F64 mProximityCamera; -	LLMimeDiscoveryResponder *mMimeTypeProbe;  	bool mMediaAutoPlay;  	std::string mMediaEntryURL;  	bool mInNearbyMediaList;	// used by LLPanelNearbyMedia::refreshList() for performance reasons @@ -470,6 +474,10 @@ private:  	BOOL mIsUpdated ;  	std::list< LLVOVolume* > mObjectList ; +    void mimeDiscoveryCoro(LLCoros::self& self, std::string url); +    LLCoreHttpUtil::HttpCoroutineAdapter::wptr_t mMimeProbe; +    bool mCanceling; +  private:  	LLViewerMediaTexture *updatePlaceholderImage();  }; diff --git a/indra/newview/llwebprofile.cpp b/indra/newview/llwebprofile.cpp index df5f4e3588..a72deafe33 100755 --- a/indra/newview/llwebprofile.cpp +++ b/indra/newview/llwebprofile.cpp @@ -202,7 +202,7 @@ void LLWebProfile::uploadImageCoro(LLCoros::self& self, LLPointer<LLImageFormatt  /*static*/  LLCore::BufferArray::ptr_t LLWebProfile::buildPostData(const LLSD &data, LLPointer<LLImageFormatted> &image, const std::string &boundary)  { -    LLCore::BufferArray::ptr_t body(new LLCore::BufferArray); +    LLCore::BufferArray::ptr_t body(new LLCore::BufferArray, false);      LLCore::BufferArrayStream bas(body.get());      // *NOTE: The order seems to matter. | 
