diff options
author | thickbrick | 2010-10-14 20:22:23 +0200 |
---|---|---|
committer | thickbrick | 2010-10-14 20:22:23 +0200 |
commit | 202deea1a2480f5a18553f6e60e797a5f2582eb6 (patch) | |
tree | ec90d66be694572079a3cc0979ff05977e1d159f /linden | |
parent | Don't try to fetch http-textures past end of file (diff) | |
download | meta-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.cpp | 97 |
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 | ||
1302 | void LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels, | 1304 | void 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 | } |