summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorprep <prep@lindenlab.com>2012-02-22 12:00:37 -0500
committerprep <prep@lindenlab.com>2012-02-22 12:00:37 -0500
commit95aa437160ef732d584868a7d37cbe55d5959fa0 (patch)
tree9206af968a68976b1c65556f5793c2ee67c38469 /indra
parent06970dd907db7a7c5ebe950c0e74e10bab13483d (diff)
Path-305: Added support for retrieving compressed navmeshes in a LLSD.
Diffstat (limited to 'indra')
-rw-r--r--indra/llcommon/llsdserialize.cpp83
-rw-r--r--indra/llcommon/llsdserialize.h2
-rw-r--r--indra/newview/llnavmeshstation.cpp51
3 files changed, 122 insertions, 14 deletions
diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp
index bf62600514..4722421fca 100644
--- a/indra/llcommon/llsdserialize.cpp
+++ b/indra/llcommon/llsdserialize.cpp
@@ -55,6 +55,10 @@ static const char LEGACY_NON_HEADER[] = "<llsd>";
const std::string LLSD_BINARY_HEADER("LLSD/Binary");
const std::string LLSD_XML_HEADER("LLSD/XML");
+//used to deflate a gzipped asset (currently used for navmeshes)
+#define windowBits 15
+#define ENABLE_ZLIB_GZIP 32
+
/**
* LLSDSerialize
*/
@@ -2096,7 +2100,7 @@ bool unzip_llsd(LLSD& data, std::istream& is, S32 size)
strm.next_in = in;
S32 ret = inflateInit(&strm);
-
+
do
{
strm.avail_out = CHUNK;
@@ -2159,12 +2163,87 @@ bool unzip_llsd(LLSD& data, std::istream& is, S32 size)
llwarns << "Failed to unzip LLSD block" << llendl;
free(result);
return false;
- }
+ }
}
free(result);
return true;
}
+//This unzip function will only work with a gzip header and trailer - while the contents
+//of the actual compressed data is the same for either format (gzip vs zlib ), the headers
+//and trailers are different for the formats.
+U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, std::istream& is, S32 size )
+{
+ U8* result = NULL;
+ U32 cur_size = 0;
+ z_stream strm;
+
+ const U32 CHUNK = 0x4000;
+ U8 *in = new U8[size];
+ is.read((char*) in, size);
+
+ U8 out[CHUNK];
+
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+ strm.avail_in = size;
+ strm.next_in = in;
+
+
+ S32 ret = inflateInit2(&strm, windowBits | ENABLE_ZLIB_GZIP );
+ do
+ {
+ strm.avail_out = CHUNK;
+ strm.next_out = out;
+ ret = inflate(&strm, Z_NO_FLUSH);
+ if (ret == Z_STREAM_ERROR)
+ {
+ inflateEnd(&strm);
+ free(result);
+ delete [] in;
+ valid = false;
+ }
+
+ switch (ret)
+ {
+ case Z_NEED_DICT:
+ ret = Z_DATA_ERROR;
+ case Z_DATA_ERROR:
+ case Z_MEM_ERROR:
+ inflateEnd(&strm);
+ free(result);
+ delete [] in;
+ valid = false;
+ break;
+ }
+
+ U32 have = CHUNK-strm.avail_out;
+
+ result = (U8*) realloc(result, cur_size + have);
+ memcpy(result+cur_size, out, have);
+ cur_size += have;
+
+ } while (ret == Z_OK);
+
+ inflateEnd(&strm);
+ delete [] in;
+
+ if (ret != Z_STREAM_END)
+ {
+ free(result);
+ valid = false;
+ return NULL;
+ }
+
+ //result now points to the decompressed LLSD block
+ {
+ outsize= cur_size;
+ valid = true;
+ }
+
+ return result;
+}
diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h
index 99a3ea3cd4..86e3fc864c 100644
--- a/indra/llcommon/llsdserialize.h
+++ b/indra/llcommon/llsdserialize.h
@@ -793,5 +793,5 @@ public:
//dirty little zip functions -- yell at davep
LL_COMMON_API std::string zip_llsd(LLSD& data);
LL_COMMON_API bool unzip_llsd(LLSD& data, std::istream& is, S32 size);
-
+LL_COMMON_API U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize,std::istream& is, S32 size);
#endif // LL_LLSDSERIALIZE_H
diff --git a/indra/newview/llnavmeshstation.cpp b/indra/newview/llnavmeshstation.cpp
index 87f7e92ddd..54a945e562 100644
--- a/indra/newview/llnavmeshstation.cpp
+++ b/indra/newview/llnavmeshstation.cpp
@@ -32,7 +32,7 @@
#include "llviewerregion.h"
#include "llsdutil.h"
#include "llfloaterpathfindingconsole.h"
-
+#include "llsdserialize.h"
//===============================================================================
LLNavMeshStation::LLNavMeshStation()
{
@@ -48,8 +48,7 @@ public:
}
void error( U32 statusNum, const std::string& reason )
- {
- //statusNum;
+ {
llwarns << "Transport error "<<reason<<llendl;
}
@@ -65,23 +64,53 @@ public:
{
LLNavMeshDownloadObserver* pObserver = mObserverHandle.get();
if ( pObserver )
- {
-
+ {
if ( content.has("navmesh_data") )
{
- const LLSD::Binary& stuff = content["navmesh_data"].asBinary();
- LLPathingLib::getInstance()->extractNavMeshSrcFromLLSD( stuff, mDir );
- pObserver->getPathfindingConsole()->setHasNavMeshReceived();
+ const std::vector<U8>& value = content["navmesh_data"].asBinary();
+ unsigned int binSize = value.size();
+ U8* pBinBuffer = new U8[binSize];
+ memcpy( &pBinBuffer[0], &value[0], binSize );
+ std::string newStr((char*) pBinBuffer, binSize );
+ std::istringstream streamdecomp( newStr );
+ unsigned int decompBinSize = 0;
+ bool valid = false;
+ if ( pBinBuffer )
+ {
+ delete [] pBinBuffer ;
+ }
+ U8* pUncompressedNavMeshContainer = unzip_llsdNavMesh( valid, decompBinSize, streamdecomp, binSize ) ;
+ if ( !valid )
+ {
+ if ( pUncompressedNavMeshContainer )
+ {
+ free( pUncompressedNavMeshContainer );
+ }
+ llwarns << "Unable to decompress the navmesh llsd." << llendl;
+ pObserver->getPathfindingConsole()->setHasNoNavMesh();
+ return;
+ }
+ else
+ {
+ if ( pUncompressedNavMeshContainer )
+ {
+ std::vector<U8> lsd;
+ lsd.resize( decompBinSize );
+ memcpy( &lsd[0], &pUncompressedNavMeshContainer[0], decompBinSize );
+ LLPathingLib::getInstance()->extractNavMeshSrcFromLLSD( lsd, mDir );
+ pObserver->getPathfindingConsole()->setHasNavMeshReceived();
+ free( pUncompressedNavMeshContainer );
+ }
+ }
}
else
{
- llwarns<<"no mesh data "<<llendl;
+ llwarns<<"No mesh data received"<<llendl;
pObserver->getPathfindingConsole()->setHasNoNavMesh();
}
}
}
-}
-
+}
private:
//Observer handle
LLHandle<LLNavMeshDownloadObserver> mObserverHandle;