第二人生的源码分析(三十三)消息解包的实现
下面的代码是实现数据包的有效性检验,先调用函数validateMessage来检验接收数据缓冲区里是否有效的数据包,然后调用getMessageName函数来查看是否属于这个环路的数据包,最后判断数据包是否值得信任的或者是否禁止接收的数据。
#159 // UseCircuitCode can be a valid, off-circuit packet.
#160 // But we don't want to acknowledge UseCircuitCode until the circuit is
#161 // available, which is why the acknowledgement test is done above.JC
#162
下面检验数据包是否有效。
#163 valid_packet = mTemplateMessageReader->validateMessage(
#164 buffer,
#165 receive_size,
#166 host);
#167
#168 // UseCircuitCode is allowed in even from an invalid circuit, so that
判断这个数据包是否属于这个环路。
#169 // we can toss circuits around.
#170 if(
#171 valid_packet &&
#172 !cdp &&
#173 (mTemplateMessageReader->getMessageName() !=
#174 _PREHASH_UseCircuitCode))
#175 {
#176 logMsgFromInvalidCircuit( host, recv_reliable );
#177 clearReceiveState();
#178 valid_packet = FALSE;
#179 }
#180
判断数据包是否值得信任。
#181 if(
#182 valid_packet &&
#183 cdp &&
#184 !cdp->getTrusted() &&
#185 mTemplateMessageReader->isTrusted())
#186 {
#187 logTrustedMsgFromUntrustedCircuit( host );
#188 clearReceiveState();
#189
#190 sendDenyTrustedCircuit(host);
#191 valid_packet = FALSE;
#192 }
#193
判断数据包是否属于禁止接收的。
#194 if (
#195 valid_packet &&
#196 mTemplateMessageReader->isBanned(cdp && cdp->getTrusted()))
#197 {
#198 llwarns << "LLMessageSystem::checkMessages "
#199 << "received banned message "
#200 << mTemplateMessageReader->getMessageName()
#201 << " from "
#202 << ((cdp && cdp->getTrusted()) ? "trusted " : "untrusted ")
#203 << host << llendl;
#204 clearReceiveState();
#205 valid_packet = FALSE;
#206 }
#207
这个数据包是有效的,下面就开始读取数据包里面的内容,也就是通过消息模板来解释数据,获取所有的信息。
#208 if( valid_packet )
#209 {
#210 logValidMsg(cdp, host, recv_reliable, recv_resent, (BOOL)(acks>0) );
#211
#212 valid_packet = mTemplateMessageReader->readMessage(buffer, host);
#213 }
#214
#215 // It's possible that the circuit went away, because ANY message can disable the circuit
#216 // (for example, UseCircuit, CloseCircuit, DisableSimulator).Find it again.
#217 cdp = mCircuitInfo.findCircuit(host);
#218
#219 if (valid_packet)
#220 {
#221 // enable this for output of message names
#222 //llinfos << "< /"" << mTemplateMessageReader->getMessageName()
#223 //<< "/"" << llendl;
#224
#328
#329 mPacketsIn++;
#330 mBytesIn += mTrueReceiveSize;
#331
#332 // ACK here for valid packets that we've seen
#333 // for the first time.
下面通过判断这个数据包是否需要可靠性控制,如果需要就加到回应控制里面。
#334 if (cdp && recv_reliable)
#335 {
#336 // Add to the recently received list for duplicate suppression
#337 cdp->mRecentlyReceivedReliablePackets[mCurrentRecvPacketID] = getMessageTimeUsecs();
#338
#339 // Put it onto the list of packets to be acked
#340 cdp->collectRAck(mCurrentRecvPacketID);
#341 mReliablePacketsIn++;
#342 }
#343 }
#344 else
#345 {
#346 if (mbProtected&& (!cdp))
#347 {
#348 llwarns << "Invalid Packet from invalid circuit " << host << llendl;
#349 mOffCircuitPackets++;
#350 }
#351 else
#352 {
#353 mInvalidOnCircuitPackets++;
#354 }
#355 }
#356
#357 // Code for dumping the complete contents of a message
#358 // delete [] zero_unexpanded_buffer;
#359 }
#360 } while (!valid_packet && receive_size > 0);
#361
#362 F64 mt_sec = getMessageTimeSeconds();
#363 // Check to see if we need to print debug info
#364 if ((mt_sec - mCircuitPrintTime) > mCircuitPrintFreq)
#365 {
#366 dumpCircuitInfo();
#367 mCircuitPrintTime = mt_sec;
#368 }
#369
#370 if( !valid_packet )
#371 {
#372 clearReceiveState();
#373 }
#374
#375 return valid_packet;
#376}
消息解包的实现,首先要做的任务,就是判断数据包是否有效,如果无效的数据包就需要丢掉,这样也可以提高网络的安全性,也可以丢掉错误的数据包引起的其它错误。最后使用消息模板实现数据的解释,获取每个字段所表达的意思。
//蔡军生2008/4/10 QQ:9073204 深圳