summaryrefslogtreecommitdiff
path: root/indra/llmessage/lltemplatemessagereader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llmessage/lltemplatemessagereader.cpp')
-rw-r--r--indra/llmessage/lltemplatemessagereader.cpp1660
1 files changed, 830 insertions, 830 deletions
diff --git a/indra/llmessage/lltemplatemessagereader.cpp b/indra/llmessage/lltemplatemessagereader.cpp
index 46123f0f55..b62288590e 100644
--- a/indra/llmessage/lltemplatemessagereader.cpp
+++ b/indra/llmessage/lltemplatemessagereader.cpp
@@ -1,830 +1,830 @@
-/**
- * @file lltemplatemessagereader.cpp
- * @brief LLTemplateMessageReader class implementation.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-#include "lltemplatemessagereader.h"
-
-#include "llfasttimer.h"
-#include "llmessagebuilder.h"
-#include "llmessagetemplate.h"
-#include "llmath.h"
-#include "llquaternion.h"
-#include "message.h"
-#include "u64.h"
-#include "v3dmath.h"
-#include "v3math.h"
-#include "v4math.h"
-
-LLTemplateMessageReader::LLTemplateMessageReader(message_template_number_map_t&
- number_template_map) :
- mReceiveSize(0),
- mCurrentRMessageTemplate(NULL),
- mCurrentRMessageData(NULL),
- mMessageNumbers(number_template_map)
-{
-}
-
-//virtual
-LLTemplateMessageReader::~LLTemplateMessageReader()
-{
- delete mCurrentRMessageData;
- mCurrentRMessageData = NULL;
-}
-
-//virtual
-void LLTemplateMessageReader::clearMessage()
-{
- mReceiveSize = -1;
- mCurrentRMessageTemplate = NULL;
- delete mCurrentRMessageData;
- mCurrentRMessageData = NULL;
-}
-
-void LLTemplateMessageReader::getData(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum, S32 max_size)
-{
- // is there a message ready to go?
- if (mReceiveSize == -1)
- {
- LL_ERRS() << "No message waiting for decode 2!" << LL_ENDL;
- return;
- }
-
- if (!mCurrentRMessageData)
- {
- LL_ERRS() << "Invalid mCurrentMessageData in getData!" << LL_ENDL;
- return;
- }
-
- char *bnamep = (char *)blockname + blocknum; // this works because it's just a hash. The bnamep is never derefference
- char *vnamep = (char *)varname;
-
- LLMsgData::msg_blk_data_map_t::const_iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep);
-
- if (iter == mCurrentRMessageData->mMemberBlocks.end())
- {
- LL_ERRS() << "Block " << blockname << " #" << blocknum
- << " not in message " << mCurrentRMessageData->mName << LL_ENDL;
- return;
- }
-
- LLMsgBlkData *msg_block_data = iter->second;
- LLMsgBlkData::msg_var_data_map_t &var_data_map = msg_block_data->mMemberVarData;
-
- if (var_data_map.find(vnamep) == var_data_map.end())
- {
- LL_ERRS() << "Variable "<< vnamep << " not in message "
- << mCurrentRMessageData->mName<< " block " << bnamep << LL_ENDL;
- return;
- }
-
- LLMsgVarData& vardata = msg_block_data->mMemberVarData[vnamep];
-
- if (size && size != vardata.getSize())
- {
- LL_ERRS() << "Msg " << mCurrentRMessageData->mName
- << " variable " << vnamep
- << " is size " << vardata.getSize()
- << " but copying into buffer of size " << size
- << LL_ENDL;
- return;
- }
-
-
- const S32 vardata_size = vardata.getSize();
- if( max_size >= vardata_size )
- {
- switch( vardata_size )
- {
- case 1:
- *((U8*)datap) = *((U8*)vardata.getData());
- break;
- case 2:
- *((U16*)datap) = *((U16*)vardata.getData());
- break;
- case 4:
- *((U32*)datap) = *((U32*)vardata.getData());
- break;
- case 8:
- ((U32*)datap)[0] = ((U32*)vardata.getData())[0];
- ((U32*)datap)[1] = ((U32*)vardata.getData())[1];
- break;
- default:
- memcpy(datap, vardata.getData(), vardata_size);
- break;
- }
- }
- else
- {
- LL_WARNS() << "Msg " << mCurrentRMessageData->mName
- << " variable " << vnamep
- << " is size " << vardata.getSize()
- << " but truncated to max size of " << max_size
- << LL_ENDL;
-
- memcpy(datap, vardata.getData(), max_size);
- }
-}
-
-S32 LLTemplateMessageReader::getNumberOfBlocks(const char *blockname)
-{
- // is there a message ready to go?
- if (mReceiveSize == -1)
- {
- LL_ERRS() << "No message waiting for decode 3!" << LL_ENDL;
- return -1;
- }
-
- if (!mCurrentRMessageData)
- {
- LL_ERRS() << "Invalid mCurrentRMessageData in getData!" << LL_ENDL;
- return -1;
- }
-
- char *bnamep = (char *)blockname;
-
- LLMsgData::msg_blk_data_map_t::const_iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep);
-
- if (iter == mCurrentRMessageData->mMemberBlocks.end())
- {
- return 0;
- }
-
- return (iter->second)->mBlockNumber;
-}
-
-S32 LLTemplateMessageReader::getSize(const char *blockname, const char *varname)
-{
- // is there a message ready to go?
- if (mReceiveSize == -1)
- { // This is a serious error - crash
- LL_ERRS() << "No message waiting for decode 4!" << LL_ENDL;
- return LL_MESSAGE_ERROR;
- }
-
- if (!mCurrentRMessageData)
- { // This is a serious error - crash
- LL_ERRS() << "Invalid mCurrentRMessageData in getData!" << LL_ENDL;
- return LL_MESSAGE_ERROR;
- }
-
- char *bnamep = (char *)blockname;
-
- LLMsgData::msg_blk_data_map_t::const_iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep);
-
- if (iter == mCurrentRMessageData->mMemberBlocks.end())
- { // don't crash
- LL_INFOS() << "Block " << bnamep << " not in message "
- << mCurrentRMessageData->mName << LL_ENDL;
- return LL_BLOCK_NOT_IN_MESSAGE;
- }
-
- char *vnamep = (char *)varname;
-
- LLMsgBlkData* msg_data = iter->second;
- LLMsgVarData& vardata = msg_data->mMemberVarData[vnamep];
-
- if (!vardata.getName())
- { // don't crash
- LL_INFOS() << "Variable " << varname << " not in message "
- << mCurrentRMessageData->mName << " block " << bnamep << LL_ENDL;
- return LL_VARIABLE_NOT_IN_BLOCK;
- }
-
- if (mCurrentRMessageTemplate->mMemberBlocks[bnamep]->mType != MBT_SINGLE)
- { // This is a serious error - crash
- LL_ERRS() << "Block " << bnamep << " isn't type MBT_SINGLE,"
- " use getSize with blocknum argument!" << LL_ENDL;
- return LL_MESSAGE_ERROR;
- }
-
- return vardata.getSize();
-}
-
-S32 LLTemplateMessageReader::getSize(const char *blockname, S32 blocknum, const char *varname)
-{
- // is there a message ready to go?
- if (mReceiveSize == -1)
- { // This is a serious error - crash
- LL_ERRS() << "No message waiting for decode 5!" << LL_ENDL;
- return LL_MESSAGE_ERROR;
- }
-
- if (!mCurrentRMessageData)
- { // This is a serious error - crash
- LL_ERRS() << "Invalid mCurrentRMessageData in getData!" << LL_ENDL;
- return LL_MESSAGE_ERROR;
- }
-
- char *bnamep = (char *)blockname + blocknum;
- char *vnamep = (char *)varname;
-
- LLMsgData::msg_blk_data_map_t::const_iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep);
-
- if (iter == mCurrentRMessageData->mMemberBlocks.end())
- { // don't crash
- LL_INFOS() << "Block " << bnamep << " not in message "
- << mCurrentRMessageData->mName << LL_ENDL;
- return LL_BLOCK_NOT_IN_MESSAGE;
- }
-
- LLMsgBlkData* msg_data = iter->second;
- LLMsgVarData& vardata = msg_data->mMemberVarData[vnamep];
-
- if (!vardata.getName())
- { // don't crash
- LL_INFOS() << "Variable " << vnamep << " not in message "
- << mCurrentRMessageData->mName << " block " << bnamep << LL_ENDL;
- return LL_VARIABLE_NOT_IN_BLOCK;
- }
-
- return vardata.getSize();
-}
-
-void LLTemplateMessageReader::getBinaryData(const char *blockname,
- const char *varname, void *datap,
- S32 size, S32 blocknum,
- S32 max_size)
-{
- getData(blockname, varname, datap, size, blocknum, max_size);
-}
-
-void LLTemplateMessageReader::getS8(const char *block, const char *var,
- S8 &u, S32 blocknum)
-{
- getData(block, var, &u, sizeof(S8), blocknum);
-}
-
-void LLTemplateMessageReader::getU8(const char *block, const char *var,
- U8 &u, S32 blocknum)
-{
- getData(block, var, &u, sizeof(U8), blocknum);
-}
-
-void LLTemplateMessageReader::getBOOL(const char *block, const char *var,
- bool &b, S32 blocknum )
-{
- U8 value;
- getData(block, var, &value, sizeof(U8), blocknum);
- b = (bool)value;
-}
-
-void LLTemplateMessageReader::getS16(const char *block, const char *var,
- S16 &d, S32 blocknum)
-{
- getData(block, var, &d, sizeof(S16), blocknum);
-}
-
-void LLTemplateMessageReader::getU16(const char *block, const char *var,
- U16 &d, S32 blocknum)
-{
- getData(block, var, &d, sizeof(U16), blocknum);
-}
-
-void LLTemplateMessageReader::getS32(const char *block, const char *var,
- S32 &d, S32 blocknum)
-{
- getData(block, var, &d, sizeof(S32), blocknum);
-}
-
-void LLTemplateMessageReader::getU32(const char *block, const char *var,
- U32 &d, S32 blocknum)
-{
- getData(block, var, &d, sizeof(U32), blocknum);
-}
-
-void LLTemplateMessageReader::getU64(const char *block, const char *var,
- U64 &d, S32 blocknum)
-{
- getData(block, var, &d, sizeof(U64), blocknum);
-}
-
-void LLTemplateMessageReader::getF32(const char *block, const char *var,
- F32 &d, S32 blocknum)
-{
- getData(block, var, &d, sizeof(F32), blocknum);
-
- if( !llfinite( d ) )
- {
- LL_WARNS() << "non-finite in getF32Fast " << block << " " << var
- << LL_ENDL;
- d = 0;
- }
-}
-
-void LLTemplateMessageReader::getF64(const char *block, const char *var,
- F64 &d, S32 blocknum)
-{
- getData(block, var, &d, sizeof(F64), blocknum);
-
- if( !llfinite( d ) )
- {
- LL_WARNS() << "non-finite in getF64Fast " << block << " " << var
- << LL_ENDL;
- d = 0;
- }
-}
-
-void LLTemplateMessageReader::getVector3(const char *block, const char *var,
- LLVector3 &v, S32 blocknum )
-{
- getData(block, var, &v.mV[0], sizeof(v.mV), blocknum);
-
- if( !v.isFinite() )
- {
- LL_WARNS() << "non-finite in getVector3Fast " << block << " "
- << var << LL_ENDL;
- v.zeroVec();
- }
-}
-
-void LLTemplateMessageReader::getVector4(const char *block, const char *var,
- LLVector4 &v, S32 blocknum)
-{
- getData(block, var, &v.mV[0], sizeof(v.mV), blocknum);
-
- if( !v.isFinite() )
- {
- LL_WARNS() << "non-finite in getVector4Fast " << block << " "
- << var << LL_ENDL;
- v.zeroVec();
- }
-}
-
-void LLTemplateMessageReader::getVector3d(const char *block, const char *var,
- LLVector3d &v, S32 blocknum )
-{
- getData(block, var, &v.mdV[0], sizeof(v.mdV), blocknum);
-
- if( !v.isFinite() )
- {
- LL_WARNS() << "non-finite in getVector3dFast " << block << " "
- << var << LL_ENDL;
- v.zeroVec();
- }
-
-}
-
-void LLTemplateMessageReader::getQuat(const char *block, const char *var,
- LLQuaternion &q, S32 blocknum)
-{
- LLVector3 vec;
- getData(block, var, &vec.mV[0], sizeof(vec.mV), blocknum);
- if( vec.isFinite() )
- {
- q.unpackFromVector3( vec );
- }
- else
- {
- LL_WARNS() << "non-finite in getQuatFast " << block << " " << var
- << LL_ENDL;
- q.loadIdentity();
- }
-}
-
-void LLTemplateMessageReader::getUUID(const char *block, const char *var,
- LLUUID &u, S32 blocknum)
-{
- getData(block, var, &u.mData[0], sizeof(u.mData), blocknum);
-}
-
-inline void LLTemplateMessageReader::getIPAddr(const char *block, const char *var, U32 &u, S32 blocknum)
-{
- getData(block, var, &u, sizeof(U32), blocknum);
-}
-
-inline void LLTemplateMessageReader::getIPPort(const char *block, const char *var, U16 &u, S32 blocknum)
-{
- getData(block, var, &u, sizeof(U16), blocknum);
- u = ntohs(u);
-}
-
-inline void LLTemplateMessageReader::getString(const char *block, const char *var, S32 buffer_size, char *s, S32 blocknum )
-{
- s[0] = '\0';
- getData(block, var, s, 0, blocknum, buffer_size);
- s[buffer_size - 1] = '\0';
-}
-
-inline void LLTemplateMessageReader::getString(const char *block, const char *var, std::string& outstr, S32 blocknum )
-{
- char s[MTUBYTES + 1]= {0}; // every element is initialized with 0
- getData(block, var, s, 0, blocknum, MTUBYTES);
- s[MTUBYTES] = '\0';
- outstr = s;
-}
-
-//virtual
-S32 LLTemplateMessageReader::getMessageSize() const
-{
- return mReceiveSize;
-}
-
-// Returns template for the message contained in buffer
-bool LLTemplateMessageReader::decodeTemplate(
- const U8* buffer, S32 buffer_size, // inputs
- LLMessageTemplate** msg_template ) // outputs
-{
- const U8* header = buffer + LL_PACKET_ID_SIZE;
-
- // is there a message ready to go?
- if (buffer_size <= 0)
- {
- LL_WARNS() << "No message waiting for decode!" << LL_ENDL;
- return(false);
- }
-
- U32 num = 0;
-
- if (header[0] != 255)
- {
- // high frequency message
- num = header[0];
- }
- else if ((buffer_size >= ((S32) LL_MINIMUM_VALID_PACKET_SIZE + 1)) && (header[1] != 255))
- {
- // medium frequency message
- num = (255 << 8) | header[1];
- }
- else if ((buffer_size >= ((S32) LL_MINIMUM_VALID_PACKET_SIZE + 3)) && (header[1] == 255))
- {
- // low frequency message
- U16 message_id_U16 = 0;
- // I think this check busts the message system.
- // it appears that if there is a NULL in the message #, it won't copy it....
- // what was the goal?
- //if(header[2])
- memcpy(&message_id_U16, &header[2], 2);
-
- // dependant on endian-ness:
- // U32 temp = (255 << 24) | (255 << 16) | header[2];
-
- // independant of endian-ness:
- message_id_U16 = ntohs(message_id_U16);
- num = 0xFFFF0000 | message_id_U16;
- }
- else // bogus packet received (too short)
- {
- LL_WARNS() << "Packet with unusable length received (too short): "
- << buffer_size << LL_ENDL;
- return(false);
- }
-
- LLMessageTemplate* temp = get_ptr_in_map(mMessageNumbers,num);
- if (temp)
- {
- *msg_template = temp;
- }
- else
- {
- // MAINT-7482 - make viewer more tolerant of unknown messages.
- LL_WARNS_ONCE() << "Message #" << std::hex << num << std::dec
- << " received but not registered!" << LL_ENDL;
- //gMessageSystem->callExceptionFunc(MX_UNREGISTERED_MESSAGE);
- return(false);
- }
-
- return(true);
-}
-
-void LLTemplateMessageReader::logRanOffEndOfPacket( const LLHost& host, const S32 where, const S32 wanted )
-{
- // we've run off the end of the packet!
- LL_WARNS() << "Ran off end of packet " << mCurrentRMessageTemplate->mName
-// << " with id " << mCurrentRecvPacketID
- << " from " << host
- << " trying to read " << wanted
- << " bytes at position " << where
- << " going past packet end at " << mReceiveSize
- << LL_ENDL;
- if(gMessageSystem->mVerboseLog)
- {
- LL_INFOS() << "MSG: -> " << host << "\tREAD PAST END:\t"
-// << mCurrentRecvPacketID << " "
- << getMessageName() << LL_ENDL;
- }
- gMessageSystem->callExceptionFunc(MX_RAN_OFF_END_OF_PACKET);
-}
-
-static LLTrace::BlockTimerStatHandle FTM_PROCESS_MESSAGES("Process Messages");
-
-// decode a given message
-bool LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender )
-{
- LL_RECORD_BLOCK_TIME(FTM_PROCESS_MESSAGES);
-
- llassert( mReceiveSize >= 0 );
- llassert( mCurrentRMessageTemplate);
- llassert( !mCurrentRMessageData );
- delete mCurrentRMessageData; // just to make sure
-
- // The offset tells us how may bytes to skip after the end of the
- // message name.
- U8 offset = buffer[PHL_OFFSET];
- S32 decode_pos = LL_PACKET_ID_SIZE + (S32)(mCurrentRMessageTemplate->mFrequency) + offset;
-
- // create base working data set
- mCurrentRMessageData = new LLMsgData(mCurrentRMessageTemplate->mName);
-
- // loop through the template building the data structure as we go
- LLMessageTemplate::message_block_map_t::const_iterator iter;
- for(iter = mCurrentRMessageTemplate->mMemberBlocks.begin();
- iter != mCurrentRMessageTemplate->mMemberBlocks.end();
- ++iter)
- {
- LLMessageBlock* mbci = *iter;
- U8 repeat_number;
- S32 i;
-
- // how many of this block?
-
- if (mbci->mType == MBT_SINGLE)
- {
- // just one
- repeat_number = 1;
- }
- else if (mbci->mType == MBT_MULTIPLE)
- {
- // a known number
- repeat_number = mbci->mNumber;
- }
- else if (mbci->mType == MBT_VARIABLE)
- {
- // need to read the number from the message
- // repeat number is a single byte
- if (decode_pos >= mReceiveSize)
- {
- // commented out - hetgrid says that missing variable blocks
- // at end of message are legal
- // logRanOffEndOfPacket(sender, decode_pos, 1);
-
- // default to 0 repeats
- repeat_number = 0;
- }
- else
- {
- repeat_number = buffer[decode_pos];
- decode_pos++;
- }
- }
- else
- {
- LL_ERRS() << "Unknown block type" << LL_ENDL;
- return false;
- }
-
- LLMsgBlkData* cur_data_block = NULL;
-
- // now loop through the block
- for (i = 0; i < repeat_number; i++)
- {
- if (i)
- {
- // build new name to prevent collisions
- // TODO: This should really change to a vector
- cur_data_block = new LLMsgBlkData(mbci->mName, repeat_number);
- cur_data_block->mName = mbci->mName + i;
- }
- else
- {
- cur_data_block = new LLMsgBlkData(mbci->mName, repeat_number);
- }
-
- // add the block to the message
- mCurrentRMessageData->addBlock(cur_data_block);
-
- // now read the variables
- for (LLMessageBlock::message_variable_map_t::const_iterator iter =
- mbci->mMemberVariables.begin();
- iter != mbci->mMemberVariables.end(); iter++)
- {
- const LLMessageVariable& mvci = **iter;
-
- // ok, build out the variables
- // add variable block
- cur_data_block->addVariable(mvci.getName(), mvci.getType());
-
- // what type of variable?
- if (mvci.getType() == MVT_VARIABLE)
- {
- // variable, get the number of bytes to read from the template
- S32 data_size = mvci.getSize();
- U8 tsizeb = 0;
- U16 tsizeh = 0;
- U32 tsize = 0;
-
- if ((decode_pos + data_size) > mReceiveSize)
- {
- logRanOffEndOfPacket(sender, decode_pos, data_size);
-
- // default to 0 length variable blocks
- tsize = 0;
- }
- else
- {
- switch(data_size)
- {
- case 1:
- htolememcpy(&tsizeb, &buffer[decode_pos], MVT_U8, 1);
- tsize = tsizeb;
- break;
- case 2:
- htolememcpy(&tsizeh, &buffer[decode_pos], MVT_U16, 2);
- tsize = tsizeh;
- break;
- case 4:
- htolememcpy(&tsize, &buffer[decode_pos], MVT_U32, 4);
- break;
- default:
- LL_ERRS() << "Attempting to read variable field with unknown size of " << data_size << LL_ENDL;
- break;
- }
- }
- decode_pos += data_size;
-
- cur_data_block->addData(mvci.getName(), &buffer[decode_pos], tsize, mvci.getType());
- decode_pos += tsize;
- }
- else
- {
- // fixed!
- // so, copy data pointer and set data size to fixed size
- if ((decode_pos + mvci.getSize()) > mReceiveSize)
- {
- logRanOffEndOfPacket(sender, decode_pos, mvci.getSize());
-
- // default to 0s.
- U32 size = mvci.getSize();
- std::vector<U8> data(size, 0);
- cur_data_block->addData(mvci.getName(), &(data[0]),
- size, mvci.getType());
- }
- else
- {
- cur_data_block->addData(mvci.getName(),
- &buffer[decode_pos],
- mvci.getSize(),
- mvci.getType());
- }
- decode_pos += mvci.getSize();
- }
- }
- }
- }
-
- if (mCurrentRMessageData->mMemberBlocks.empty()
- && !mCurrentRMessageTemplate->mMemberBlocks.empty())
- {
- LL_DEBUGS() << "Empty message '" << mCurrentRMessageTemplate->mName << "' (no blocks)" << LL_ENDL;
- return false;
- }
-
- {
- static LLTimer decode_timer;
-
- if(LLMessageReader::getTimeDecodes() || gMessageSystem->getTimingCallback())
- {
- decode_timer.reset();
- }
-
- if( !mCurrentRMessageTemplate->callHandlerFunc(gMessageSystem) )
- {
- LL_WARNS() << "Message from " << sender << " with no handler function received: " << mCurrentRMessageTemplate->mName << LL_ENDL;
- }
-
- if(LLMessageReader::getTimeDecodes() || gMessageSystem->getTimingCallback())
- {
- F32 decode_time = decode_timer.getElapsedTimeF32();
-
- if (gMessageSystem->getTimingCallback())
- {
- (gMessageSystem->getTimingCallback())(mCurrentRMessageTemplate->mName,
- decode_time,
- gMessageSystem->getTimingCallbackData());
- }
-
- if (LLMessageReader::getTimeDecodes())
- {
- mCurrentRMessageTemplate->mDecodeTimeThisFrame += decode_time;
-
- mCurrentRMessageTemplate->mTotalDecoded++;
- mCurrentRMessageTemplate->mTotalDecodeTime += decode_time;
-
- if( mCurrentRMessageTemplate->mMaxDecodeTimePerMsg < decode_time )
- {
- mCurrentRMessageTemplate->mMaxDecodeTimePerMsg = decode_time;
- }
-
-
- if(decode_time > LLMessageReader::getTimeDecodesSpamThreshold())
- {
- LL_DEBUGS() << "--------- Message " << mCurrentRMessageTemplate->mName << " decode took " << decode_time << " seconds. (" <<
- mCurrentRMessageTemplate->mMaxDecodeTimePerMsg << " max, " <<
- (mCurrentRMessageTemplate->mTotalDecodeTime / mCurrentRMessageTemplate->mTotalDecoded) << " avg)" << LL_ENDL;
- }
- }
- }
- }
- return true;
-}
-
-bool LLTemplateMessageReader::validateMessage(const U8* buffer,
- S32 buffer_size,
- const LLHost& sender,
- bool trusted)
-{
- mReceiveSize = buffer_size;
- bool valid = decodeTemplate(buffer, buffer_size, &mCurrentRMessageTemplate );
- if(valid)
- {
- mCurrentRMessageTemplate->mReceiveCount++;
- //LL_DEBUGS() << "MessageRecvd:"
- // << mCurrentRMessageTemplate->mName
- // << " from " << sender << LL_ENDL;
- }
-
- if (valid && isBanned(trusted))
- {
- LL_WARNS("Messaging") << "LLMessageSystem::checkMessages "
- << "received banned message "
- << getMessageName()
- << " from "
- << ((trusted) ? "trusted " : "untrusted ")
- << sender << LL_ENDL;
- valid = false;
- }
-
- if(valid && isUdpBanned())
- {
- LL_WARNS() << "Received UDP black listed message "
- << getMessageName()
- << " from " << sender << LL_ENDL;
- valid = false;
- }
- return valid;
-}
-
-bool LLTemplateMessageReader::readMessage(const U8* buffer,
- const LLHost& sender)
-{
- return decodeData(buffer, sender);
-}
-
-//virtual
-const char* LLTemplateMessageReader::getMessageName() const
-{
- if (!mCurrentRMessageTemplate)
- {
- // no message currently being read
- return "";
- }
- return mCurrentRMessageTemplate->mName;
-}
-
-//virtual
-bool LLTemplateMessageReader::isTrusted() const
-{
- return mCurrentRMessageTemplate->getTrust() == MT_TRUST;
-}
-
-bool LLTemplateMessageReader::isBanned(bool trustedSource) const
-{
- return mCurrentRMessageTemplate->isBanned(trustedSource);
-}
-
-bool LLTemplateMessageReader::isUdpBanned() const
-{
- return mCurrentRMessageTemplate->isUdpBanned();
-}
-
-//virtual
-void LLTemplateMessageReader::copyToBuilder(LLMessageBuilder& builder) const
-{
- if(NULL == mCurrentRMessageTemplate)
- {
- return;
- }
- builder.copyFromMessageData(*mCurrentRMessageData);
-}
+/**
+ * @file lltemplatemessagereader.cpp
+ * @brief LLTemplateMessageReader class implementation.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "lltemplatemessagereader.h"
+
+#include "llfasttimer.h"
+#include "llmessagebuilder.h"
+#include "llmessagetemplate.h"
+#include "llmath.h"
+#include "llquaternion.h"
+#include "message.h"
+#include "u64.h"
+#include "v3dmath.h"
+#include "v3math.h"
+#include "v4math.h"
+
+LLTemplateMessageReader::LLTemplateMessageReader(message_template_number_map_t&
+ number_template_map) :
+ mReceiveSize(0),
+ mCurrentRMessageTemplate(NULL),
+ mCurrentRMessageData(NULL),
+ mMessageNumbers(number_template_map)
+{
+}
+
+//virtual
+LLTemplateMessageReader::~LLTemplateMessageReader()
+{
+ delete mCurrentRMessageData;
+ mCurrentRMessageData = NULL;
+}
+
+//virtual
+void LLTemplateMessageReader::clearMessage()
+{
+ mReceiveSize = -1;
+ mCurrentRMessageTemplate = NULL;
+ delete mCurrentRMessageData;
+ mCurrentRMessageData = NULL;
+}
+
+void LLTemplateMessageReader::getData(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum, S32 max_size)
+{
+ // is there a message ready to go?
+ if (mReceiveSize == -1)
+ {
+ LL_ERRS() << "No message waiting for decode 2!" << LL_ENDL;
+ return;
+ }
+
+ if (!mCurrentRMessageData)
+ {
+ LL_ERRS() << "Invalid mCurrentMessageData in getData!" << LL_ENDL;
+ return;
+ }
+
+ char *bnamep = (char *)blockname + blocknum; // this works because it's just a hash. The bnamep is never derefference
+ char *vnamep = (char *)varname;
+
+ LLMsgData::msg_blk_data_map_t::const_iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep);
+
+ if (iter == mCurrentRMessageData->mMemberBlocks.end())
+ {
+ LL_ERRS() << "Block " << blockname << " #" << blocknum
+ << " not in message " << mCurrentRMessageData->mName << LL_ENDL;
+ return;
+ }
+
+ LLMsgBlkData *msg_block_data = iter->second;
+ LLMsgBlkData::msg_var_data_map_t &var_data_map = msg_block_data->mMemberVarData;
+
+ if (var_data_map.find(vnamep) == var_data_map.end())
+ {
+ LL_ERRS() << "Variable "<< vnamep << " not in message "
+ << mCurrentRMessageData->mName<< " block " << bnamep << LL_ENDL;
+ return;
+ }
+
+ LLMsgVarData& vardata = msg_block_data->mMemberVarData[vnamep];
+
+ if (size && size != vardata.getSize())
+ {
+ LL_ERRS() << "Msg " << mCurrentRMessageData->mName
+ << " variable " << vnamep
+ << " is size " << vardata.getSize()
+ << " but copying into buffer of size " << size
+ << LL_ENDL;
+ return;
+ }
+
+
+ const S32 vardata_size = vardata.getSize();
+ if( max_size >= vardata_size )
+ {
+ switch( vardata_size )
+ {
+ case 1:
+ *((U8*)datap) = *((U8*)vardata.getData());
+ break;
+ case 2:
+ *((U16*)datap) = *((U16*)vardata.getData());
+ break;
+ case 4:
+ *((U32*)datap) = *((U32*)vardata.getData());
+ break;
+ case 8:
+ ((U32*)datap)[0] = ((U32*)vardata.getData())[0];
+ ((U32*)datap)[1] = ((U32*)vardata.getData())[1];
+ break;
+ default:
+ memcpy(datap, vardata.getData(), vardata_size);
+ break;
+ }
+ }
+ else
+ {
+ LL_WARNS() << "Msg " << mCurrentRMessageData->mName
+ << " variable " << vnamep
+ << " is size " << vardata.getSize()
+ << " but truncated to max size of " << max_size
+ << LL_ENDL;
+
+ memcpy(datap, vardata.getData(), max_size);
+ }
+}
+
+S32 LLTemplateMessageReader::getNumberOfBlocks(const char *blockname)
+{
+ // is there a message ready to go?
+ if (mReceiveSize == -1)
+ {
+ LL_ERRS() << "No message waiting for decode 3!" << LL_ENDL;
+ return -1;
+ }
+
+ if (!mCurrentRMessageData)
+ {
+ LL_ERRS() << "Invalid mCurrentRMessageData in getData!" << LL_ENDL;
+ return -1;
+ }
+
+ char *bnamep = (char *)blockname;
+
+ LLMsgData::msg_blk_data_map_t::const_iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep);
+
+ if (iter == mCurrentRMessageData->mMemberBlocks.end())
+ {
+ return 0;
+ }
+
+ return (iter->second)->mBlockNumber;
+}
+
+S32 LLTemplateMessageReader::getSize(const char *blockname, const char *varname)
+{
+ // is there a message ready to go?
+ if (mReceiveSize == -1)
+ { // This is a serious error - crash
+ LL_ERRS() << "No message waiting for decode 4!" << LL_ENDL;
+ return LL_MESSAGE_ERROR;
+ }
+
+ if (!mCurrentRMessageData)
+ { // This is a serious error - crash
+ LL_ERRS() << "Invalid mCurrentRMessageData in getData!" << LL_ENDL;
+ return LL_MESSAGE_ERROR;
+ }
+
+ char *bnamep = (char *)blockname;
+
+ LLMsgData::msg_blk_data_map_t::const_iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep);
+
+ if (iter == mCurrentRMessageData->mMemberBlocks.end())
+ { // don't crash
+ LL_INFOS() << "Block " << bnamep << " not in message "
+ << mCurrentRMessageData->mName << LL_ENDL;
+ return LL_BLOCK_NOT_IN_MESSAGE;
+ }
+
+ char *vnamep = (char *)varname;
+
+ LLMsgBlkData* msg_data = iter->second;
+ LLMsgVarData& vardata = msg_data->mMemberVarData[vnamep];
+
+ if (!vardata.getName())
+ { // don't crash
+ LL_INFOS() << "Variable " << varname << " not in message "
+ << mCurrentRMessageData->mName << " block " << bnamep << LL_ENDL;
+ return LL_VARIABLE_NOT_IN_BLOCK;
+ }
+
+ if (mCurrentRMessageTemplate->mMemberBlocks[bnamep]->mType != MBT_SINGLE)
+ { // This is a serious error - crash
+ LL_ERRS() << "Block " << bnamep << " isn't type MBT_SINGLE,"
+ " use getSize with blocknum argument!" << LL_ENDL;
+ return LL_MESSAGE_ERROR;
+ }
+
+ return vardata.getSize();
+}
+
+S32 LLTemplateMessageReader::getSize(const char *blockname, S32 blocknum, const char *varname)
+{
+ // is there a message ready to go?
+ if (mReceiveSize == -1)
+ { // This is a serious error - crash
+ LL_ERRS() << "No message waiting for decode 5!" << LL_ENDL;
+ return LL_MESSAGE_ERROR;
+ }
+
+ if (!mCurrentRMessageData)
+ { // This is a serious error - crash
+ LL_ERRS() << "Invalid mCurrentRMessageData in getData!" << LL_ENDL;
+ return LL_MESSAGE_ERROR;
+ }
+
+ char *bnamep = (char *)blockname + blocknum;
+ char *vnamep = (char *)varname;
+
+ LLMsgData::msg_blk_data_map_t::const_iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep);
+
+ if (iter == mCurrentRMessageData->mMemberBlocks.end())
+ { // don't crash
+ LL_INFOS() << "Block " << bnamep << " not in message "
+ << mCurrentRMessageData->mName << LL_ENDL;
+ return LL_BLOCK_NOT_IN_MESSAGE;
+ }
+
+ LLMsgBlkData* msg_data = iter->second;
+ LLMsgVarData& vardata = msg_data->mMemberVarData[vnamep];
+
+ if (!vardata.getName())
+ { // don't crash
+ LL_INFOS() << "Variable " << vnamep << " not in message "
+ << mCurrentRMessageData->mName << " block " << bnamep << LL_ENDL;
+ return LL_VARIABLE_NOT_IN_BLOCK;
+ }
+
+ return vardata.getSize();
+}
+
+void LLTemplateMessageReader::getBinaryData(const char *blockname,
+ const char *varname, void *datap,
+ S32 size, S32 blocknum,
+ S32 max_size)
+{
+ getData(blockname, varname, datap, size, blocknum, max_size);
+}
+
+void LLTemplateMessageReader::getS8(const char *block, const char *var,
+ S8 &u, S32 blocknum)
+{
+ getData(block, var, &u, sizeof(S8), blocknum);
+}
+
+void LLTemplateMessageReader::getU8(const char *block, const char *var,
+ U8 &u, S32 blocknum)
+{
+ getData(block, var, &u, sizeof(U8), blocknum);
+}
+
+void LLTemplateMessageReader::getBOOL(const char *block, const char *var,
+ bool &b, S32 blocknum )
+{
+ U8 value;
+ getData(block, var, &value, sizeof(U8), blocknum);
+ b = (bool)value;
+}
+
+void LLTemplateMessageReader::getS16(const char *block, const char *var,
+ S16 &d, S32 blocknum)
+{
+ getData(block, var, &d, sizeof(S16), blocknum);
+}
+
+void LLTemplateMessageReader::getU16(const char *block, const char *var,
+ U16 &d, S32 blocknum)
+{
+ getData(block, var, &d, sizeof(U16), blocknum);
+}
+
+void LLTemplateMessageReader::getS32(const char *block, const char *var,
+ S32 &d, S32 blocknum)
+{
+ getData(block, var, &d, sizeof(S32), blocknum);
+}
+
+void LLTemplateMessageReader::getU32(const char *block, const char *var,
+ U32 &d, S32 blocknum)
+{
+ getData(block, var, &d, sizeof(U32), blocknum);
+}
+
+void LLTemplateMessageReader::getU64(const char *block, const char *var,
+ U64 &d, S32 blocknum)
+{
+ getData(block, var, &d, sizeof(U64), blocknum);
+}
+
+void LLTemplateMessageReader::getF32(const char *block, const char *var,
+ F32 &d, S32 blocknum)
+{
+ getData(block, var, &d, sizeof(F32), blocknum);
+
+ if( !llfinite( d ) )
+ {
+ LL_WARNS() << "non-finite in getF32Fast " << block << " " << var
+ << LL_ENDL;
+ d = 0;
+ }
+}
+
+void LLTemplateMessageReader::getF64(const char *block, const char *var,
+ F64 &d, S32 blocknum)
+{
+ getData(block, var, &d, sizeof(F64), blocknum);
+
+ if( !llfinite( d ) )
+ {
+ LL_WARNS() << "non-finite in getF64Fast " << block << " " << var
+ << LL_ENDL;
+ d = 0;
+ }
+}
+
+void LLTemplateMessageReader::getVector3(const char *block, const char *var,
+ LLVector3 &v, S32 blocknum )
+{
+ getData(block, var, &v.mV[0], sizeof(v.mV), blocknum);
+
+ if( !v.isFinite() )
+ {
+ LL_WARNS() << "non-finite in getVector3Fast " << block << " "
+ << var << LL_ENDL;
+ v.zeroVec();
+ }
+}
+
+void LLTemplateMessageReader::getVector4(const char *block, const char *var,
+ LLVector4 &v, S32 blocknum)
+{
+ getData(block, var, &v.mV[0], sizeof(v.mV), blocknum);
+
+ if( !v.isFinite() )
+ {
+ LL_WARNS() << "non-finite in getVector4Fast " << block << " "
+ << var << LL_ENDL;
+ v.zeroVec();
+ }
+}
+
+void LLTemplateMessageReader::getVector3d(const char *block, const char *var,
+ LLVector3d &v, S32 blocknum )
+{
+ getData(block, var, &v.mdV[0], sizeof(v.mdV), blocknum);
+
+ if( !v.isFinite() )
+ {
+ LL_WARNS() << "non-finite in getVector3dFast " << block << " "
+ << var << LL_ENDL;
+ v.zeroVec();
+ }
+
+}
+
+void LLTemplateMessageReader::getQuat(const char *block, const char *var,
+ LLQuaternion &q, S32 blocknum)
+{
+ LLVector3 vec;
+ getData(block, var, &vec.mV[0], sizeof(vec.mV), blocknum);
+ if( vec.isFinite() )
+ {
+ q.unpackFromVector3( vec );
+ }
+ else
+ {
+ LL_WARNS() << "non-finite in getQuatFast " << block << " " << var
+ << LL_ENDL;
+ q.loadIdentity();
+ }
+}
+
+void LLTemplateMessageReader::getUUID(const char *block, const char *var,
+ LLUUID &u, S32 blocknum)
+{
+ getData(block, var, &u.mData[0], sizeof(u.mData), blocknum);
+}
+
+inline void LLTemplateMessageReader::getIPAddr(const char *block, const char *var, U32 &u, S32 blocknum)
+{
+ getData(block, var, &u, sizeof(U32), blocknum);
+}
+
+inline void LLTemplateMessageReader::getIPPort(const char *block, const char *var, U16 &u, S32 blocknum)
+{
+ getData(block, var, &u, sizeof(U16), blocknum);
+ u = ntohs(u);
+}
+
+inline void LLTemplateMessageReader::getString(const char *block, const char *var, S32 buffer_size, char *s, S32 blocknum )
+{
+ s[0] = '\0';
+ getData(block, var, s, 0, blocknum, buffer_size);
+ s[buffer_size - 1] = '\0';
+}
+
+inline void LLTemplateMessageReader::getString(const char *block, const char *var, std::string& outstr, S32 blocknum )
+{
+ char s[MTUBYTES + 1]= {0}; // every element is initialized with 0
+ getData(block, var, s, 0, blocknum, MTUBYTES);
+ s[MTUBYTES] = '\0';
+ outstr = s;
+}
+
+//virtual
+S32 LLTemplateMessageReader::getMessageSize() const
+{
+ return mReceiveSize;
+}
+
+// Returns template for the message contained in buffer
+bool LLTemplateMessageReader::decodeTemplate(
+ const U8* buffer, S32 buffer_size, // inputs
+ LLMessageTemplate** msg_template ) // outputs
+{
+ const U8* header = buffer + LL_PACKET_ID_SIZE;
+
+ // is there a message ready to go?
+ if (buffer_size <= 0)
+ {
+ LL_WARNS() << "No message waiting for decode!" << LL_ENDL;
+ return(false);
+ }
+
+ U32 num = 0;
+
+ if (header[0] != 255)
+ {
+ // high frequency message
+ num = header[0];
+ }
+ else if ((buffer_size >= ((S32) LL_MINIMUM_VALID_PACKET_SIZE + 1)) && (header[1] != 255))
+ {
+ // medium frequency message
+ num = (255 << 8) | header[1];
+ }
+ else if ((buffer_size >= ((S32) LL_MINIMUM_VALID_PACKET_SIZE + 3)) && (header[1] == 255))
+ {
+ // low frequency message
+ U16 message_id_U16 = 0;
+ // I think this check busts the message system.
+ // it appears that if there is a NULL in the message #, it won't copy it....
+ // what was the goal?
+ //if(header[2])
+ memcpy(&message_id_U16, &header[2], 2);
+
+ // dependant on endian-ness:
+ // U32 temp = (255 << 24) | (255 << 16) | header[2];
+
+ // independant of endian-ness:
+ message_id_U16 = ntohs(message_id_U16);
+ num = 0xFFFF0000 | message_id_U16;
+ }
+ else // bogus packet received (too short)
+ {
+ LL_WARNS() << "Packet with unusable length received (too short): "
+ << buffer_size << LL_ENDL;
+ return(false);
+ }
+
+ LLMessageTemplate* temp = get_ptr_in_map(mMessageNumbers,num);
+ if (temp)
+ {
+ *msg_template = temp;
+ }
+ else
+ {
+ // MAINT-7482 - make viewer more tolerant of unknown messages.
+ LL_WARNS_ONCE() << "Message #" << std::hex << num << std::dec
+ << " received but not registered!" << LL_ENDL;
+ //gMessageSystem->callExceptionFunc(MX_UNREGISTERED_MESSAGE);
+ return(false);
+ }
+
+ return(true);
+}
+
+void LLTemplateMessageReader::logRanOffEndOfPacket( const LLHost& host, const S32 where, const S32 wanted )
+{
+ // we've run off the end of the packet!
+ LL_WARNS() << "Ran off end of packet " << mCurrentRMessageTemplate->mName
+// << " with id " << mCurrentRecvPacketID
+ << " from " << host
+ << " trying to read " << wanted
+ << " bytes at position " << where
+ << " going past packet end at " << mReceiveSize
+ << LL_ENDL;
+ if(gMessageSystem->mVerboseLog)
+ {
+ LL_INFOS() << "MSG: -> " << host << "\tREAD PAST END:\t"
+// << mCurrentRecvPacketID << " "
+ << getMessageName() << LL_ENDL;
+ }
+ gMessageSystem->callExceptionFunc(MX_RAN_OFF_END_OF_PACKET);
+}
+
+static LLTrace::BlockTimerStatHandle FTM_PROCESS_MESSAGES("Process Messages");
+
+// decode a given message
+bool LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender )
+{
+ LL_RECORD_BLOCK_TIME(FTM_PROCESS_MESSAGES);
+
+ llassert( mReceiveSize >= 0 );
+ llassert( mCurrentRMessageTemplate);
+ llassert( !mCurrentRMessageData );
+ delete mCurrentRMessageData; // just to make sure
+
+ // The offset tells us how may bytes to skip after the end of the
+ // message name.
+ U8 offset = buffer[PHL_OFFSET];
+ S32 decode_pos = LL_PACKET_ID_SIZE + (S32)(mCurrentRMessageTemplate->mFrequency) + offset;
+
+ // create base working data set
+ mCurrentRMessageData = new LLMsgData(mCurrentRMessageTemplate->mName);
+
+ // loop through the template building the data structure as we go
+ LLMessageTemplate::message_block_map_t::const_iterator iter;
+ for(iter = mCurrentRMessageTemplate->mMemberBlocks.begin();
+ iter != mCurrentRMessageTemplate->mMemberBlocks.end();
+ ++iter)
+ {
+ LLMessageBlock* mbci = *iter;
+ U8 repeat_number;
+ S32 i;
+
+ // how many of this block?
+
+ if (mbci->mType == MBT_SINGLE)
+ {
+ // just one
+ repeat_number = 1;
+ }
+ else if (mbci->mType == MBT_MULTIPLE)
+ {
+ // a known number
+ repeat_number = mbci->mNumber;
+ }
+ else if (mbci->mType == MBT_VARIABLE)
+ {
+ // need to read the number from the message
+ // repeat number is a single byte
+ if (decode_pos >= mReceiveSize)
+ {
+ // commented out - hetgrid says that missing variable blocks
+ // at end of message are legal
+ // logRanOffEndOfPacket(sender, decode_pos, 1);
+
+ // default to 0 repeats
+ repeat_number = 0;
+ }
+ else
+ {
+ repeat_number = buffer[decode_pos];
+ decode_pos++;
+ }
+ }
+ else
+ {
+ LL_ERRS() << "Unknown block type" << LL_ENDL;
+ return false;
+ }
+
+ LLMsgBlkData* cur_data_block = NULL;
+
+ // now loop through the block
+ for (i = 0; i < repeat_number; i++)
+ {
+ if (i)
+ {
+ // build new name to prevent collisions
+ // TODO: This should really change to a vector
+ cur_data_block = new LLMsgBlkData(mbci->mName, repeat_number);
+ cur_data_block->mName = mbci->mName + i;
+ }
+ else
+ {
+ cur_data_block = new LLMsgBlkData(mbci->mName, repeat_number);
+ }
+
+ // add the block to the message
+ mCurrentRMessageData->addBlock(cur_data_block);
+
+ // now read the variables
+ for (LLMessageBlock::message_variable_map_t::const_iterator iter =
+ mbci->mMemberVariables.begin();
+ iter != mbci->mMemberVariables.end(); iter++)
+ {
+ const LLMessageVariable& mvci = **iter;
+
+ // ok, build out the variables
+ // add variable block
+ cur_data_block->addVariable(mvci.getName(), mvci.getType());
+
+ // what type of variable?
+ if (mvci.getType() == MVT_VARIABLE)
+ {
+ // variable, get the number of bytes to read from the template
+ S32 data_size = mvci.getSize();
+ U8 tsizeb = 0;
+ U16 tsizeh = 0;
+ U32 tsize = 0;
+
+ if ((decode_pos + data_size) > mReceiveSize)
+ {
+ logRanOffEndOfPacket(sender, decode_pos, data_size);
+
+ // default to 0 length variable blocks
+ tsize = 0;
+ }
+ else
+ {
+ switch(data_size)
+ {
+ case 1:
+ htolememcpy(&tsizeb, &buffer[decode_pos], MVT_U8, 1);
+ tsize = tsizeb;
+ break;
+ case 2:
+ htolememcpy(&tsizeh, &buffer[decode_pos], MVT_U16, 2);
+ tsize = tsizeh;
+ break;
+ case 4:
+ htolememcpy(&tsize, &buffer[decode_pos], MVT_U32, 4);
+ break;
+ default:
+ LL_ERRS() << "Attempting to read variable field with unknown size of " << data_size << LL_ENDL;
+ break;
+ }
+ }
+ decode_pos += data_size;
+
+ cur_data_block->addData(mvci.getName(), &buffer[decode_pos], tsize, mvci.getType());
+ decode_pos += tsize;
+ }
+ else
+ {
+ // fixed!
+ // so, copy data pointer and set data size to fixed size
+ if ((decode_pos + mvci.getSize()) > mReceiveSize)
+ {
+ logRanOffEndOfPacket(sender, decode_pos, mvci.getSize());
+
+ // default to 0s.
+ U32 size = mvci.getSize();
+ std::vector<U8> data(size, 0);
+ cur_data_block->addData(mvci.getName(), &(data[0]),
+ size, mvci.getType());
+ }
+ else
+ {
+ cur_data_block->addData(mvci.getName(),
+ &buffer[decode_pos],
+ mvci.getSize(),
+ mvci.getType());
+ }
+ decode_pos += mvci.getSize();
+ }
+ }
+ }
+ }
+
+ if (mCurrentRMessageData->mMemberBlocks.empty()
+ && !mCurrentRMessageTemplate->mMemberBlocks.empty())
+ {
+ LL_DEBUGS() << "Empty message '" << mCurrentRMessageTemplate->mName << "' (no blocks)" << LL_ENDL;
+ return false;
+ }
+
+ {
+ static LLTimer decode_timer;
+
+ if(LLMessageReader::getTimeDecodes() || gMessageSystem->getTimingCallback())
+ {
+ decode_timer.reset();
+ }
+
+ if( !mCurrentRMessageTemplate->callHandlerFunc(gMessageSystem) )
+ {
+ LL_WARNS() << "Message from " << sender << " with no handler function received: " << mCurrentRMessageTemplate->mName << LL_ENDL;
+ }
+
+ if(LLMessageReader::getTimeDecodes() || gMessageSystem->getTimingCallback())
+ {
+ F32 decode_time = decode_timer.getElapsedTimeF32();
+
+ if (gMessageSystem->getTimingCallback())
+ {
+ (gMessageSystem->getTimingCallback())(mCurrentRMessageTemplate->mName,
+ decode_time,
+ gMessageSystem->getTimingCallbackData());
+ }
+
+ if (LLMessageReader::getTimeDecodes())
+ {
+ mCurrentRMessageTemplate->mDecodeTimeThisFrame += decode_time;
+
+ mCurrentRMessageTemplate->mTotalDecoded++;
+ mCurrentRMessageTemplate->mTotalDecodeTime += decode_time;
+
+ if( mCurrentRMessageTemplate->mMaxDecodeTimePerMsg < decode_time )
+ {
+ mCurrentRMessageTemplate->mMaxDecodeTimePerMsg = decode_time;
+ }
+
+
+ if(decode_time > LLMessageReader::getTimeDecodesSpamThreshold())
+ {
+ LL_DEBUGS() << "--------- Message " << mCurrentRMessageTemplate->mName << " decode took " << decode_time << " seconds. (" <<
+ mCurrentRMessageTemplate->mMaxDecodeTimePerMsg << " max, " <<
+ (mCurrentRMessageTemplate->mTotalDecodeTime / mCurrentRMessageTemplate->mTotalDecoded) << " avg)" << LL_ENDL;
+ }
+ }
+ }
+ }
+ return true;
+}
+
+bool LLTemplateMessageReader::validateMessage(const U8* buffer,
+ S32 buffer_size,
+ const LLHost& sender,
+ bool trusted)
+{
+ mReceiveSize = buffer_size;
+ bool valid = decodeTemplate(buffer, buffer_size, &mCurrentRMessageTemplate );
+ if(valid)
+ {
+ mCurrentRMessageTemplate->mReceiveCount++;
+ //LL_DEBUGS() << "MessageRecvd:"
+ // << mCurrentRMessageTemplate->mName
+ // << " from " << sender << LL_ENDL;
+ }
+
+ if (valid && isBanned(trusted))
+ {
+ LL_WARNS("Messaging") << "LLMessageSystem::checkMessages "
+ << "received banned message "
+ << getMessageName()
+ << " from "
+ << ((trusted) ? "trusted " : "untrusted ")
+ << sender << LL_ENDL;
+ valid = false;
+ }
+
+ if(valid && isUdpBanned())
+ {
+ LL_WARNS() << "Received UDP black listed message "
+ << getMessageName()
+ << " from " << sender << LL_ENDL;
+ valid = false;
+ }
+ return valid;
+}
+
+bool LLTemplateMessageReader::readMessage(const U8* buffer,
+ const LLHost& sender)
+{
+ return decodeData(buffer, sender);
+}
+
+//virtual
+const char* LLTemplateMessageReader::getMessageName() const
+{
+ if (!mCurrentRMessageTemplate)
+ {
+ // no message currently being read
+ return "";
+ }
+ return mCurrentRMessageTemplate->mName;
+}
+
+//virtual
+bool LLTemplateMessageReader::isTrusted() const
+{
+ return mCurrentRMessageTemplate->getTrust() == MT_TRUST;
+}
+
+bool LLTemplateMessageReader::isBanned(bool trustedSource) const
+{
+ return mCurrentRMessageTemplate->isBanned(trustedSource);
+}
+
+bool LLTemplateMessageReader::isUdpBanned() const
+{
+ return mCurrentRMessageTemplate->isUdpBanned();
+}
+
+//virtual
+void LLTemplateMessageReader::copyToBuilder(LLMessageBuilder& builder) const
+{
+ if(NULL == mCurrentRMessageTemplate)
+ {
+ return;
+ }
+ builder.copyFromMessageData(*mCurrentRMessageData);
+}