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

上面介绍了怎么样构造消息模板,并用它来灵活地生成各种各样需要传送数据的数据结构,现在就来分析一下使用模板怎么样去分析缓冲区里的数据,然后获取消息各个字段数据,这样才可以让别的程序使用起来。
#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 来获取这个消息的字段数据,这样就达到第二人生客户端与服务器交流的目的。 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

caimouse

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值