PageRenderTime 106ms CodeModel.GetById 51ms app.highlight 48ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llmessage/lltemplatemessagereader.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 828 lines | 633 code | 114 blank | 81 comment | 88 complexity | 4c11c0d6aa5b1e83c3cfc470d2b8f0ac MD5 | raw file
  1/** 
  2 * @file lltemplatemessagereader.cpp
  3 * @brief LLTemplateMessageReader 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#include "lltemplatemessagereader.h"
 29
 30#include "llfasttimer.h"
 31#include "llmessagebuilder.h"
 32#include "llmessagetemplate.h"
 33#include "llmath.h"
 34#include "llquaternion.h"
 35#include "message.h"
 36#include "u64.h"
 37#include "v3dmath.h"
 38#include "v3math.h"
 39#include "v4math.h"
 40
 41LLTemplateMessageReader::LLTemplateMessageReader(message_template_number_map_t&
 42												 number_template_map) :
 43	mReceiveSize(0),
 44	mCurrentRMessageTemplate(NULL),
 45	mCurrentRMessageData(NULL),
 46	mMessageNumbers(number_template_map)
 47{
 48}
 49
 50//virtual 
 51LLTemplateMessageReader::~LLTemplateMessageReader()
 52{
 53	delete mCurrentRMessageData;
 54	mCurrentRMessageData = NULL;
 55}
 56
 57//virtual
 58void LLTemplateMessageReader::clearMessage()
 59{
 60	mReceiveSize = -1;
 61	mCurrentRMessageTemplate = NULL;
 62	delete mCurrentRMessageData;
 63	mCurrentRMessageData = NULL;
 64}
 65
 66void LLTemplateMessageReader::getData(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum, S32 max_size)
 67{
 68	// is there a message ready to go?
 69	if (mReceiveSize == -1)
 70	{
 71		llerrs << "No message waiting for decode 2!" << llendl;
 72		return;
 73	}
 74
 75	if (!mCurrentRMessageData)
 76	{
 77		llerrs << "Invalid mCurrentMessageData in getData!" << llendl;
 78		return;
 79	}
 80
 81	char *bnamep = (char *)blockname + blocknum; // this works because it's just a hash.  The bnamep is never derefference
 82	char *vnamep = (char *)varname; 
 83
 84	LLMsgData::msg_blk_data_map_t::const_iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep);
 85
 86	if (iter == mCurrentRMessageData->mMemberBlocks.end())
 87	{
 88		llerrs << "Block " << blockname << " #" << blocknum
 89			<< " not in message " << mCurrentRMessageData->mName << llendl;
 90		return;
 91	}
 92
 93	LLMsgBlkData *msg_block_data = iter->second;
 94	LLMsgVarData& vardata = msg_block_data->mMemberVarData[vnamep];
 95
 96	if (!vardata.getName())
 97	{
 98		llerrs << "Variable "<< vnamep << " not in message "
 99			<< mCurrentRMessageData->mName<< " block " << bnamep << llendl;
100		return;
101	}
102
103	if (size && size != vardata.getSize())
104	{
105		llerrs << "Msg " << mCurrentRMessageData->mName 
106			<< " variable " << vnamep
107			<< " is size " << vardata.getSize()
108			<< " but copying into buffer of size " << size
109			<< llendl;
110		return;
111	}
112
113
114	const S32 vardata_size = vardata.getSize();
115	if( max_size >= vardata_size )
116	{   
117		switch( vardata_size )
118		{ 
119		case 1:
120			*((U8*)datap) = *((U8*)vardata.getData());
121			break;
122		case 2:
123			*((U16*)datap) = *((U16*)vardata.getData());
124			break;
125		case 4:
126			*((U32*)datap) = *((U32*)vardata.getData());
127			break;
128		case 8:
129			((U32*)datap)[0] = ((U32*)vardata.getData())[0];
130			((U32*)datap)[1] = ((U32*)vardata.getData())[1];
131			break;
132		default:
133			memcpy(datap, vardata.getData(), vardata_size);
134			break;
135		}
136	}
137	else
138	{
139		llwarns << "Msg " << mCurrentRMessageData->mName 
140			<< " variable " << vnamep
141			<< " is size " << vardata.getSize()
142			<< " but truncated to max size of " << max_size
143			<< llendl;
144
145		memcpy(datap, vardata.getData(), max_size);
146	}
147}
148
149S32 LLTemplateMessageReader::getNumberOfBlocks(const char *blockname)
150{
151	// is there a message ready to go?
152	if (mReceiveSize == -1)
153	{
154		llerrs << "No message waiting for decode 3!" << llendl;
155		return -1;
156	}
157
158	if (!mCurrentRMessageData)
159	{
160		llerrs << "Invalid mCurrentRMessageData in getData!" << llendl;
161		return -1;
162	}
163
164	char *bnamep = (char *)blockname; 
165
166	LLMsgData::msg_blk_data_map_t::const_iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep);
167	
168	if (iter == mCurrentRMessageData->mMemberBlocks.end())
169	{
170		return 0;
171	}
172
173	return (iter->second)->mBlockNumber;
174}
175
176S32 LLTemplateMessageReader::getSize(const char *blockname, const char *varname)
177{
178	// is there a message ready to go?
179	if (mReceiveSize == -1)
180	{	// This is a serious error - crash 
181		llerrs << "No message waiting for decode 4!" << llendl;
182		return LL_MESSAGE_ERROR;
183	}
184
185	if (!mCurrentRMessageData)
186	{	// This is a serious error - crash
187		llerrs << "Invalid mCurrentRMessageData in getData!" << llendl;
188		return LL_MESSAGE_ERROR;
189	}
190
191	char *bnamep = (char *)blockname; 
192
193	LLMsgData::msg_blk_data_map_t::const_iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep);
194	
195	if (iter == mCurrentRMessageData->mMemberBlocks.end())
196	{	// don't crash
197		llinfos << "Block " << bnamep << " not in message "
198			<< mCurrentRMessageData->mName << llendl;
199		return LL_BLOCK_NOT_IN_MESSAGE;
200	}
201
202	char *vnamep = (char *)varname; 
203
204	LLMsgBlkData* msg_data = iter->second;
205	LLMsgVarData& vardata = msg_data->mMemberVarData[vnamep];
206	
207	if (!vardata.getName())
208	{	// don't crash
209		llinfos << "Variable " << varname << " not in message "
210			<< mCurrentRMessageData->mName << " block " << bnamep << llendl;
211		return LL_VARIABLE_NOT_IN_BLOCK;
212	}
213
214	if (mCurrentRMessageTemplate->mMemberBlocks[bnamep]->mType != MBT_SINGLE)
215	{	// This is a serious error - crash
216		llerrs << "Block " << bnamep << " isn't type MBT_SINGLE,"
217			" use getSize with blocknum argument!" << llendl;
218		return LL_MESSAGE_ERROR;
219	}
220
221	return vardata.getSize();
222}
223
224S32 LLTemplateMessageReader::getSize(const char *blockname, S32 blocknum, const char *varname)
225{
226	// is there a message ready to go?
227	if (mReceiveSize == -1)
228	{	// This is a serious error - crash
229		llerrs << "No message waiting for decode 5!" << llendl;
230		return LL_MESSAGE_ERROR;
231	}
232
233	if (!mCurrentRMessageData)
234	{	// This is a serious error - crash
235		llerrs << "Invalid mCurrentRMessageData in getData!" << llendl;
236		return LL_MESSAGE_ERROR;
237	}
238
239	char *bnamep = (char *)blockname + blocknum; 
240	char *vnamep = (char *)varname; 
241
242	LLMsgData::msg_blk_data_map_t::const_iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep);
243	
244	if (iter == mCurrentRMessageData->mMemberBlocks.end())
245	{	// don't crash
246		llinfos << "Block " << bnamep << " not in message " 
247			<< mCurrentRMessageData->mName << llendl;
248		return LL_BLOCK_NOT_IN_MESSAGE;
249	}
250
251	LLMsgBlkData* msg_data = iter->second;
252	LLMsgVarData& vardata = msg_data->mMemberVarData[vnamep];
253	
254	if (!vardata.getName())
255	{	// don't crash
256		llinfos << "Variable " << vnamep << " not in message "
257			<<  mCurrentRMessageData->mName << " block " << bnamep << llendl;
258		return LL_VARIABLE_NOT_IN_BLOCK;
259	}
260
261	return vardata.getSize();
262}
263
264void LLTemplateMessageReader::getBinaryData(const char *blockname, 
265											const char *varname, void *datap, 
266											S32 size, S32 blocknum, 
267											S32 max_size)
268{
269	getData(blockname, varname, datap, size, blocknum, max_size);
270}
271
272void LLTemplateMessageReader::getS8(const char *block, const char *var, 
273										S8 &u, S32 blocknum)
274{
275	getData(block, var, &u, sizeof(S8), blocknum);
276}
277
278void LLTemplateMessageReader::getU8(const char *block, const char *var, 
279										U8 &u, S32 blocknum)
280{
281	getData(block, var, &u, sizeof(U8), blocknum);
282}
283
284void LLTemplateMessageReader::getBOOL(const char *block, const char *var, 
285										  BOOL &b, S32 blocknum )
286{
287	U8 value;
288	getData(block, var, &value, sizeof(U8), blocknum);
289	b = (BOOL) value;
290}
291
292void LLTemplateMessageReader::getS16(const char *block, const char *var, 
293										 S16 &d, S32 blocknum)
294{
295	getData(block, var, &d, sizeof(S16), blocknum);
296}
297
298void LLTemplateMessageReader::getU16(const char *block, const char *var, 
299										 U16 &d, S32 blocknum)
300{
301	getData(block, var, &d, sizeof(U16), blocknum);
302}
303
304void LLTemplateMessageReader::getS32(const char *block, const char *var, 
305										 S32 &d, S32 blocknum)
306{
307	getData(block, var, &d, sizeof(S32), blocknum);
308}
309
310void LLTemplateMessageReader::getU32(const char *block, const char *var, 
311									 U32 &d, S32 blocknum)
312{
313	getData(block, var, &d, sizeof(U32), blocknum);
314}
315
316void LLTemplateMessageReader::getU64(const char *block, const char *var, 
317									 U64 &d, S32 blocknum)
318{
319	getData(block, var, &d, sizeof(U64), blocknum);
320}
321
322void LLTemplateMessageReader::getF32(const char *block, const char *var, 
323									 F32 &d, S32 blocknum)
324{
325	getData(block, var, &d, sizeof(F32), blocknum);
326
327	if( !llfinite( d ) )
328	{
329		llwarns << "non-finite in getF32Fast " << block << " " << var 
330				<< llendl;
331		d = 0;
332	}
333}
334
335void LLTemplateMessageReader::getF64(const char *block, const char *var, 
336									 F64 &d, S32 blocknum)
337{
338	getData(block, var, &d, sizeof(F64), blocknum);
339
340	if( !llfinite( d ) )
341	{
342		llwarns << "non-finite in getF64Fast " << block << " " << var 
343				<< llendl;
344		d = 0;
345	}
346}
347
348void LLTemplateMessageReader::getVector3(const char *block, const char *var, 
349										 LLVector3 &v, S32 blocknum )
350{
351	getData(block, var, &v.mV[0], sizeof(v.mV), blocknum);
352
353	if( !v.isFinite() )
354	{
355		llwarns << "non-finite in getVector3Fast " << block << " " 
356				<< var << llendl;
357		v.zeroVec();
358	}
359}
360
361void LLTemplateMessageReader::getVector4(const char *block, const char *var, 
362										 LLVector4 &v, S32 blocknum)
363{
364	getData(block, var, &v.mV[0], sizeof(v.mV), blocknum);
365
366	if( !v.isFinite() )
367	{
368		llwarns << "non-finite in getVector4Fast " << block << " " 
369				<< var << llendl;
370		v.zeroVec();
371	}
372}
373
374void LLTemplateMessageReader::getVector3d(const char *block, const char *var, 
375										  LLVector3d &v, S32 blocknum )
376{
377	getData(block, var, &v.mdV[0], sizeof(v.mdV), blocknum);
378
379	if( !v.isFinite() )
380	{
381		llwarns << "non-finite in getVector3dFast " << block << " " 
382				<< var << llendl;
383		v.zeroVec();
384	}
385
386}
387
388void LLTemplateMessageReader::getQuat(const char *block, const char *var, 
389									  LLQuaternion &q, S32 blocknum)
390{
391	LLVector3 vec;
392	getData(block, var, &vec.mV[0], sizeof(vec.mV), blocknum);
393	if( vec.isFinite() )
394	{
395		q.unpackFromVector3( vec );
396	}
397	else
398	{
399		llwarns << "non-finite in getQuatFast " << block << " " << var 
400				<< llendl;
401		q.loadIdentity();
402	}
403}
404
405void LLTemplateMessageReader::getUUID(const char *block, const char *var, 
406									  LLUUID &u, S32 blocknum)
407{
408	getData(block, var, &u.mData[0], sizeof(u.mData), blocknum);
409}
410
411inline void LLTemplateMessageReader::getIPAddr(const char *block, const char *var, U32 &u, S32 blocknum)
412{
413	getData(block, var, &u, sizeof(U32), blocknum);
414}
415
416inline void LLTemplateMessageReader::getIPPort(const char *block, const char *var, U16 &u, S32 blocknum)
417{
418	getData(block, var, &u, sizeof(U16), blocknum);
419	u = ntohs(u);
420}
421
422inline void LLTemplateMessageReader::getString(const char *block, const char *var, S32 buffer_size, char *s, S32 blocknum )
423{
424	s[0] = '\0';
425	getData(block, var, s, 0, blocknum, buffer_size);
426	s[buffer_size - 1] = '\0';
427}
428
429inline void LLTemplateMessageReader::getString(const char *block, const char *var, std::string& outstr, S32 blocknum )
430{
431	char s[MTUBYTES + 1]= {0}; // every element is initialized with 0
432	getData(block, var, s, 0, blocknum, MTUBYTES);
433	s[MTUBYTES] = '\0';
434	outstr = s;
435}
436
437//virtual 
438S32 LLTemplateMessageReader::getMessageSize() const
439{
440	return mReceiveSize;
441}
442
443// Returns template for the message contained in buffer
444BOOL LLTemplateMessageReader::decodeTemplate(  
445		const U8* buffer, S32 buffer_size,  // inputs
446		LLMessageTemplate** msg_template ) // outputs
447{
448	const U8* header = buffer + LL_PACKET_ID_SIZE;
449
450	// is there a message ready to go?
451	if (buffer_size <= 0)
452	{
453		llwarns << "No message waiting for decode!" << llendl;
454		return(FALSE);
455	}
456
457	U32 num = 0;
458
459	if (header[0] != 255)
460	{
461		// high frequency message
462		num = header[0];
463	}
464	else if ((buffer_size >= ((S32) LL_MINIMUM_VALID_PACKET_SIZE + 1)) && (header[1] != 255))
465	{
466		// medium frequency message
467		num = (255 << 8) | header[1];
468	}
469	else if ((buffer_size >= ((S32) LL_MINIMUM_VALID_PACKET_SIZE + 3)) && (header[1] == 255))
470	{
471		// low frequency message
472		U16	message_id_U16 = 0;
473		// I think this check busts the message system.
474		// it appears that if there is a NULL in the message #, it won't copy it....
475		// what was the goal?
476		//if(header[2])
477		memcpy(&message_id_U16, &header[2], 2);
478
479		// dependant on endian-ness:
480		//		U32	temp = (255 << 24) | (255 << 16) | header[2];
481
482		// independant of endian-ness:
483		message_id_U16 = ntohs(message_id_U16);
484		num = 0xFFFF0000 | message_id_U16;
485	}
486	else // bogus packet received (too short)
487	{
488		llwarns << "Packet with unusable length received (too short): "
489				<< buffer_size << llendl;
490		return(FALSE);
491	}
492
493	LLMessageTemplate* temp = get_ptr_in_map(mMessageNumbers,num);
494	if (temp)
495	{
496		*msg_template = temp;
497	}
498	else
499	{
500		llwarns << "Message #" << std::hex << num << std::dec
501			<< " received but not registered!" << llendl;
502		gMessageSystem->callExceptionFunc(MX_UNREGISTERED_MESSAGE);
503		return(FALSE);
504	}
505
506	return(TRUE);
507}
508
509void LLTemplateMessageReader::logRanOffEndOfPacket( const LLHost& host, const S32 where, const S32 wanted )
510{
511	// we've run off the end of the packet!
512	llwarns << "Ran off end of packet " << mCurrentRMessageTemplate->mName
513//			<< " with id " << mCurrentRecvPacketID 
514			<< " from " << host
515			<< " trying to read " << wanted
516			<< " bytes at position " << where
517			<< " going past packet end at " << mReceiveSize
518			<< llendl;
519	if(gMessageSystem->mVerboseLog)
520	{
521		llinfos << "MSG: -> " << host << "\tREAD PAST END:\t"
522//				<< mCurrentRecvPacketID << " "
523				<< getMessageName() << llendl;
524	}
525	gMessageSystem->callExceptionFunc(MX_RAN_OFF_END_OF_PACKET);
526}
527
528static LLFastTimer::DeclareTimer FTM_PROCESS_MESSAGES("Process Messages");
529
530// decode a given message
531BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender )
532{
533	llassert( mReceiveSize >= 0 );
534	llassert( mCurrentRMessageTemplate);
535	llassert( !mCurrentRMessageData );
536	delete mCurrentRMessageData; // just to make sure
537
538	// The offset tells us how may bytes to skip after the end of the
539	// message name.
540	U8 offset = buffer[PHL_OFFSET];
541	S32 decode_pos = LL_PACKET_ID_SIZE + (S32)(mCurrentRMessageTemplate->mFrequency) + offset;
542
543	// create base working data set
544	mCurrentRMessageData = new LLMsgData(mCurrentRMessageTemplate->mName);
545	
546	// loop through the template building the data structure as we go
547	LLMessageTemplate::message_block_map_t::const_iterator iter;
548	for(iter = mCurrentRMessageTemplate->mMemberBlocks.begin();
549		iter != mCurrentRMessageTemplate->mMemberBlocks.end();
550		++iter)
551	{
552		LLMessageBlock* mbci = *iter;
553		U8	repeat_number;
554		S32	i;
555
556		// how many of this block?
557
558		if (mbci->mType == MBT_SINGLE)
559		{
560			// just one
561			repeat_number = 1;
562		}
563		else if (mbci->mType == MBT_MULTIPLE)
564		{
565			// a known number
566			repeat_number = mbci->mNumber;
567		}
568		else if (mbci->mType == MBT_VARIABLE)
569		{
570			// need to read the number from the message
571			// repeat number is a single byte
572			if (decode_pos >= mReceiveSize)
573			{
574				// commented out - hetgrid says that missing variable blocks
575				// at end of message are legal
576				// logRanOffEndOfPacket(sender, decode_pos, 1);
577
578				// default to 0 repeats
579				repeat_number = 0;
580			}
581			else
582			{
583				repeat_number = buffer[decode_pos];
584				decode_pos++;
585			}
586		}
587		else
588		{
589			llerrs << "Unknown block type" << llendl;
590			return FALSE;
591		}
592
593		LLMsgBlkData* cur_data_block = NULL;
594
595		// now loop through the block
596		for (i = 0; i < repeat_number; i++)
597		{
598			if (i)
599			{
600				// build new name to prevent collisions
601				// TODO: This should really change to a vector
602				cur_data_block = new LLMsgBlkData(mbci->mName, repeat_number);
603				cur_data_block->mName = mbci->mName + i;
604			}
605			else
606			{
607				cur_data_block = new LLMsgBlkData(mbci->mName, repeat_number);
608			}
609
610			// add the block to the message
611			mCurrentRMessageData->addBlock(cur_data_block);
612
613			// now read the variables
614			for (LLMessageBlock::message_variable_map_t::const_iterator iter = 
615					 mbci->mMemberVariables.begin();
616				 iter != mbci->mMemberVariables.end(); iter++)
617			{
618				const LLMessageVariable& mvci = **iter;
619
620				// ok, build out the variables
621				// add variable block
622				cur_data_block->addVariable(mvci.getName(), mvci.getType());
623
624				// what type of variable?
625				if (mvci.getType() == MVT_VARIABLE)
626				{
627					// variable, get the number of bytes to read from the template
628					S32 data_size = mvci.getSize();
629					U8 tsizeb = 0;
630					U16 tsizeh = 0;
631					U32 tsize = 0;
632
633					if ((decode_pos + data_size) > mReceiveSize)
634					{
635						logRanOffEndOfPacket(sender, decode_pos, data_size);
636
637						// default to 0 length variable blocks
638						tsize = 0;
639					}
640					else
641					{
642						switch(data_size)
643						{
644						case 1:
645							htonmemcpy(&tsizeb, &buffer[decode_pos], MVT_U8, 1);
646							tsize = tsizeb;
647							break;
648						case 2:
649							htonmemcpy(&tsizeh, &buffer[decode_pos], MVT_U16, 2);
650							tsize = tsizeh;
651							break;
652						case 4:
653							htonmemcpy(&tsize, &buffer[decode_pos], MVT_U32, 4);
654							break;
655						default:
656							llerrs << "Attempting to read variable field with unknown size of " << data_size << llendl;
657							break;
658						}
659					}
660					decode_pos += data_size;
661
662					cur_data_block->addData(mvci.getName(), &buffer[decode_pos], tsize, mvci.getType());
663					decode_pos += tsize;
664				}
665				else
666				{
667					// fixed!
668					// so, copy data pointer and set data size to fixed size
669					if ((decode_pos + mvci.getSize()) > mReceiveSize)
670					{
671						logRanOffEndOfPacket(sender, decode_pos, mvci.getSize());
672
673						// default to 0s.
674						U32 size = mvci.getSize();
675						std::vector<U8> data(size, 0);
676						cur_data_block->addData(mvci.getName(), &(data[0]), 
677												size, mvci.getType());
678					}
679					else
680					{
681						cur_data_block->addData(mvci.getName(), 
682												&buffer[decode_pos], 
683												mvci.getSize(), 
684												mvci.getType());
685					}
686					decode_pos += mvci.getSize();
687				}
688			}
689		}
690	}
691
692	if (mCurrentRMessageData->mMemberBlocks.empty()
693		&& !mCurrentRMessageTemplate->mMemberBlocks.empty())
694	{
695		lldebugs << "Empty message '" << mCurrentRMessageTemplate->mName << "' (no blocks)" << llendl;
696		return FALSE;
697	}
698
699	{
700		static LLTimer decode_timer;
701
702		if(LLMessageReader::getTimeDecodes() || gMessageSystem->getTimingCallback())
703		{
704			decode_timer.reset();
705		}
706
707		{
708			LLFastTimer t(FTM_PROCESS_MESSAGES);
709			if( !mCurrentRMessageTemplate->callHandlerFunc(gMessageSystem) )
710			{
711				llwarns << "Message from " << sender << " with no handler function received: " << mCurrentRMessageTemplate->mName << llendl;
712			}
713		}
714
715		if(LLMessageReader::getTimeDecodes() || gMessageSystem->getTimingCallback())
716		{
717			F32 decode_time = decode_timer.getElapsedTimeF32();
718
719			if (gMessageSystem->getTimingCallback())
720			{
721				(gMessageSystem->getTimingCallback())(mCurrentRMessageTemplate->mName,
722								decode_time,
723								gMessageSystem->getTimingCallbackData());
724			}
725
726			if (LLMessageReader::getTimeDecodes())
727			{
728				mCurrentRMessageTemplate->mDecodeTimeThisFrame += decode_time;
729
730				mCurrentRMessageTemplate->mTotalDecoded++;
731				mCurrentRMessageTemplate->mTotalDecodeTime += decode_time;
732
733				if( mCurrentRMessageTemplate->mMaxDecodeTimePerMsg < decode_time )
734				{
735					mCurrentRMessageTemplate->mMaxDecodeTimePerMsg = decode_time;
736				}
737
738
739				if(decode_time > LLMessageReader::getTimeDecodesSpamThreshold())
740				{
741					lldebugs << "--------- Message " << mCurrentRMessageTemplate->mName << " decode took " << decode_time << " seconds. (" <<
742						mCurrentRMessageTemplate->mMaxDecodeTimePerMsg << " max, " <<
743						(mCurrentRMessageTemplate->mTotalDecodeTime / mCurrentRMessageTemplate->mTotalDecoded) << " avg)" << llendl;
744				}
745			}
746		}
747	}
748	return TRUE;
749}
750
751BOOL LLTemplateMessageReader::validateMessage(const U8* buffer, 
752											  S32 buffer_size, 
753											  const LLHost& sender,
754											  bool trusted)
755{
756	mReceiveSize = buffer_size;
757	BOOL valid = decodeTemplate(buffer, buffer_size, &mCurrentRMessageTemplate );
758	if(valid)
759	{
760		mCurrentRMessageTemplate->mReceiveCount++;
761		//lldebugs << "MessageRecvd:"
762		//						 << mCurrentRMessageTemplate->mName 
763		//						 << " from " << sender << llendl;
764	}
765
766	if (valid && isBanned(trusted))
767	{
768		LL_WARNS("Messaging") << "LLMessageSystem::checkMessages "
769			<< "received banned message "
770			<< getMessageName()
771			<< " from "
772			<< ((trusted) ? "trusted " : "untrusted ")
773			<< sender << llendl;
774		valid = FALSE;
775	}
776
777	if(valid && isUdpBanned())
778	{
779		llwarns << "Received UDP black listed message "
780				<<  getMessageName()
781				<< " from " << sender << llendl;
782		valid = FALSE;
783	}
784	return valid;
785}
786
787BOOL LLTemplateMessageReader::readMessage(const U8* buffer, 
788										  const LLHost& sender)
789{
790	return decodeData(buffer, sender);
791}
792
793//virtual 
794const char* LLTemplateMessageReader::getMessageName() const
795{
796	if (!mCurrentRMessageTemplate)
797	{
798		// no message currently being read
799		return "";
800	}
801	return mCurrentRMessageTemplate->mName;
802}
803
804//virtual 
805bool LLTemplateMessageReader::isTrusted() const
806{
807	return mCurrentRMessageTemplate->getTrust() == MT_TRUST;
808}
809
810bool LLTemplateMessageReader::isBanned(bool trustedSource) const
811{
812	return mCurrentRMessageTemplate->isBanned(trustedSource);
813}
814
815bool LLTemplateMessageReader::isUdpBanned() const
816{
817	return mCurrentRMessageTemplate->isUdpBanned();
818}
819
820//virtual 
821void LLTemplateMessageReader::copyToBuilder(LLMessageBuilder& builder) const
822{
823	if(NULL == mCurrentRMessageTemplate)
824    {
825        return;
826    }
827	builder.copyFromMessageData(*mCurrentRMessageData);
828}