123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898 |
- /**
- * @file lltemplatemessagebuilder.cpp
- * @brief LLTemplateMessageBuilder class implementation.
- *
- * $LicenseInfo:firstyear=2007&license=viewergpl$
- *
- * Copyright (c) 2007-2009, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
- #include "linden_common.h"
- #include "lltemplatemessagebuilder.h"
- #include "llmessagetemplate.h"
- #include "llmath.h"
- #include "llquaternion.h"
- #include "llvector3d.h"
- #include "llvector3.h"
- #include "llvector4.h"
- LLTemplateMessageBuilder::LLTemplateMessageBuilder(const template_name_map_t& name_template_map)
- : mCurrentSMessageData(NULL),
- mCurrentSMessageTemplate(NULL),
- mCurrentSDataBlock(NULL),
- mCurrentSMessageName(NULL),
- mCurrentSBlockName(NULL),
- mSBuilt(false),
- mSClear(true),
- mCurrentSendTotal(0),
- mMessageTemplates(name_template_map)
- {
- }
- //virtual
- LLTemplateMessageBuilder::~LLTemplateMessageBuilder()
- {
- delete mCurrentSMessageData;
- mCurrentSMessageData = NULL;
- }
- //virtual
- void LLTemplateMessageBuilder::newMessage(const char* name)
- {
- mSBuilt = false;
- mSClear = false;
- mCurrentSendTotal = 0;
- if (mCurrentSMessageData)
- {
- delete mCurrentSMessageData;
- mCurrentSMessageData = NULL;
- }
- template_name_map_t::const_iterator it = mMessageTemplates.find(name);
- if (it == mMessageTemplates.end())
- {
- llerrs << "Message " << name << " not registered" << llendl;
- return;
- }
- mCurrentSMessageTemplate = it->second;
- mCurrentSMessageData = new LLMsgData(name);
- mCurrentSMessageName = (char*)name;
- mCurrentSDataBlock = NULL;
- mCurrentSBlockName = NULL;
- // Add at one of each block
- const LLMessageTemplate* msg_template =
- mMessageTemplates.find(name)->second;
- if (msg_template->getDeprecation() != MD_NOTDEPRECATED)
- {
- llwarns << "Sending deprecated message " << name << llendl;
- }
- for (LLMessageTemplate::message_block_map_t::const_iterator
- iter = msg_template->mMemberBlocks.begin(),
- end = msg_template->mMemberBlocks.end();
- iter != end; ++iter)
- {
- LLMessageBlock* ci = *iter;
- mCurrentSMessageData->addBlock(new LLMsgBlkData(ci->mName, 0));
- }
- }
- //virtual
- void LLTemplateMessageBuilder::clearMessage()
- {
- mSBuilt = false;
- mSClear = true;
- mCurrentSendTotal = 0;
- mCurrentSMessageTemplate = NULL;
- delete mCurrentSMessageData;
- mCurrentSMessageData = NULL;
- mCurrentSMessageName = NULL;
- mCurrentSDataBlock = NULL;
- mCurrentSBlockName = NULL;
- }
- //virtual
- void LLTemplateMessageBuilder::nextBlock(const char* blockname)
- {
- char* bnamep = (char*)blockname;
- if (!mCurrentSMessageTemplate)
- {
- llerrs << "newMessage not called prior to setBlock" << llendl;
- return;
- }
- // now, does this block exist ?
- const LLMessageBlock* template_data =
- mCurrentSMessageTemplate->getBlock(bnamep);
- if (!template_data)
- {
- llerrs << bnamep << " is not a block in "
- << mCurrentSMessageTemplate->mName << llendl;
- return;
- }
- // OK, have we already set this block ?
- LLMsgBlkData* block_data = mCurrentSMessageData->mMemberBlocks[bnamep];
- if (block_data->mBlockNumber == 0)
- {
- // nope ! set this as the current block
- block_data->mBlockNumber = 1;
- mCurrentSDataBlock = block_data;
- mCurrentSBlockName = bnamep;
- // add placeholders for each of the variables
- for (LLMessageBlock::message_variable_map_t::const_iterator
- iter = template_data->mMemberVariables.begin();
- iter != template_data->mMemberVariables.end(); ++iter)
- {
- LLMessageVariable& ci = **iter;
- mCurrentSDataBlock->addVariable(ci.getName(), ci.getType());
- }
- return;
- }
- else
- {
- // Already have this block; are we supposed to have a new one ?
- // if the block is type MBT_SINGLE this is bad !
- if (template_data->mType == MBT_SINGLE)
- {
- llerrs << "Call done multiple times for " << bnamep
- << " which is type MBT_SINGLE" << llendl;
- return;
- }
- // If the block is type MBT_MULTIPLE then we need a known number,
- // make sure that we're not exceeding it
- if (template_data->mType == MBT_MULTIPLE &&
- mCurrentSDataBlock->mBlockNumber == template_data->mNumber)
- {
- llerrs << "Called " << mCurrentSDataBlock->mBlockNumber
- << " times for " << bnamep << ", exceeding "
- << template_data->mNumber
- << " specified in type MBT_MULTIPLE." << llendl;
- return;
- }
- // OK, we can make a new one; modify the name to avoid name collision
- // by adding number to end.
- S32 count = block_data->mBlockNumber;
- // incrememt base name's count
- block_data->mBlockNumber++;
- if (block_data->mBlockNumber > MAX_BLOCKS)
- {
- llerrs << "Trying to pack too many blocks into MBT_VARIABLE type "
- << "(limited to " << MAX_BLOCKS << ")" << llendl;
- }
- // Create new name. NB: if things are working correctly, then
- // mCurrentMessageData->mMemberBlocks[blockname]->mBlockNumber ==
- // mCurrentDataBlock->mBlockNumber + 1
- char* nbnamep = bnamep + count;
- mCurrentSDataBlock = new LLMsgBlkData(bnamep, count);
- mCurrentSDataBlock->mName = nbnamep;
- mCurrentSMessageData->mMemberBlocks[nbnamep] = mCurrentSDataBlock;
- // Add placeholders for each of the variables
- for (LLMessageBlock::message_variable_map_t::const_iterator
- iter = template_data->mMemberVariables.begin(),
- end = template_data->mMemberVariables.end();
- iter != end; ++iter)
- {
- LLMessageVariable& ci = **iter;
- mCurrentSDataBlock->addVariable(ci.getName(), ci.getType());
- }
- }
- }
- // *TODO: Remove this horror...
- bool LLTemplateMessageBuilder::removeLastBlock()
- {
- if (!mCurrentSBlockName || !mCurrentSMessageData || !mCurrentSMessageTemplate ||
- mCurrentSMessageData->mMemberBlocks[mCurrentSBlockName]->mBlockNumber < 1)
- {
- return false;
- }
- // At least one block for the current block name.
- // Store the current block name for future reference.
- char* block_name = mCurrentSBlockName;
- // Decrement the sent total by the size of the data in the message block
- // that we are currently building.
- const LLMessageBlock* template_data =
- mCurrentSMessageTemplate->getBlock(mCurrentSBlockName);
- for (LLMessageBlock::message_variable_map_t::const_iterator
- iter = template_data->mMemberVariables.begin(),
- end = template_data->mMemberVariables.end();
- iter != end; ++iter)
- {
- LLMessageVariable& ci = **iter;
- mCurrentSendTotal -= ci.getSize();
- }
- // Now we want to find the block that we're blowing away.
- // Get the number of blocks.
- LLMsgBlkData* block_data = mCurrentSMessageData->mMemberBlocks[block_name];
- S32 num_blocks = block_data->mBlockNumber;
- // Use the same (suspect?) algorithm that's used to generate the names in
- // the nextBlock method to find it.
- char* block_getting_whacked = block_name + num_blocks - 1;
- LLMsgBlkData* whacked_data =
- mCurrentSMessageData->mMemberBlocks[block_getting_whacked];
- delete whacked_data;
- mCurrentSMessageData->mMemberBlocks.erase(block_getting_whacked);
- if (num_blocks <= 1)
- {
- // We just blew away the last one, so return false
- llwarns << "not blowing away the only block of message "
- << mCurrentSMessageName << ". Block: " << block_name
- << ". Number: " << num_blocks << llendl;
- return false;
- }
- // Decrement the counter.
- --block_data->mBlockNumber;
- return true;
- }
- // Add data to variable in current block
- void LLTemplateMessageBuilder::addData(const char* varname, const void* data,
- EMsgVariableType type, S32 size)
- {
- char* vnamep = (char*)varname;
- // Do we have a current message ?
- if (!mCurrentSMessageTemplate)
- {
- llerrs << "newMessage not called prior to addData" << llendl;
- return;
- }
- // Do we have a current block ?
- if (!mCurrentSDataBlock)
- {
- llerrs << "setBlock not called prior to addData" << llendl;
- return;
- }
- // Add the data if it exists
- const LLMessageVariable* var_data =
- mCurrentSMessageTemplate->getBlock(mCurrentSBlockName)->getVariable(vnamep);
- if (!var_data || !var_data->getName())
- {
- llerrs << vnamep << " not a variable in block " << mCurrentSBlockName
- << " of " << mCurrentSMessageTemplate->mName << llendl;
- return;
- }
- // Are we the correct size ?
- if (var_data->getType() == MVT_VARIABLE)
- {
- // Variable 1 can only store 255 bytes, make sure our data is smaller
- if (var_data->getSize() == 1 && size > 255)
- {
- llwarns_once << "Field " << varname
- << " is a Variable 1 (255 bytes max) but program attempted to stuff "
- << size << " bytes. Truncating data." << llendl;
- size = 255;
- char* truncate = (char*)data;
- // Array size is 255 but the last element index is 254
- truncate[254] = 0;
- }
- // No correct size for MVT_VARIABLE, instead we need to tell how many
- // bytes the size will be encoded as
- mCurrentSDataBlock->addData(vnamep, data, size, type,
- var_data->getSize());
- mCurrentSendTotal += size;
- }
- else
- {
- if (size != var_data->getSize())
- {
- llerrs << varname << " is type MVT_FIXED but request size "
- << size << " doesn't match template size "
- << var_data->getSize() << llendl;
- return;
- }
- // Alright, smash it in
- mCurrentSDataBlock->addData(vnamep, data, size, type);
- mCurrentSendTotal += size;
- }
- }
- // add data to variable in current block - fails if variable isn't MVT_FIXED
- void LLTemplateMessageBuilder::addData(const char* varname, const void* data,
- EMsgVariableType type)
- {
- char* vnamep = (char*)varname;
- // Do we have a current message ?
- if (!mCurrentSMessageTemplate)
- {
- llerrs << "newMessage not called prior to addData" << llendl;
- return;
- }
- // Do we have a current block ?
- if (!mCurrentSDataBlock)
- {
- llerrs << "setBlock not called prior to addData" << llendl;
- return;
- }
- // Add the data if it exists
- const LLMessageVariable* var_data =
- mCurrentSMessageTemplate->getBlock(mCurrentSBlockName)->getVariable(vnamep);
- if (!var_data->getName())
- {
- llerrs << vnamep << " not a variable in block " << mCurrentSBlockName
- << " of " << mCurrentSMessageTemplate->mName << llendl;
- return;
- }
- // Are we MVT_VARIABLE ?
- if (var_data->getType() == MVT_VARIABLE)
- {
- // nope
- llerrs << vnamep
- << " is type MVT_VARIABLE. Call using addData(name, data, size)"
- << llendl;
- return;
- }
- else
- {
- mCurrentSDataBlock->addData(vnamep, data, var_data->getSize(), type);
- mCurrentSendTotal += var_data->getSize();
- }
- }
- void LLTemplateMessageBuilder::addBinaryData(const char* varname,
- const void* data, S32 size)
- {
- addData(varname, data, MVT_FIXED, size);
- }
- void LLTemplateMessageBuilder::addS8(const char* varname, S8 s)
- {
- addData(varname, &s, MVT_S8, sizeof(s));
- }
- void LLTemplateMessageBuilder::addU8(const char* varname, U8 u)
- {
- addData(varname, &u, MVT_U8, sizeof(u));
- }
- void LLTemplateMessageBuilder::addS16(const char* varname, S16 i)
- {
- addData(varname, &i, MVT_S16, sizeof(i));
- }
- void LLTemplateMessageBuilder::addU16(const char* varname, U16 i)
- {
- addData(varname, &i, MVT_U16, sizeof(i));
- }
- void LLTemplateMessageBuilder::addF32(const char* varname, F32 f)
- {
- addData(varname, &f, MVT_F32, sizeof(f));
- }
- void LLTemplateMessageBuilder::addS32(const char* varname, S32 s)
- {
- addData(varname, &s, MVT_S32, sizeof(s));
- }
- void LLTemplateMessageBuilder::addU32(const char* varname, U32 u)
- {
- addData(varname, &u, MVT_U32, sizeof(u));
- }
- void LLTemplateMessageBuilder::addU64(const char* varname, U64 lu)
- {
- addData(varname, &lu, MVT_U64, sizeof(lu));
- }
- void LLTemplateMessageBuilder::addF64(const char* varname, F64 d)
- {
- addData(varname, &d, MVT_F64, sizeof(d));
- }
- void LLTemplateMessageBuilder::addIPAddr(const char* varname, U32 u)
- {
- addData(varname, &u, MVT_IP_ADDR, sizeof(u));
- }
- void LLTemplateMessageBuilder::addIPPort(const char* varname, U16 u)
- {
- u = htons(u);
- addData(varname, &u, MVT_IP_PORT, sizeof(u));
- }
- void LLTemplateMessageBuilder::addBool(const char* varname, bool b)
- {
- U8 temp = b;
- addData(varname, &temp, MVT_BOOL, sizeof(temp));
- }
- void LLTemplateMessageBuilder::addString(const char* varname, const char* s)
- {
- if (s)
- {
- addData(varname, (void*)s, MVT_VARIABLE, (S32)strlen(s) + 1);
- }
- else
- {
- addData(varname, NULL, MVT_VARIABLE, 0);
- }
- }
- void LLTemplateMessageBuilder::addString(const char* varname,
- const std::string& s)
- {
- if (s.size())
- {
- addData(varname, (void*)s.c_str(), MVT_VARIABLE, (S32)s.size() + 1);
- }
- else
- {
- addData(varname, NULL, MVT_VARIABLE, 0);
- }
- }
- void LLTemplateMessageBuilder::addVector3(const char* varname,
- const LLVector3& vec)
- {
- addData(varname, vec.mV, MVT_LLVector3, sizeof(vec.mV));
- }
- void LLTemplateMessageBuilder::addVector4(const char* varname,
- const LLVector4& vec)
- {
- addData(varname, vec.mV, MVT_LLVector4, sizeof(vec.mV));
- }
- void LLTemplateMessageBuilder::addVector3d(const char* varname,
- const LLVector3d& vec)
- {
- addData(varname, vec.mdV, MVT_LLVector3d, sizeof(vec.mdV));
- }
- void LLTemplateMessageBuilder::addQuat(const char* varname,
- const LLQuaternion& quat)
- {
- addData(varname, quat.packToVector3().mV, MVT_LLQuaternion,
- sizeof(LLVector3));
- }
- void LLTemplateMessageBuilder::addUUID(const char* varname, const LLUUID& uuid)
- {
- addData(varname, uuid.mData, MVT_LLUUID, sizeof(uuid.mData));
- }
- static S32 zero_code(U8** data, U32* data_size)
- {
- // Encoded send buffer needs to be slightly larger since the zero coding
- // can potentially increase the size of the send data.
- static U8 encodedSendBuffer[2 * MAX_BUFFER_SIZE];
- S32 count = *data_size;
- S32 net_gain = 0;
- U8 num_zeroes = 0;
- U8* inptr = (U8*)*data;
- U8* outptr = (U8*)encodedSendBuffer;
- // Skip the packet id field
- for (U32 ii = 0; ii < LL_PACKET_ID_SIZE ; ++ii)
- {
- --count;
- *outptr++ = *inptr++;
- }
- // Build encoded packet, keeping track of net size gain
- // Sequential zero bytes are encoded as 0 [U8 count] with 0 0 [count]
- // representing wrap (>256 zeroes)
- while (count--)
- {
- if (!(*inptr)) // in a zero count
- {
- if (num_zeroes)
- {
- if (++num_zeroes > 254)
- {
- *outptr++ = num_zeroes;
- num_zeroes = 0;
- }
- --net_gain; // subseqent zeroes save one
- }
- else
- {
- *outptr++ = 0;
- ++net_gain; // starting a zero count adds one
- num_zeroes = 1;
- }
- ++inptr;
- }
- else
- {
- if (num_zeroes)
- {
- *outptr++ = num_zeroes;
- num_zeroes = 0;
- }
- *outptr++ = *inptr++;
- }
- }
- if (num_zeroes)
- {
- *outptr++ = num_zeroes;
- }
- if (net_gain < 0)
- {
- #if 0 // *TODO: babbage: reinstate stat collecting...
- ++mCompressedPacketsOut;
- mUncompressedBytesOut += *data_size;
- #endif
- *data = encodedSendBuffer;
- *data_size += net_gain;
- // Set the head bit to indicate zero coding
- encodedSendBuffer[0] |= LL_ZERO_CODE_FLAG;
- #if 0 // *TODO: babbage: reinstate stat collecting...
- mCompressedBytesOut += *data_size;
- #endif
- }
- #if 0 // *TODO: babbage: reinstate stat collecting...
- mTotalBytesOut += *data_size;
- #endif
- return net_gain;
- }
- void LLTemplateMessageBuilder::compressMessage(U8*& buf_ptr, U32& buffer_size)
- {
- if (mCurrentSMessageTemplate->getEncoding() == ME_ZEROCODED)
- {
- zero_code(&buf_ptr, &buffer_size);
- }
- }
- bool LLTemplateMessageBuilder::isMessageFull(const char* blockname) const
- {
- if (mCurrentSendTotal > MTUBYTES)
- {
- return true;
- }
- if (!blockname)
- {
- return false;
- }
- char* bnamep = (char*)blockname;
- const LLMessageBlock* template_data =
- mCurrentSMessageTemplate->getBlock(bnamep);
- S32 max;
- switch (template_data->mType)
- {
- case MBT_SINGLE:
- max = 1;
- break;
- case MBT_MULTIPLE:
- max = template_data->mNumber;
- break;
- case MBT_VARIABLE:
- default:
- max = MAX_BLOCKS;
- }
- return mCurrentSMessageData->mMemberBlocks[bnamep]->mBlockNumber >= max;
- }
- static S32 buildBlock(U8* buffer, S32 buffer_size,
- const LLMessageBlock* template_data,
- LLMsgData* message_data)
- {
- S32 result = 0;
- LLMsgData::msg_blk_data_map_t::const_iterator block_iter;
- block_iter = message_data->mMemberBlocks.find(template_data->mName);
- const LLMsgBlkData* mbci = block_iter->second;
- // OK, if this is the first block of a repeating pack, set block_count and,
- // if it is type MBT_VARIABLE encode a byte for how many there are.
- S32 block_count = mbci->mBlockNumber;
- if (template_data->mType == MBT_VARIABLE)
- {
- // Remember that mBlockNumber is a S32
- U8 temp_block_number = (U8)mbci->mBlockNumber;
- if ((S32)(result + sizeof(U8)) < MAX_BUFFER_SIZE)
- {
- memcpy(&buffer[result], &temp_block_number, sizeof(U8));
- result += sizeof(U8);
- }
- else
- {
- // Just reporting error is likely not enough. Need to check how to
- // abort or error out gracefully from this function.
- llerrs << "buildBlock failed. Message excedding sendBuffersize."
- << llendl;
- }
- }
- else if (template_data->mType == MBT_MULTIPLE)
- {
- if (block_count != template_data->mNumber)
- {
- // Nope ! Need to fill it in all the way !
- llerrs << "Block " << mbci->mName
- << " is type MBT_MULTIPLE but only has data for "
- << block_count << " out of its "
- << template_data->mNumber << " blocks" << llendl;
- }
- }
- while (block_count > 0)
- {
- // Now loop through the variables
- for (LLMsgBlkData::msg_var_data_map_t::const_iterator
- iter = mbci->mMemberVarData.begin();
- iter != mbci->mMemberVarData.end(); iter++)
- {
- const LLMsgVarData& mvci = *iter;
- if (mvci.getSize() == -1)
- {
- // Oops, this variable was never set !
- llerrs << "The variable " << mvci.getName() << " in block "
- << mbci->mName << " of message " << template_data->mName
- << " was not set prior to buildMessage call" << llendl;
- }
- else
- {
- S32 data_size = mvci.getDataSize();
- if (data_size > 0)
- {
- // The type is MVT_VARIABLE, which means that we need to
- // encode a size argument. Otherwise, there is no need.
- S32 size = mvci.getSize();
- U8 sizeb;
- U16 sizeh;
- switch (data_size)
- {
- case 1:
- sizeb = size;
- htonmemcpy(&buffer[result], &sizeb, MVT_U8, 1);
- break;
- case 2:
- sizeh = size;
- htonmemcpy(&buffer[result], &sizeh, MVT_U16, 2);
- break;
- case 4:
- htonmemcpy(&buffer[result], &size, MVT_S32, 4);
- break;
- default:
- llerrs << "Attempting to build variable field with unknown size of "
- << size << llendl;
- break;
- }
- result += mvci.getDataSize();
- }
- // If there is any data to pack, pack it
- if (mvci.getData() != NULL && mvci.getSize())
- {
- if (result + mvci.getSize() < buffer_size)
- {
- memcpy(&buffer[result], mvci.getData(),
- mvci.getSize());
- result += mvci.getSize();
- }
- else
- {
- // Just reporting error is likely not enough. Need to
- // check how to abort or error out gracefully from this
- // function. XXXTBD
- llerrs << "Failed attempted to pack "
- << (result + mvci.getSize())
- << " bytes into a buffer with size "
- << buffer_size << "." << llendl;
- }
- }
- }
- }
- --block_count;
- if (block_iter != message_data->mMemberBlocks.end())
- {
- ++block_iter;
- if (block_iter != message_data->mMemberBlocks.end())
- {
- mbci = block_iter->second;
- }
- }
- }
- return result;
- }
- // Make sure that all the desired data is in place and then copy the data into
- // MAX_BUFFER_SIZEd buffer
- U32 LLTemplateMessageBuilder::buildMessage(U8* buffer, U32 buffer_size,
- U8 offset_to_data)
- {
- // Basic algorithm is to loop through the various pieces, building size and
- // offset info if we encounter a -1 for mSize at any point that variable
- // wasn't given data.
- // Do we have a current message ?
- if (!mCurrentSMessageTemplate)
- {
- llerrs << "newMessage not called prior to buildMessage" << llendl;
- return 0;
- }
- // Leave room for flags, packet sequence #, and data offset
- // information.
- buffer[PHL_OFFSET] = offset_to_data;
- U32 result = LL_PACKET_ID_SIZE;
- // Encode message number and adjust total_offset
- if (mCurrentSMessageTemplate->mFrequency == MFT_HIGH)
- {
- #if 0 // old, endian-dependant way
- memcpy(&buffer[result], &mCurrentMessageTemplate->mMessageNumber,
- sizeof(U8));
- #else // new, independant way
- buffer[result] = (U8)mCurrentSMessageTemplate->mMessageNumber;
- #endif
- result += sizeof(U8);
- }
- else if (mCurrentSMessageTemplate->mFrequency == MFT_MEDIUM)
- {
- U8 temp = 255;
- memcpy(&buffer[result], &temp, sizeof(U8));
- result += sizeof(U8);
- // Mask off unsightly bits
- temp = mCurrentSMessageTemplate->mMessageNumber & 255;
- memcpy(&buffer[result], &temp, sizeof(U8));
- result += sizeof(U8);
- }
- else if (mCurrentSMessageTemplate->mFrequency == MFT_LOW)
- {
- U8 temp = 255;
- U16 message_num;
- memcpy(&buffer[result], &temp, sizeof(U8));
- result += sizeof(U8);
- memcpy(&buffer[result], &temp, sizeof(U8));
- result += sizeof(U8);
- // Mask off unsightly bits
- message_num = mCurrentSMessageTemplate->mMessageNumber & 0xFFFF;
- // Convert to network byte order
- message_num = htons(message_num);
- memcpy(&buffer[result], &message_num, sizeof(U16));
- result += sizeof(U16);
- }
- else
- {
- llerrs << "unexpected message frequency in buildMessage" << llendl;
- return 0;
- }
- // Fast forward through the offset and build the message
- result += offset_to_data;
- for (LLMessageTemplate::message_block_map_t::const_iterator
- iter = mCurrentSMessageTemplate->mMemberBlocks.begin(),
- end = mCurrentSMessageTemplate->mMemberBlocks.end();
- iter != end;
- ++iter)
- {
- result += buildBlock(buffer + result, buffer_size - result, *iter,
- mCurrentSMessageData);
- }
- mSBuilt = true;
- return result;
- }
- void LLTemplateMessageBuilder::copyFromMessageData(const LLMsgData& data)
- {
- // Counting variables used to encode multiple block info
- S32 block_count = 0;
- char* block_name = NULL;
- // Loop through msg blocks to loop through variables, totalling up size
- // data and filling the new (send) message
- for (LLMsgData::msg_blk_data_map_t::const_iterator
- iter = data.mMemberBlocks.begin(),
- end = data.mMemberBlocks.end();
- iter != end; ++iter)
- {
- const LLMsgBlkData* mbci = iter->second;
- if (!mbci) continue;
- // Do we need to encode a block code ?
- if (block_count == 0)
- {
- block_count = mbci->mBlockNumber;
- block_name = (char*)mbci->mName;
- }
- // Counting down mutliple blocks
- --block_count;
- nextBlock(block_name);
- // Now loop through the variables
- for (LLMsgBlkData::msg_var_data_map_t::const_iterator
- dit = mbci->mMemberVarData.begin(),
- dend = mbci->mMemberVarData.end();
- dit != dend; ++dit)
- {
- const LLMsgVarData& mvci = *dit;
- addData(mvci.getName(), mvci.getData(), mvci.getType(),
- mvci.getSize());
- }
- }
- }
|