aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden
diff options
context:
space:
mode:
authorthickbrick2010-10-14 20:22:23 +0200
committerthickbrick2010-10-14 20:22:23 +0200
commit202deea1a2480f5a18553f6e60e797a5f2582eb6 (patch)
treeec90d66be694572079a3cc0979ff05977e1d159f /linden
parentDon't try to fetch http-textures past end of file (diff)
downloadmeta-impy-202deea1a2480f5a18553f6e60e797a5f2582eb6.zip
meta-impy-202deea1a2480f5a18553f6e60e797a5f2582eb6.tar.gz
meta-impy-202deea1a2480f5a18553f6e60e797a5f2582eb6.tar.bz2
meta-impy-202deea1a2480f5a18553f6e60e797a5f2582eb6.tar.xz
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.
Diffstat (limited to 'linden')
-rw-r--r--linden/indra/newview/lltexturefetch.cpp97
1 files changed, 68 insertions, 29 deletions
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:
157 157
158 void callbackHttpGet(const LLChannelDescriptors& channels, 158 void callbackHttpGet(const LLChannelDescriptors& channels,
159 const LLIOPipe::buffer_ptr_t& buffer, 159 const LLIOPipe::buffer_ptr_t& buffer,
160 bool last_block, bool success); 160 bool partial, bool unsatisfiable, bool success);
161 void callbackCacheRead(bool success, LLImageFormatted* image, 161 void callbackCacheRead(bool success, LLImageFormatted* image,
162 S32 imagesize, BOOL islocal); 162 S32 imagesize, BOOL islocal);
163 void callbackCacheWrite(bool success); 163 void callbackCacheWrite(bool success);
@@ -324,6 +324,7 @@ public:
324 { 324 {
325 bool success = false; 325 bool success = false;
326 bool partial = false; 326 bool partial = false;
327 bool unsatisfiable = false;
327 if (200 <= status && status < 300) 328 if (200 <= status && status < 300)
328 { 329 {
329 success = true; 330 success = true;
@@ -332,18 +333,19 @@ public:
332 partial = true; 333 partial = true;
333 } 334 }
334 } 335 }
335 else 336 else if (status == HTTP_REQUESTED_RANGE_NOT_SATISFIABLE)
336 { 337 {
337 worker->setGetStatus(status, reason); 338 LL_DEBUGS("TextureFetch") << "Request was an unsatisfiable range: mRequestedSize=" << mRequestedSize << " mOffset=" << mOffset << " for: " << mID << LL_ENDL;
338// llwarns << status << ": " << reason << llendl; 339 unsatisfiable = true;
339 } 340 }
341
340 if (!success) 342 if (!success)
341 { 343 {
342 worker->setGetStatus(status, reason); 344 worker->setGetStatus(status, reason);
343// llwarns << "CURL GET FAILED, status:" << status << " reason:" << reason << llendl; 345// llwarns << "CURL GET FAILED, status:" << status << " reason:" << reason << llendl;
344 } 346 }
345 mFetcher->removeFromHTTPQueue(mID); 347 mFetcher->removeFromHTTPQueue(mID);
346 worker->callbackHttpGet(channels, buffer, partial, success); 348 worker->callbackHttpGet(channels, buffer, partial, unsatisfiable, success);
347 } 349 }
348 else 350 else
349 { 351 {
@@ -1301,7 +1303,9 @@ bool LLTextureFetchWorker::processSimulatorPackets()
1301 1303
1302void LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels, 1304void LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels,
1303 const LLIOPipe::buffer_ptr_t& buffer, 1305 const LLIOPipe::buffer_ptr_t& buffer,
1304 bool last_block, bool success) 1306 bool partial,
1307 bool unsatisfiable,
1308 bool success)
1305{ 1309{
1306 LLMutexLock lock(&mWorkMutex); 1310 LLMutexLock lock(&mWorkMutex);
1307 1311
@@ -1316,56 +1320,91 @@ void LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels,
1316 llwarns << "Duplicate callback for " << mID.asString() << llendl; 1320 llwarns << "Duplicate callback for " << mID.asString() << llendl;
1317 return; // ignore duplicate callback 1321 return; // ignore duplicate callback
1318 } 1322 }
1323
1324 S32 data_size = 0;
1319 if (success) 1325 if (success)
1320 { 1326 {
1321 // get length of stream: 1327 // get length of stream:
1322 S32 data_size = buffer->countAfter(channels.in(), NULL); 1328 data_size = buffer->countAfter(channels.in(), NULL);
1323 1329
1324 gImageList.sTextureBits += data_size * 8; // Approximate - does not include header bits 1330 gImageList.sTextureBits += data_size * 8; // Approximate - does not include header bits
1325 1331
1326 LL_DEBUGS("TextureFetch") << "HTTP RECEIVED: " << mID.asString() << " Bytes: " << data_size << " mRequestedSize: " << mRequestedSize << LL_ENDL; 1332 LL_DEBUGS("TextureFetch") << "HTTP RECEIVED: " << mID.asString() << " Bytes: " << data_size << " mRequestedSize: " << mRequestedSize << LL_ENDL;
1333
1327 if (data_size > 0) 1334 if (data_size > 0)
1328 { 1335 {
1329 // *TODO: set the formatted image data here directly to avoid the copy 1336 bool clean_data = false;
1330 mBuffer = new U8[data_size]; 1337 bool done = false;
1331 buffer->readAfter(channels.in(), NULL, mBuffer, data_size); 1338 if (!partial)
1332 mBufferSize += data_size;
1333 if (data_size < mRequestedSize)
1334 { 1339 {
1335 // We requested whole image (by discard or by size,) so assume we got it 1340 // we got the whole image in one go
1336 mHaveAllData = TRUE; 1341 done = true;
1337 mRequestedDiscard = 0; 1342 clean_data = true;
1343 }
1344 else if (data_size < mRequestedSize)
1345 {
1346 // we have the whole image
1347 done = true;
1348 }
1349 else if (data_size == mRequestedSize)
1350 {
1351 if (mRequestedDiscard <= 0)
1352 {
1353 done = true;
1354 }
1355 else
1356 {
1357 // this is the normal case where we get the data we requested,
1358 // but still need to request more data.
1359 }
1338 } 1360 }
1339 else if (data_size > mRequestedSize) 1361 else if (data_size > mRequestedSize)
1340 { 1362 {
1341 // *TODO: This shouldn't be happening any more 1363 // *TODO: This shouldn't be happening any more
1342 llwarns << "data_size = " << data_size << " > requested: " << mRequestedSize << llendl; 1364 llwarns << "data_size = " << data_size << " > requested: " << mRequestedSize << llendl;
1343 mHaveAllData = TRUE; 1365 done = true;
1366 clean_data = true;
1344 llassert_always(mDecodeHandle == 0); 1367 llassert_always(mDecodeHandle == 0);
1345 mFormattedImage = NULL; // discard any previous data we had
1346 mBufferSize = data_size;
1347 } 1368 }
1348 mRequestedSize = data_size; 1369
1349 } 1370 if (clean_data)
1350 else
1351 {
1352 // We requested data but received none (and no error),
1353 if (mFormattedImage.notNull() && mFormattedImage->getDataSize() > 0)
1354 { 1371 {
1355 // but have earlier data, so presumably we have it all. 1372 resetFormattedData(); // discard any previous data we had
1356 mRequestedSize = 0; 1373 llassert(mBufferSize == 0);
1357 mHaveAllData = TRUE;
1358 } 1374 }
1359 else 1375 if (done)
1360 { 1376 {
1361 mRequestedSize = -1; // treat this fetch as if it failed. 1377 mHaveAllData = TRUE;
1378 mRequestedDiscard = 0;
1362 } 1379 }
1380
1381 // *TODO: set the formatted image data here directly to avoid the copy
1382 mBuffer = new U8[data_size];
1383 buffer->readAfter(channels.in(), NULL, mBuffer, data_size);
1384 mBufferSize += data_size;
1385 mRequestedSize = data_size;
1386 }
1387 }
1388
1389 if ((success && (data_size == 0)) || unsatisfiable)
1390 {
1391 if (mFormattedImage.notNull() && mFormattedImage->getDataSize() > 0)
1392 {
1393 // we already have some data, so we'll assume we have it all
1394 mRequestedSize = 0;
1395 mRequestedDiscard = 0;
1396 mHaveAllData = TRUE;
1397 }
1398 else
1399 {
1400 mRequestedSize = -1; // treat this fetch as if it failed.
1363 } 1401 }
1364 } 1402 }
1365 else 1403 else
1366 { 1404 {
1367 mRequestedSize = -1; // error 1405 mRequestedSize = -1; // error
1368 } 1406 }
1407
1369 mLoaded = TRUE; 1408 mLoaded = TRUE;
1370 setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); 1409 setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
1371} 1410}