上面介绍了怎么样构造消息模板,并用它来灵活地生成各种各样需要传送数据的数据结构,现在就来分析一下使用模板怎么样去分析缓冲区里的数据,然后获取消息各个字段数据,这样才可以让别的程序使用起来。
#001 BOOL LLTemplateMessageReader::readMessage(const U8* buffer,
#002
const LLHost&
#003 sender)
#004 {
#005
return decodeData(buffer, sender);
#006 }
在LLMessageSystem::checkMessages函数里调用readMessage函数来解包,而函数readMessage又需要调用函数decodeData把缓冲区buffer里的数据分离出来,供其它的程序使用。下面就是函数decodeData的代码:
#001 // decode a given message
#002 BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender )
#003 {
#004
llassert( mReceiveSize >= 0 );
#005
llassert( mCurrentRMessageTemplate);
#006
llassert( !mCurrentRMessageData );
#007
delete mCurrentRMessageData; // just to make sure
#008
下面的程序跳过包头数据,获取到真实的数据开始位置。
#009
// The offset tells us how may bytes to skip after the end of the
#010
// message name.
#011
U8 offset = buffer[PHL_OFFSET];
#012
S32 decode_pos = LL_PACKET_ID_SIZE + (S32)(mCurrentRMessageTemplate->mFrequency) + offset;
#013
创建一个消息保存当前的数据字段。
#014
// create base working data set
#015
mCurrentRMessageData = new LLMsgData(mCurrentRMessageTemplate->mName);
#016
下面通过消息的模板来获取缓冲区里每个字段的数据。
#017
// loop through the template building the data structure as we go
#018
LLMessageTemplate::message_block_map_t::const_iterator iter;
#019
for(iter = mCurrentRMessageTemplate->mMemberBlocks.begin();
#020
iter != mCurrentRMessageTemplate->mMemberBlocks.end();
#021
++iter)
#022
{
#023
LLMessageBlock* mbci = *iter;
#024
U8 repeat_number;
#025
S32 i;
#026
先根据模板查看有多少块数据。
#027
// how many of this block?
#028
只有一块数据。
#029
if (mbci->mType == MBT_SINGLE)
#030
{
#031
// just one
#032
repeat_number = 1;
#033
}
多块数据。
#034
else if (mbci->mType == MBT_MULTIPLE)
#035
{
#036
// a known number
#037
repeat_number = mbci->mNumber;
#038
}
可变的数据块。
#039
else if (mbci->mType == MBT_VARIABLE)
#040
{
#041
// need to read the number from the message
#042
// repeat number is a single byte
#043
if (decode_pos >= mReceiveSize)
#044
{
#045
logRanOffEndOfPacket(sender, decode_pos, 1);
#046
#047
// default to 0 repeats
#048
repeat_number = 0;
#049
}
#050
else
#051
{
#052
repeat_number = buffer[decode_pos];
#053
decode_pos++;
#054
}
#055
}
没有定义的数据块。
#056
else
#057
{
#058
llerrs << "Unknown block type" << llendl;
#059
return FALSE;
#060
}
#061
#062
LLMsgBlkData* cur_data_block = NULL;
#063
下面开始循环分析数据块。
#064
// now loop through the block
#065
for (i = 0; i < repeat_number; i++)
#066
{
创建数据块结构保存数据。
#067
if (i)
#068
{
#069
// build new name to prevent collisions
#070
// TODO: This should really change to a vector
#071
cur_data_block = new LLMsgBlkData(mbci->mName, repeat_number);
#072
cur_data_block->mName = mbci->mName + i;
#073
}
#074
else
#075
{
#076
cur_data_block = new LLMsgBlkData(mbci->mName, repeat_number);
#077
}
#078
添加数据块到当前消息结构里。
#079
// add the block to the message
#080
mCurrentRMessageData->addBlock(cur_data_block);
#081
开始根据消息模板的定义去分析缓冲区里每个字段。
#082
// now read the variables
#083
for (LLMessageBlock::message_variable_map_t::const_iterator iter =
#084
mbci->mMemberVariables.begin();
#085
iter != mbci->mMemberVariables.end(); iter++)
#086
{
#087
const LLMessageVariable& mvci = **iter;
#088
#089
// ok, build out the variables
#090
// add variable block
#091
cur_data_block->addVariable(mvci.getName(), mvci.getType());
#092
#093
// what type of variable?
#094
if (mvci.getType() == MVT_VARIABLE)
#095
{
#096
// variable, get the number of bytes to read from the template
#097
S32 data_size = mvci.getSize();
#098
U8 tsizeb = 0;
#099
U16 tsizeh = 0;
#100
U32 tsize = 0;
#101
#102
if ((decode_pos + data_size) > mReceiveSize)
#103
{
#104
logRanOffEndOfPacket(sender, decode_pos, data_size);
#105
#106
// default to 0 length variable blocks
#107
tsize = 0;
#108
}
#109
else
#110
{
#111
switch(data_size)
#112
{
#113
case 1:
#114
htonmemcpy(&tsizeb, &buffer[decode_pos], MVT_U8, 1);
#115
tsize = tsizeb;
#116
break;
#117
case 2:
#118
htonmemcpy(&tsizeh, &buffer[decode_pos], MVT_U16, 2);
#119
tsize = tsizeh;
#120
break;
#121
case 4:
#122
htonmemcpy(&tsize, &buffer[decode_pos], MVT_U32, 4);
#123
break;
#124
default:
#125
llerrs << "Attempting to read variable field with unknown size of " <<
#126 data_size << llendl;
#127
break;
#128
}
#129
}
#130
decode_pos += data_size;
#131
#132
cur_data_block->addData(mvci.getName(), &buffer[decode_pos], tsize, mvci.getType());
#133
decode_pos += tsize;
#134
}
#135
else
#136
{
#137
// fixed!
#138
// so, copy data pointer and set data size to fixed size
#139
if ((decode_pos + mvci.getSize()) > mReceiveSize)
#140
{
#141
logRanOffEndOfPacket(sender, decode_pos, mvci.getSize());
#142
#143
// default to 0s.
#144
U32 size = mvci.getSize();
#145
std::vector<U8> data(size);
#146
memset(&(data[0]), 0, size);
#147
cur_data_block->addData(mvci.getName(), &(data[0]),
#148
#149
size, mvci.getType());
#150
}
#151
else
#152
{
#153
cur_data_block->addData(mvci.getName(),
#154
#155
&buffer[decode_pos],
#156
#157
mvci.getSize(),
#158
#159
mvci.getType());
#160
}
#161
decode_pos += mvci.getSize();
#162
}
#163
}
#164
}
#165
}
#166
数据块分析完成,后面就需要判断这个数据包是否分析合法。
#167
if (mCurrentRMessageData->mMemberBlocks.empty()
#168
&& !mCurrentRMessageTemplate->mMemberBlocks.empty())
#169
{
#170
lldebugs << "Empty message '" << mCurrentRMessageTemplate->mName << "' (no blocks)" << llendl;
#171
return FALSE;
#172
}
#173
#174
{
#175
static LLTimer decode_timer;
#176
#177
if(LLMessageReader::getTimeDecodes() || gMessageSystem->getTimingCallback())
#178
{
#179
decode_timer.reset();
#180
}
#181
#182
{
#183
LLFastTimer t(LLFastTimer::FTM_PROCESS_MESSAGES);
#184
if( !mCurrentRMessageTemplate->callHandlerFunc(gMessageSystem) )
#185
{
#186
llwarns << "Message from " << sender << " with no handler function received: " << mCurrentRMessageTemplate-
#187 >mName << llendl;
#188
}
#189
}
#190
#191
if(LLMessageReader::getTimeDecodes() || gMessageSystem->getTimingCallback())
#192
{
#193
F32 decode_time = decode_timer.getElapsedTimeF32();
#194
#195
if (gMessageSystem->getTimingCallback())
#196
{
#197
(gMessageSystem->getTimingCallback())(mCurrentRMessageTemplate->mName,
#198
decode_time,
#199
gMessageSystem->getTimingCallbackData());
#200
}
#201
#202
if (LLMessageReader::getTimeDecodes())
#203
{
#204
mCurrentRMessageTemplate->mDecodeTimeThisFrame += decode_time;
#205
#206
mCurrentRMessageTemplate->mTotalDecoded++;
#207
mCurrentRMessageTemplate->mTotalDecodeTime += decode_time;
#208
#209
if( mCurrentRMessageTemplate->mMaxDecodeTimePerMsg < decode_time )
#210
{
#211
mCurrentRMessageTemplate->mMaxDecodeTimePerMsg = decode_time;
#212
}
#213
#214
#215
if(decode_time > LLMessageReader::getTimeDecodesSpamThreshold())
#216
{
#217
lldebugs << "--------- Message " << mCurrentRMessageTemplate->mName << " decode took " <<
#218 decode_time << " seconds. (" <<
#219
mCurrentRMessageTemplate->mMaxDecodeTimePerMsg << " max, " <<
#220
(mCurrentRMessageTemplate->mTotalDecodeTime / mCurrentRMessageTemplate-
#221 >mTotalDecoded) << " avg)" << llendl;
#222
}
#223
}
#224
}
#225
}
#226
return TRUE;
#227 }
#228