PageRenderTime 66ms CodeModel.GetById 8ms app.highlight 51ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llmessage/lltemplatemessagebuilder.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 895 lines | 641 code | 123 blank | 131 comment | 95 complexity | 9e8ee59426a43f37f17ef01a3f1e43b7 MD5 | raw file
  1/** 
  2 * @file lltemplatemessagebuilder.cpp
  3 * @brief LLTemplateMessageBuilder class implementation.
  4 *
  5 * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  6 * Second Life Viewer Source Code
  7 * Copyright (C) 2010, Linden Research, Inc.
  8 * 
  9 * This library is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU Lesser General Public
 11 * License as published by the Free Software Foundation;
 12 * version 2.1 of the License only.
 13 * 
 14 * This library is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17 * Lesser General Public License for more details.
 18 * 
 19 * You should have received a copy of the GNU Lesser General Public
 20 * License along with this library; if not, write to the Free Software
 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 22 * 
 23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 24 * $/LicenseInfo$
 25 */
 26
 27#include "linden_common.h"
 28
 29#include "lltemplatemessagebuilder.h"
 30
 31#include "llmessagetemplate.h"
 32#include "llmath.h"
 33#include "llquaternion.h"
 34#include "u64.h"
 35#include "v3dmath.h"
 36#include "v3math.h"
 37#include "v4math.h"
 38
 39LLTemplateMessageBuilder::LLTemplateMessageBuilder(const message_template_name_map_t& name_template_map) :
 40	mCurrentSMessageData(NULL),
 41	mCurrentSMessageTemplate(NULL),
 42	mCurrentSDataBlock(NULL),
 43	mCurrentSMessageName(NULL),
 44	mCurrentSBlockName(NULL),
 45	mbSBuilt(FALSE),
 46	mbSClear(TRUE),
 47	mCurrentSendTotal(0),
 48	mMessageTemplates(name_template_map)
 49{
 50}
 51
 52//virtual
 53LLTemplateMessageBuilder::~LLTemplateMessageBuilder()
 54{
 55	delete mCurrentSMessageData;
 56	mCurrentSMessageData = NULL;
 57}
 58
 59// virtual
 60void LLTemplateMessageBuilder::newMessage(const char *name)
 61{
 62	mbSBuilt = FALSE;
 63	mbSClear = FALSE;
 64
 65	mCurrentSendTotal = 0;
 66
 67	delete mCurrentSMessageData;
 68	mCurrentSMessageData = NULL;
 69
 70	char* namep = (char*)name; 
 71	if (mMessageTemplates.count(namep) > 0)
 72	{
 73		mCurrentSMessageTemplate = mMessageTemplates.find(name)->second;
 74		mCurrentSMessageData = new LLMsgData(namep);
 75		mCurrentSMessageName = namep;
 76		mCurrentSDataBlock = NULL;
 77		mCurrentSBlockName = NULL;
 78
 79		// add at one of each block
 80		const LLMessageTemplate* msg_template = mMessageTemplates.find(name)->second;
 81
 82		if (msg_template->getDeprecation() != MD_NOTDEPRECATED)
 83		{
 84			llwarns << "Sending deprecated message " << namep << llendl;
 85		}
 86		
 87		LLMessageTemplate::message_block_map_t::const_iterator iter;
 88		for(iter = msg_template->mMemberBlocks.begin();
 89			iter != msg_template->mMemberBlocks.end();
 90			++iter)
 91		{
 92			LLMessageBlock* ci = *iter;
 93			LLMsgBlkData* tblockp = new LLMsgBlkData(ci->mName, 0);
 94			mCurrentSMessageData->addBlock(tblockp);
 95		}
 96	}
 97	else
 98	{
 99		llerrs << "newMessage - Message " << name << " not registered" << llendl;
100	}
101}
102
103// virtual
104void LLTemplateMessageBuilder::clearMessage()
105{
106	mbSBuilt = FALSE;
107	mbSClear = TRUE;
108
109	mCurrentSendTotal = 0;
110
111	mCurrentSMessageTemplate = NULL;
112
113	delete mCurrentSMessageData;
114	mCurrentSMessageData = NULL;
115
116	mCurrentSMessageName = NULL;
117	mCurrentSDataBlock = NULL;
118	mCurrentSBlockName = NULL;
119}
120
121// virtual
122void LLTemplateMessageBuilder::nextBlock(const char* blockname)
123{
124	char *bnamep = (char *)blockname; 
125
126	if (!mCurrentSMessageTemplate)
127	{
128		llerrs << "newMessage not called prior to setBlock" << llendl;
129		return;
130	}
131
132	// now, does this block exist?
133	const LLMessageBlock* template_data = mCurrentSMessageTemplate->getBlock(bnamep);
134	if (!template_data)
135	{
136		llerrs << "LLTemplateMessageBuilder::nextBlock " << bnamep
137			<< " not a block in " << mCurrentSMessageTemplate->mName << llendl;
138		return;
139	}
140	
141	// ok, have we already set this block?
142	LLMsgBlkData* block_data = mCurrentSMessageData->mMemberBlocks[bnamep];
143	if (block_data->mBlockNumber == 0)
144	{
145		// nope! set this as the current block
146		block_data->mBlockNumber = 1;
147		mCurrentSDataBlock = block_data;
148		mCurrentSBlockName = bnamep;
149
150		// add placeholders for each of the variables
151		for (LLMessageBlock::message_variable_map_t::const_iterator iter = template_data->mMemberVariables.begin();
152			 iter != template_data->mMemberVariables.end(); iter++)
153		{
154			LLMessageVariable& ci = **iter;
155			mCurrentSDataBlock->addVariable(ci.getName(), ci.getType());
156		}
157		return;
158	}
159	else
160	{
161		// already have this block. . . 
162		// are we supposed to have a new one?
163
164		// if the block is type MBT_SINGLE this is bad!
165		if (template_data->mType == MBT_SINGLE)
166		{
167			llerrs << "LLTemplateMessageBuilder::nextBlock called multiple times"
168				<< " for " << bnamep << " but is type MBT_SINGLE" << llendl;
169			return;
170		}
171
172
173		// if the block is type MBT_MULTIPLE then we need a known number, 
174		// make sure that we're not exceeding it
175		if (  (template_data->mType == MBT_MULTIPLE)
176			&&(mCurrentSDataBlock->mBlockNumber == template_data->mNumber))
177		{
178			llerrs << "LLTemplateMessageBuilder::nextBlock called "
179				<< mCurrentSDataBlock->mBlockNumber << " times for " << bnamep
180				<< " exceeding " << template_data->mNumber
181				<< " specified in type MBT_MULTIPLE." << llendl;
182			return;
183		}
184
185		// ok, we can make a new one
186		// modify the name to avoid name collision by adding number to end
187		S32  count = block_data->mBlockNumber;
188
189		// incrememt base name's count
190		block_data->mBlockNumber++;
191
192		if (block_data->mBlockNumber > MAX_BLOCKS)
193		{
194			llerrs << "Trying to pack too many blocks into MBT_VARIABLE type "
195				   << "(limited to " << MAX_BLOCKS << ")" << llendl;
196		}
197
198		// create new name
199		// Nota Bene: if things are working correctly, 
200		// mCurrentMessageData->mMemberBlocks[blockname]->mBlockNumber == 
201		// mCurrentDataBlock->mBlockNumber + 1
202
203		char *nbnamep = bnamep + count;
204	
205		mCurrentSDataBlock = new LLMsgBlkData(bnamep, count);
206		mCurrentSDataBlock->mName = nbnamep;
207		mCurrentSMessageData->mMemberBlocks[nbnamep] = mCurrentSDataBlock;
208
209		// add placeholders for each of the variables
210		for (LLMessageBlock::message_variable_map_t::const_iterator
211				 iter = template_data->mMemberVariables.begin(),
212				 end = template_data->mMemberVariables.end();
213			 iter != end; iter++)
214		{
215			LLMessageVariable& ci = **iter;
216			mCurrentSDataBlock->addVariable(ci.getName(), ci.getType());
217		}
218		return;
219	}
220}
221
222// TODO: Remove this horror...
223BOOL LLTemplateMessageBuilder::removeLastBlock()
224{
225	if (mCurrentSBlockName)
226	{
227		if (  (mCurrentSMessageData)
228			&&(mCurrentSMessageTemplate))
229		{
230			if (mCurrentSMessageData->mMemberBlocks[mCurrentSBlockName]->mBlockNumber >= 1)
231			{
232				// At least one block for the current block name.
233
234				// Store the current block name for future reference.
235				char *block_name = mCurrentSBlockName;
236
237				// Decrement the sent total by the size of the
238				// data in the message block that we're currently building.
239
240				const LLMessageBlock* template_data = mCurrentSMessageTemplate->getBlock(mCurrentSBlockName);
241				
242				for (LLMessageBlock::message_variable_map_t::const_iterator iter = template_data->mMemberVariables.begin();
243					 iter != template_data->mMemberVariables.end(); iter++)
244				{
245					LLMessageVariable& ci = **iter;
246					mCurrentSendTotal -= ci.getSize();
247				}
248
249
250				// Now we want to find the block that we're blowing away.
251
252				// Get the number of blocks.
253				LLMsgBlkData* block_data = mCurrentSMessageData->mMemberBlocks[block_name];
254				S32 num_blocks = block_data->mBlockNumber;
255
256				// Use the same (suspect?) algorithm that's used to generate
257				// the names in the nextBlock method to find it.
258				char *block_getting_whacked = block_name + num_blocks - 1;
259				LLMsgBlkData* whacked_data = mCurrentSMessageData->mMemberBlocks[block_getting_whacked];
260				delete whacked_data;
261				mCurrentSMessageData->mMemberBlocks.erase(block_getting_whacked);
262
263				if (num_blocks <= 1)
264				{
265					// we just blew away the last one, so return FALSE
266					llwarns << "not blowing away the only block of message "
267							<< mCurrentSMessageName
268							<< ". Block: " << block_name
269							<< ". Number: " << num_blocks
270							<< llendl;
271					return FALSE;
272				}
273				else
274				{
275					// Decrement the counter.
276					block_data->mBlockNumber--;
277					return TRUE;
278				}
279			}
280		}
281	}
282	return FALSE;
283}
284
285// add data to variable in current block
286void LLTemplateMessageBuilder::addData(const char *varname, const void *data, EMsgVariableType type, S32 size)
287{
288	char *vnamep = (char *)varname; 
289
290	// do we have a current message?
291	if (!mCurrentSMessageTemplate)
292	{
293		llerrs << "newMessage not called prior to addData" << llendl;
294		return;
295	}
296
297	// do we have a current block?
298	if (!mCurrentSDataBlock)
299	{
300		llerrs << "setBlock not called prior to addData" << llendl;
301		return;
302	}
303
304	// kewl, add the data if it exists
305	const LLMessageVariable* var_data = mCurrentSMessageTemplate->getBlock(mCurrentSBlockName)->getVariable(vnamep);
306	if (!var_data || !var_data->getName())
307	{
308		llerrs << vnamep << " not a variable in block " << mCurrentSBlockName << " of " << mCurrentSMessageTemplate->mName << llendl;
309		return;
310	}
311
312	// ok, it seems ok. . . are we the correct size?
313	if (var_data->getType() == MVT_VARIABLE)
314	{
315		// Variable 1 can only store 255 bytes, make sure our data is smaller
316		if ((var_data->getSize() == 1) &&
317			(size > 255))
318		{
319			llwarns << "Field " << varname << " is a Variable 1 but program "
320			       << "attempted to stuff more than 255 bytes in "
321			       << "(" << size << ").  Clamping size and truncating data." << llendl;
322			size = 255;
323			char *truncate = (char *)data;
324			truncate[254] = 0; // array size is 255 but the last element index is 254
325		}
326
327		// no correct size for MVT_VARIABLE, instead we need to tell how many bytes the size will be encoded as
328		mCurrentSDataBlock->addData(vnamep, data, size, type, var_data->getSize());
329		mCurrentSendTotal += size;
330	}
331	else
332	{
333		if (size != var_data->getSize())
334		{
335			llerrs << varname << " is type MVT_FIXED but request size " << size << " doesn't match template size "
336				   << var_data->getSize() << llendl;
337			return;
338		}
339		// alright, smash it in
340		mCurrentSDataBlock->addData(vnamep, data, size, type);
341		mCurrentSendTotal += size;
342	}
343}
344
345// add data to variable in current block - fails if variable isn't MVT_FIXED
346void LLTemplateMessageBuilder::addData(const char *varname, const void *data, EMsgVariableType type)
347{
348	char *vnamep = (char *)varname; 
349
350	// do we have a current message?
351	if (!mCurrentSMessageTemplate)
352	{
353		llerrs << "newMessage not called prior to addData" << llendl;
354		return;
355	}
356
357	// do we have a current block?
358	if (!mCurrentSDataBlock)
359	{
360		llerrs << "setBlock not called prior to addData" << llendl;
361		return;
362	}
363
364	// kewl, add the data if it exists
365	const LLMessageVariable* var_data = mCurrentSMessageTemplate->getBlock(mCurrentSBlockName)->getVariable(vnamep);
366	if (!var_data->getName())
367	{
368		llerrs << vnamep << " not a variable in block " << mCurrentSBlockName << " of " << mCurrentSMessageTemplate->mName << llendl;
369		return;
370	}
371
372	// ok, it seems ok. . . are we MVT_VARIABLE?
373	if (var_data->getType() == MVT_VARIABLE)
374	{
375		// nope
376		llerrs << vnamep << " is type MVT_VARIABLE. Call using addData(name, data, size)" << llendl;
377		return;
378	}
379	else
380	{
381		mCurrentSDataBlock->addData(vnamep, data, var_data->getSize(), type);
382		mCurrentSendTotal += var_data->getSize();
383	}
384}
385
386void LLTemplateMessageBuilder::addBinaryData(const char *varname, 
387											const void *data, S32 size)
388{
389	addData(varname, data, MVT_FIXED, size);
390}
391
392void LLTemplateMessageBuilder::addS8(const char *varname, S8 s)
393{
394	addData(varname, &s, MVT_S8, sizeof(s));
395}
396
397void LLTemplateMessageBuilder::addU8(const char *varname, U8 u)
398{
399	addData(varname, &u, MVT_U8, sizeof(u));
400}
401
402void LLTemplateMessageBuilder::addS16(const char *varname, S16 i)
403{
404	addData(varname, &i, MVT_S16, sizeof(i));
405}
406
407void LLTemplateMessageBuilder::addU16(const char *varname, U16 i)
408{
409	addData(varname, &i, MVT_U16, sizeof(i));
410}
411
412void LLTemplateMessageBuilder::addF32(const char *varname, F32 f)
413{
414	addData(varname, &f, MVT_F32, sizeof(f));
415}
416
417void LLTemplateMessageBuilder::addS32(const char *varname, S32 s)
418{
419	addData(varname, &s, MVT_S32, sizeof(s));
420}
421
422void LLTemplateMessageBuilder::addU32(const char *varname, U32 u)
423{
424	addData(varname, &u, MVT_U32, sizeof(u));
425}
426
427void LLTemplateMessageBuilder::addU64(const char *varname, U64 lu)
428{
429	addData(varname, &lu, MVT_U64, sizeof(lu));
430}
431
432void LLTemplateMessageBuilder::addF64(const char *varname, F64 d)
433{
434	addData(varname, &d, MVT_F64, sizeof(d));
435}
436
437void LLTemplateMessageBuilder::addIPAddr(const char *varname, U32 u)
438{
439	addData(varname, &u, MVT_IP_ADDR, sizeof(u));
440}
441
442void LLTemplateMessageBuilder::addIPPort(const char *varname, U16 u)
443{
444	u = htons(u);
445	addData(varname, &u, MVT_IP_PORT, sizeof(u));
446}
447
448void LLTemplateMessageBuilder::addBOOL(const char* varname, BOOL b)
449{
450	// Can't just cast a BOOL (actually a U32) to a U8.
451	// In some cases the low order bits will be zero.
452	U8 temp = (b != 0);
453	addData(varname, &temp, MVT_BOOL, sizeof(temp));
454}
455
456void LLTemplateMessageBuilder::addString(const char* varname, const char* s)
457{
458	if (s)
459		addData( varname, (void *)s, MVT_VARIABLE, (S32)strlen(s) + 1);  /* Flawfinder: ignore */  
460	else
461		addData( varname, NULL, MVT_VARIABLE, 0); 
462}
463
464void LLTemplateMessageBuilder::addString(const char* varname, const std::string& s)
465{
466	if (s.size())
467		addData( varname, (void *)s.c_str(), MVT_VARIABLE, (S32)(s.size()) + 1); 
468	else
469		addData( varname, NULL, MVT_VARIABLE, 0); 
470}
471
472void LLTemplateMessageBuilder::addVector3(const char *varname, const LLVector3& vec)
473{
474	addData(varname, vec.mV, MVT_LLVector3, sizeof(vec.mV));
475}
476
477void LLTemplateMessageBuilder::addVector4(const char *varname, const LLVector4& vec)
478{
479	addData(varname, vec.mV, MVT_LLVector4, sizeof(vec.mV));
480}
481
482void LLTemplateMessageBuilder::addVector3d(const char *varname, const LLVector3d& vec)
483{
484	addData(varname, vec.mdV, MVT_LLVector3d, sizeof(vec.mdV));
485}
486
487void LLTemplateMessageBuilder::addQuat(const char *varname, const LLQuaternion& quat)
488{
489	addData(varname, quat.packToVector3().mV, MVT_LLQuaternion, sizeof(LLVector3));
490}
491
492void LLTemplateMessageBuilder::addUUID(const char *varname, const LLUUID& uuid)
493{
494	addData(varname, uuid.mData, MVT_LLUUID, sizeof(uuid.mData));
495}
496
497static S32 zero_code(U8 **data, U32 *data_size)
498{
499	// Encoded send buffer needs to be slightly larger since the zero
500	// coding can potentially increase the size of the send data.
501	static U8 encodedSendBuffer[2 * MAX_BUFFER_SIZE];
502
503	S32 count = *data_size;
504	
505	S32 net_gain = 0;
506	U8 num_zeroes = 0;
507	
508	U8 *inptr = (U8 *)*data;
509	U8 *outptr = (U8 *)encodedSendBuffer;
510
511// skip the packet id field
512
513	for (U32 ii = 0; ii < LL_PACKET_ID_SIZE ; ++ii)
514	{
515		count--;
516		*outptr++ = *inptr++;
517	}
518
519// build encoded packet, keeping track of net size gain
520
521// sequential zero bytes are encoded as 0 [U8 count] 
522// with 0 0 [count] representing wrap (>256 zeroes)
523
524	while (count--)
525	{
526		if (!(*inptr))   // in a zero count
527		{
528			if (num_zeroes)
529			{
530				if (++num_zeroes > 254)
531				{
532					*outptr++ = num_zeroes;
533					num_zeroes = 0;
534				}
535				net_gain--;   // subseqent zeroes save one
536			}
537			else
538			{
539				*outptr++ = 0;
540				net_gain++;  // starting a zero count adds one
541				num_zeroes = 1;
542			}
543			inptr++;
544		}
545		else
546		{
547			if (num_zeroes)
548			{
549				*outptr++ = num_zeroes;
550				num_zeroes = 0;
551			}
552			*outptr++ = *inptr++;
553		}
554	}
555
556	if (num_zeroes)
557	{
558		*outptr++ = num_zeroes;
559	}
560
561	if (net_gain < 0)
562	{
563		// TODO: babbage: reinstate stat collecting...
564		//mCompressedPacketsOut++;
565		//mUncompressedBytesOut += *data_size;
566
567		*data = encodedSendBuffer;
568		*data_size += net_gain;
569		encodedSendBuffer[0] |= LL_ZERO_CODE_FLAG;          // set the head bit to indicate zero coding
570
571		//mCompressedBytesOut += *data_size;
572
573	}
574	//mTotalBytesOut += *data_size;
575
576	return(net_gain);
577}
578
579void LLTemplateMessageBuilder::compressMessage(U8*& buf_ptr, U32& buffer_length)
580{
581	if(ME_ZEROCODED == mCurrentSMessageTemplate->getEncoding())
582	{
583		zero_code(&buf_ptr, &buffer_length);
584	}
585}
586
587BOOL LLTemplateMessageBuilder::isMessageFull(const char* blockname) const
588{
589	if(mCurrentSendTotal > MTUBYTES)
590	{
591		return TRUE;
592	}
593	if(!blockname)
594	{
595		return FALSE;
596	}
597	char* bnamep = (char*)blockname;
598	S32 max;
599
600	const LLMessageBlock* template_data = mCurrentSMessageTemplate->getBlock(bnamep);
601	
602	switch(template_data->mType)
603	{
604	case MBT_SINGLE:
605		max = 1;
606		break;
607	case MBT_MULTIPLE:
608		max = template_data->mNumber;
609		break;
610	case MBT_VARIABLE:
611	default:
612		max = MAX_BLOCKS;
613		break;
614	}
615	if(mCurrentSMessageData->mMemberBlocks[bnamep]->mBlockNumber >= max)
616	{
617		return TRUE;
618	}
619	return FALSE;
620}
621
622static S32 buildBlock(U8* buffer, S32 buffer_size, const LLMessageBlock* template_data, LLMsgData* message_data)
623{
624	S32 result = 0;
625	LLMsgData::msg_blk_data_map_t::const_iterator block_iter = message_data->mMemberBlocks.find(template_data->mName);
626	const LLMsgBlkData* mbci = block_iter->second;
627		
628	// ok, if this is the first block of a repeating pack, set
629	// block_count and, if it's type MBT_VARIABLE encode a byte
630	// for how many there are
631	S32 block_count = mbci->mBlockNumber;
632	if (template_data->mType == MBT_VARIABLE)
633	{
634		// remember that mBlockNumber is a S32
635		U8 temp_block_number = (U8)mbci->mBlockNumber;
636		if ((S32)(result + sizeof(U8)) < MAX_BUFFER_SIZE)
637		{
638			memcpy(&buffer[result], &temp_block_number, sizeof(U8));
639			result += sizeof(U8);
640		}
641		else
642		{
643			// Just reporting error is likely not enough. Need
644			// to check how to abort or error out gracefully
645			// from this function. XXXTBD
646			llerrs << "buildBlock failed. Message excedding "
647					<< "sendBuffersize." << llendl;
648		}
649	}
650	else if (template_data->mType == MBT_MULTIPLE)
651	{
652		if (block_count != template_data->mNumber)
653		{
654			// nope!  need to fill it in all the way!
655			llerrs << "Block " << mbci->mName
656				<< " is type MBT_MULTIPLE but only has data for "
657				<< block_count << " out of its "
658				<< template_data->mNumber << " blocks" << llendl;
659		}
660	}
661
662	while(block_count > 0)
663	{
664		// now loop through the variables
665		for (LLMsgBlkData::msg_var_data_map_t::const_iterator iter = mbci->mMemberVarData.begin();
666			 iter != mbci->mMemberVarData.end(); iter++)
667		{
668			const LLMsgVarData& mvci = *iter;
669			if (mvci.getSize() == -1)
670			{
671				// oops, this variable wasn't ever set!
672				llerrs << "The variable " << mvci.getName() << " in block "
673					<< mbci->mName << " of message "
674					<< template_data->mName
675					<< " wasn't set prior to buildMessage call" << llendl;
676			}
677			else
678			{
679				S32 data_size = mvci.getDataSize();
680				if(data_size > 0)
681				{
682					// The type is MVT_VARIABLE, which means that we
683					// need to encode a size argument. Otherwise,
684					// there is no need.
685					S32 size = mvci.getSize();
686					U8 sizeb;
687					U16 sizeh;
688					switch(data_size)
689					{
690					case 1:
691						sizeb = size;
692						htonmemcpy(&buffer[result], &sizeb, MVT_U8, 1);
693						break;
694					case 2:
695						sizeh = size;
696						htonmemcpy(&buffer[result], &sizeh, MVT_U16, 2);
697						break;
698					case 4:
699						htonmemcpy(&buffer[result], &size, MVT_S32, 4);
700						break;
701					default:
702						llerrs << "Attempting to build variable field with unknown size of " << size << llendl;
703						break;
704					}
705					result += mvci.getDataSize();
706				}
707
708				// if there is any data to pack, pack it
709				if((mvci.getData() != NULL) && mvci.getSize())
710				{
711					if(result + mvci.getSize() < buffer_size)
712					{
713					    memcpy(
714							&buffer[result],
715							mvci.getData(),
716							mvci.getSize());
717					    result += mvci.getSize();
718					}
719					else
720					{
721					    // Just reporting error is likely not
722					    // enough. Need to check how to abort or error
723					    // out gracefully from this function. XXXTBD
724						llerrs << "buildBlock failed. "
725							<< "Attempted to pack "
726							<< (result + mvci.getSize())
727							<< " bytes into a buffer with size "
728							<< buffer_size << "." << llendl;
729					}						
730				}
731			}
732		}
733
734		--block_count;
735		
736		if (block_iter != message_data->mMemberBlocks.end())
737		{
738			++block_iter;
739			if (block_iter != message_data->mMemberBlocks.end())
740			{
741				mbci = block_iter->second;
742			}
743		}
744	}
745
746	return result;
747}
748
749
750// make sure that all the desired data is in place and then copy the data into MAX_BUFFER_SIZEd buffer
751U32 LLTemplateMessageBuilder::buildMessage(
752	U8* buffer,
753	U32 buffer_size,
754	U8 offset_to_data)
755{
756	// basic algorithm is to loop through the various pieces, building
757	// size and offset info if we encounter a -1 for mSize at any
758	// point that variable wasn't given data
759
760	// do we have a current message?
761	if (!mCurrentSMessageTemplate)
762	{
763		llerrs << "newMessage not called prior to buildMessage" << llendl;
764		return 0;
765	}
766
767	// leave room for flags, packet sequence #, and data offset
768	// information.
769	buffer[PHL_OFFSET] = offset_to_data;
770	U32 result = LL_PACKET_ID_SIZE;
771
772	// encode message number and adjust total_offset
773	if (mCurrentSMessageTemplate->mFrequency == MFT_HIGH)
774	{
775// old, endian-dependant way
776//		memcpy(&buffer[result], &mCurrentMessageTemplate->mMessageNumber, sizeof(U8));
777
778// new, independant way
779		buffer[result] = (U8)mCurrentSMessageTemplate->mMessageNumber;
780		result += sizeof(U8);
781	}
782	else if (mCurrentSMessageTemplate->mFrequency == MFT_MEDIUM)
783	{
784		U8 temp = 255;
785		memcpy(&buffer[result], &temp, sizeof(U8));  /*Flawfinder: ignore*/
786		result += sizeof(U8);
787
788		// mask off unsightly bits
789		temp = mCurrentSMessageTemplate->mMessageNumber & 255;
790		memcpy(&buffer[result], &temp, sizeof(U8));  /*Flawfinder: ignore*/
791		result += sizeof(U8);
792	}
793	else if (mCurrentSMessageTemplate->mFrequency == MFT_LOW)
794	{
795		U8 temp = 255;
796		U16  message_num;
797		memcpy(&buffer[result], &temp, sizeof(U8));  /*Flawfinder: ignore*/
798		result += sizeof(U8);
799		memcpy(&buffer[result], &temp, sizeof(U8));  /*Flawfinder: ignore*/
800		result += sizeof(U8);
801
802		// mask off unsightly bits
803		message_num = mCurrentSMessageTemplate->mMessageNumber & 0xFFFF;
804
805	    // convert to network byte order
806		message_num = htons(message_num);
807		memcpy(&buffer[result], &message_num, sizeof(U16)); /*Flawfinder: ignore*/
808		result += sizeof(U16);
809	}
810	else
811	{
812		llerrs << "unexpected message frequency in buildMessage" << llendl;
813		return 0;
814	}
815
816	// fast forward through the offset and build the message
817	result += offset_to_data;
818	for(LLMessageTemplate::message_block_map_t::const_iterator
819			iter = mCurrentSMessageTemplate->mMemberBlocks.begin(),
820			end = mCurrentSMessageTemplate->mMemberBlocks.end();
821		 iter != end;
822		++iter)
823	{
824		result += buildBlock(buffer + result, buffer_size - result, *iter, mCurrentSMessageData);
825	}
826	mbSBuilt = TRUE;
827
828	return result;
829}
830
831void LLTemplateMessageBuilder::copyFromMessageData(const LLMsgData& data)
832{
833	// copy the blocks
834	// counting variables used to encode multiple block info
835	S32 block_count = 0;
836    char *block_name = NULL;
837
838	// loop through msg blocks to loop through variables, totalling up size
839	// data and filling the new (send) message
840	LLMsgData::msg_blk_data_map_t::const_iterator iter = 
841		data.mMemberBlocks.begin();
842	LLMsgData::msg_blk_data_map_t::const_iterator end = 
843		data.mMemberBlocks.end();
844	for(; iter != end; ++iter)
845	{
846		const LLMsgBlkData* mbci = iter->second;
847		if(!mbci) continue;
848
849		// do we need to encode a block code?
850		if (block_count == 0)
851		{
852			block_count = mbci->mBlockNumber;
853			block_name = (char *)mbci->mName;
854		}
855
856		// counting down mutliple blocks
857		block_count--;
858
859		nextBlock(block_name);
860
861		// now loop through the variables
862		LLMsgBlkData::msg_var_data_map_t::const_iterator dit = mbci->mMemberVarData.begin();
863		LLMsgBlkData::msg_var_data_map_t::const_iterator dend = mbci->mMemberVarData.end();
864		
865		for(; dit != dend; ++dit)
866		{
867			const LLMsgVarData& mvci = *dit;
868			addData(mvci.getName(), mvci.getData(), mvci.getType(), mvci.getSize());
869		}
870	}
871}
872
873//virtual 
874void LLTemplateMessageBuilder::copyFromLLSD(const LLSD&)
875{
876	// TODO
877}
878
879//virtual
880void LLTemplateMessageBuilder::setBuilt(BOOL b) { mbSBuilt = b; }
881
882//virtual 
883BOOL LLTemplateMessageBuilder::isBuilt() const {return mbSBuilt;}
884
885//virtual 
886BOOL LLTemplateMessageBuilder::isClear() const {return mbSClear;}
887
888//virtual 
889S32 LLTemplateMessageBuilder::getMessageSize() {return mCurrentSendTotal;}
890
891//virtual 
892const char* LLTemplateMessageBuilder::getMessageName() const 
893{
894	return mCurrentSMessageName;
895}