summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorRider Linden <rider@lindenlab.com>2015-05-27 17:15:01 -0700
committerRider Linden <rider@lindenlab.com>2015-05-27 17:15:01 -0700
commit83543e556cba8753077c9f004bb0dc71b4509007 (patch)
treedb3a0f30e486475f72ddf945a5a6263b1219a4a0 /indra
parent9134a3a097607e427b18af010774eb842be893f2 (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-xindra/llcorehttp/_httpoprequest.cpp8
-rwxr-xr-xindra/llcorehttp/httpoptions.cpp29
-rwxr-xr-xindra/llcorehttp/httpoptions.h10
-rw-r--r--indra/llmessage/llcorehttputil.cpp12
-rw-r--r--indra/llmessage/llcorehttputil.h13
-rwxr-xr-xindra/newview/llviewermedia.cpp483
-rwxr-xr-xindra/newview/llviewermedia.h14
-rwxr-xr-xindra/newview/llwebprofile.cpp2
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.