From 202deea1a2480f5a18553f6e60e797a5f2582eb6 Mon Sep 17 00:00:00 2001 From: thickbrick Date: Thu, 14 Oct 2010 20:22:23 +0200 Subject: More robust handling of http texture responses. Specifically allow for status 416 (unsatisfiable range) and scuessful responses without status 216 (i.e. whole file at once). This *should* allow this to work on different servers, as long as they comply with RFC 2616 WRT range requests. --- linden/indra/newview/lltexturefetch.cpp | 97 +++++++++++++++++++++++---------- 1 file changed, 68 insertions(+), 29 deletions(-) (limited to 'linden') diff --git a/linden/indra/newview/lltexturefetch.cpp b/linden/indra/newview/lltexturefetch.cpp index bf97584..80e3bfc 100644 --- a/linden/indra/newview/lltexturefetch.cpp +++ b/linden/indra/newview/lltexturefetch.cpp @@ -157,7 +157,7 @@ public: void callbackHttpGet(const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer, - bool last_block, bool success); + bool partial, bool unsatisfiable, bool success); void callbackCacheRead(bool success, LLImageFormatted* image, S32 imagesize, BOOL islocal); void callbackCacheWrite(bool success); @@ -324,6 +324,7 @@ public: { bool success = false; bool partial = false; + bool unsatisfiable = false; if (200 <= status && status < 300) { success = true; @@ -332,18 +333,19 @@ public: partial = true; } } - else + else if (status == HTTP_REQUESTED_RANGE_NOT_SATISFIABLE) { - worker->setGetStatus(status, reason); -// llwarns << status << ": " << reason << llendl; + LL_DEBUGS("TextureFetch") << "Request was an unsatisfiable range: mRequestedSize=" << mRequestedSize << " mOffset=" << mOffset << " for: " << mID << LL_ENDL; + unsatisfiable = true; } + if (!success) { worker->setGetStatus(status, reason); // llwarns << "CURL GET FAILED, status:" << status << " reason:" << reason << llendl; } mFetcher->removeFromHTTPQueue(mID); - worker->callbackHttpGet(channels, buffer, partial, success); + worker->callbackHttpGet(channels, buffer, partial, unsatisfiable, success); } else { @@ -1301,7 +1303,9 @@ bool LLTextureFetchWorker::processSimulatorPackets() void LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer, - bool last_block, bool success) + bool partial, + bool unsatisfiable, + bool success) { LLMutexLock lock(&mWorkMutex); @@ -1316,56 +1320,91 @@ void LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels, llwarns << "Duplicate callback for " << mID.asString() << llendl; return; // ignore duplicate callback } + + S32 data_size = 0; if (success) { // get length of stream: - S32 data_size = buffer->countAfter(channels.in(), NULL); + data_size = buffer->countAfter(channels.in(), NULL); gImageList.sTextureBits += data_size * 8; // Approximate - does not include header bits LL_DEBUGS("TextureFetch") << "HTTP RECEIVED: " << mID.asString() << " Bytes: " << data_size << " mRequestedSize: " << mRequestedSize << LL_ENDL; + if (data_size > 0) { - // *TODO: set the formatted image data here directly to avoid the copy - mBuffer = new U8[data_size]; - buffer->readAfter(channels.in(), NULL, mBuffer, data_size); - mBufferSize += data_size; - if (data_size < mRequestedSize) + bool clean_data = false; + bool done = false; + if (!partial) { - // We requested whole image (by discard or by size,) so assume we got it - mHaveAllData = TRUE; - mRequestedDiscard = 0; + // we got the whole image in one go + done = true; + clean_data = true; + } + else if (data_size < mRequestedSize) + { + // we have the whole image + done = true; + } + else if (data_size == mRequestedSize) + { + if (mRequestedDiscard <= 0) + { + done = true; + } + else + { + // this is the normal case where we get the data we requested, + // but still need to request more data. + } } else if (data_size > mRequestedSize) { // *TODO: This shouldn't be happening any more llwarns << "data_size = " << data_size << " > requested: " << mRequestedSize << llendl; - mHaveAllData = TRUE; + done = true; + clean_data = true; llassert_always(mDecodeHandle == 0); - mFormattedImage = NULL; // discard any previous data we had - mBufferSize = data_size; } - mRequestedSize = data_size; - } - else - { - // We requested data but received none (and no error), - if (mFormattedImage.notNull() && mFormattedImage->getDataSize() > 0) + + if (clean_data) { - // but have earlier data, so presumably we have it all. - mRequestedSize = 0; - mHaveAllData = TRUE; + resetFormattedData(); // discard any previous data we had + llassert(mBufferSize == 0); } - else + if (done) { - mRequestedSize = -1; // treat this fetch as if it failed. + mHaveAllData = TRUE; + mRequestedDiscard = 0; } + + // *TODO: set the formatted image data here directly to avoid the copy + mBuffer = new U8[data_size]; + buffer->readAfter(channels.in(), NULL, mBuffer, data_size); + mBufferSize += data_size; + mRequestedSize = data_size; + } + } + + if ((success && (data_size == 0)) || unsatisfiable) + { + if (mFormattedImage.notNull() && mFormattedImage->getDataSize() > 0) + { + // we already have some data, so we'll assume we have it all + mRequestedSize = 0; + mRequestedDiscard = 0; + mHaveAllData = TRUE; + } + else + { + mRequestedSize = -1; // treat this fetch as if it failed. } } else { mRequestedSize = -1; // error } + mLoaded = TRUE; setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); } -- cgit v1.1