您的位置:首页 > 其它

第二人生的源码分析(三十六)获取消息包里每一个字段

2008-04-14 21:53 441 查看
上面介绍了怎么样构造消息模板,并用它来灵活地生成各种各样需要传送数据的数据结构,现在就来分析一下使用模板怎么样去分析缓冲区里的数据,然后获取消息各个字段数据,这样才可以让别的程序使用起来。
#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

通过消息模板里的定义去解释缓冲区里的数据,然后就把这些字段加入到cur_data_block里,最后其它程序通过函数LLTemplateMessageReader::getData来获取这个消息的字段数据,这样就达到第二人生客户端与服务器交流的目的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: