lltemplatemessagebuilder.cpp

Go to the documentation of this file.
00001 
00032 #include "linden_common.h"
00033 
00034 #include "lltemplatemessagebuilder.h"
00035 
00036 #include "llmessagetemplate.h"
00037 #include "llquaternion.h"
00038 #include "u64.h"
00039 #include "v3dmath.h"
00040 #include "v3math.h"
00041 #include "v4math.h"
00042 
00043 LLTemplateMessageBuilder::LLTemplateMessageBuilder(message_template_name_map_t& name_template_map) :
00044         mCurrentSMessageData(NULL),
00045         mCurrentSMessageTemplate(NULL),
00046         mCurrentSDataBlock(NULL),
00047         mCurrentSMessageName(NULL),
00048         mCurrentSBlockName(NULL),
00049         mbSBuilt(FALSE),
00050         mbSClear(TRUE),
00051         mCurrentSendTotal(0),
00052         mMessageTemplates(name_template_map)
00053 {
00054 }
00055 
00056 //virtual
00057 LLTemplateMessageBuilder::~LLTemplateMessageBuilder()
00058 {
00059         delete mCurrentSMessageData;
00060         mCurrentSMessageData = NULL;
00061 }
00062 
00063 
00064 // virtual
00065 void LLTemplateMessageBuilder::newMessage(const char *name)
00066 {
00067         mbSBuilt = FALSE;
00068         mbSClear = FALSE;
00069 
00070         mCurrentSendTotal = 0;
00071 
00072         delete mCurrentSMessageData;
00073         mCurrentSMessageData = NULL;
00074 
00075         char* namep = (char*)name; 
00076         if (mMessageTemplates.count(namep) > 0)
00077         {
00078                 mCurrentSMessageTemplate = mMessageTemplates[namep];
00079                 mCurrentSMessageData = new LLMsgData(namep);
00080                 mCurrentSMessageName = namep;
00081                 mCurrentSDataBlock = NULL;
00082                 mCurrentSBlockName = NULL;
00083 
00084                 // add at one of each block
00085                 const LLMessageTemplate* msg_template = mMessageTemplates[namep];
00086 
00087                 if (msg_template->getDeprecation() != MD_NOTDEPRECATED)
00088                 {
00089                         llwarns << "Sending deprecated message " << namep << llendl;
00090                 }
00091                 
00092                 LLMessageTemplate::message_block_map_t::const_iterator iter;
00093                 for(iter = msg_template->mMemberBlocks.begin();
00094                         iter != msg_template->mMemberBlocks.end();
00095                         ++iter)
00096                 {
00097                         LLMessageBlock* ci = *iter;
00098                         LLMsgBlkData* tblockp = new LLMsgBlkData(ci->mName, 0);
00099                         mCurrentSMessageData->addBlock(tblockp);
00100                 }
00101         }
00102         else
00103         {
00104                 llerrs << "newMessage - Message " << name << " not registered" << llendl;
00105         }
00106 }
00107 
00108 // virtual
00109 void LLTemplateMessageBuilder::clearMessage()
00110 {
00111         mbSBuilt = FALSE;
00112         mbSClear = TRUE;
00113 
00114         mCurrentSendTotal = 0;
00115 
00116         mCurrentSMessageTemplate = NULL;
00117 
00118         delete mCurrentSMessageData;
00119         mCurrentSMessageData = NULL;
00120 
00121         mCurrentSMessageName = NULL;
00122         mCurrentSDataBlock = NULL;
00123         mCurrentSBlockName = NULL;
00124 }
00125 
00126 // virtual
00127 void LLTemplateMessageBuilder::nextBlock(const char* blockname)
00128 {
00129         char *bnamep = (char *)blockname; 
00130 
00131         if (!mCurrentSMessageTemplate)
00132         {
00133                 llerrs << "newMessage not called prior to setBlock" << llendl;
00134                 return;
00135         }
00136 
00137         // now, does this block exist?
00138         const LLMessageBlock* template_data = mCurrentSMessageTemplate->getBlock(bnamep);
00139         if (!template_data)
00140         {
00141                 llerrs << "LLTemplateMessageBuilder::nextBlock " << bnamep
00142                         << " not a block in " << mCurrentSMessageTemplate->mName << llendl;
00143                 return;
00144         }
00145         
00146         // ok, have we already set this block?
00147         LLMsgBlkData* block_data = mCurrentSMessageData->mMemberBlocks[bnamep];
00148         if (block_data->mBlockNumber == 0)
00149         {
00150                 // nope! set this as the current block
00151                 block_data->mBlockNumber = 1;
00152                 mCurrentSDataBlock = block_data;
00153                 mCurrentSBlockName = bnamep;
00154 
00155                 // add placeholders for each of the variables
00156                 for (LLMessageBlock::message_variable_map_t::const_iterator iter = template_data->mMemberVariables.begin();
00157                          iter != template_data->mMemberVariables.end(); iter++)
00158                 {
00159                         LLMessageVariable& ci = **iter;
00160                         mCurrentSDataBlock->addVariable(ci.getName(), ci.getType());
00161                 }
00162                 return;
00163         }
00164         else
00165         {
00166                 // already have this block. . . 
00167                 // are we supposed to have a new one?
00168 
00169                 // if the block is type MBT_SINGLE this is bad!
00170                 if (template_data->mType == MBT_SINGLE)
00171                 {
00172                         llerrs << "LLTemplateMessageBuilder::nextBlock called multiple times"
00173                                 << " for " << bnamep << " but is type MBT_SINGLE" << llendl;
00174                         return;
00175                 }
00176 
00177 
00178                 // if the block is type MBT_MULTIPLE then we need a known number, 
00179                 // make sure that we're not exceeding it
00180                 if (  (template_data->mType == MBT_MULTIPLE)
00181                         &&(mCurrentSDataBlock->mBlockNumber == template_data->mNumber))
00182                 {
00183                         llerrs << "LLTemplateMessageBuilder::nextBlock called "
00184                                 << mCurrentSDataBlock->mBlockNumber << " times for " << bnamep
00185                                 << " exceeding " << template_data->mNumber
00186                                 << " specified in type MBT_MULTIPLE." << llendl;
00187                         return;
00188                 }
00189 
00190                 // ok, we can make a new one
00191                 // modify the name to avoid name collision by adding number to end
00192                 S32  count = block_data->mBlockNumber;
00193 
00194                 // incrememt base name's count
00195                 block_data->mBlockNumber++;
00196 
00197                 if (block_data->mBlockNumber > MAX_BLOCKS)
00198                 {
00199                         llerrs << "Trying to pack too many blocks into MBT_VARIABLE type "
00200                                    << "(limited to " << MAX_BLOCKS << ")" << llendl;
00201                 }
00202 
00203                 // create new name
00204                 // Nota Bene: if things are working correctly, 
00205                 // mCurrentMessageData->mMemberBlocks[blockname]->mBlockNumber == 
00206                 // mCurrentDataBlock->mBlockNumber + 1
00207 
00208                 char *nbnamep = bnamep + count;
00209         
00210                 mCurrentSDataBlock = new LLMsgBlkData(bnamep, count);
00211                 mCurrentSDataBlock->mName = nbnamep;
00212                 mCurrentSMessageData->mMemberBlocks[nbnamep] = mCurrentSDataBlock;
00213 
00214                 // add placeholders for each of the variables
00215                 for (LLMessageBlock::message_variable_map_t::const_iterator
00216                                  iter = template_data->mMemberVariables.begin(),
00217                                  end = template_data->mMemberVariables.end();
00218                          iter != end; iter++)
00219                 {
00220                         LLMessageVariable& ci = **iter;
00221                         mCurrentSDataBlock->addVariable(ci.getName(), ci.getType());
00222                 }
00223                 return;
00224         }
00225 }
00226 
00227 // TODO: Remove this horror...
00228 BOOL LLTemplateMessageBuilder::removeLastBlock()
00229 {
00230         if (mCurrentSBlockName)
00231         {
00232                 if (  (mCurrentSMessageData)
00233                         &&(mCurrentSMessageTemplate))
00234                 {
00235                         if (mCurrentSMessageData->mMemberBlocks[mCurrentSBlockName]->mBlockNumber >= 1)
00236                         {
00237                                 // At least one block for the current block name.
00238 
00239                                 // Store the current block name for future reference.
00240                                 char *block_name = mCurrentSBlockName;
00241 
00242                                 // Decrement the sent total by the size of the
00243                                 // data in the message block that we're currently building.
00244 
00245                                 const LLMessageBlock* template_data = mCurrentSMessageTemplate->getBlock(mCurrentSBlockName);
00246                                 
00247                                 for (LLMessageBlock::message_variable_map_t::const_iterator iter = template_data->mMemberVariables.begin();
00248                                          iter != template_data->mMemberVariables.end(); iter++)
00249                                 {
00250                                         LLMessageVariable& ci = **iter;
00251                                         mCurrentSendTotal -= ci.getSize();
00252                                 }
00253 
00254 
00255                                 // Now we want to find the block that we're blowing away.
00256 
00257                                 // Get the number of blocks.
00258                                 LLMsgBlkData* block_data = mCurrentSMessageData->mMemberBlocks[block_name];
00259                                 S32 num_blocks = block_data->mBlockNumber;
00260 
00261                                 // Use the same (suspect?) algorithm that's used to generate
00262                                 // the names in the nextBlock method to find it.
00263                                 char *block_getting_whacked = block_name + num_blocks - 1;
00264                                 LLMsgBlkData* whacked_data = mCurrentSMessageData->mMemberBlocks[block_getting_whacked];
00265                                 delete whacked_data;
00266                                 mCurrentSMessageData->mMemberBlocks.erase(block_getting_whacked);
00267 
00268                                 if (num_blocks <= 1)
00269                                 {
00270                                         // we just blew away the last one, so return FALSE
00271                                         llwarns << "not blowing away the only block of message "
00272                                                         << mCurrentSMessageName
00273                                                         << ". Block: " << block_name
00274                                                         << ". Number: " << num_blocks
00275                                                         << llendl;
00276                                         return FALSE;
00277                                 }
00278                                 else
00279                                 {
00280                                         // Decrement the counter.
00281                                         block_data->mBlockNumber--;
00282                                         return TRUE;
00283                                 }
00284                         }
00285                 }
00286         }
00287         return FALSE;
00288 }
00289 
00290 // add data to variable in current block
00291 void LLTemplateMessageBuilder::addData(const char *varname, const void *data, EMsgVariableType type, S32 size)
00292 {
00293         char *vnamep = (char *)varname; 
00294 
00295         // do we have a current message?
00296         if (!mCurrentSMessageTemplate)
00297         {
00298                 llerrs << "newMessage not called prior to addData" << llendl;
00299                 return;
00300         }
00301 
00302         // do we have a current block?
00303         if (!mCurrentSDataBlock)
00304         {
00305                 llerrs << "setBlock not called prior to addData" << llendl;
00306                 return;
00307         }
00308 
00309         // kewl, add the data if it exists
00310         const LLMessageVariable* var_data = mCurrentSMessageTemplate->getBlock(mCurrentSBlockName)->getVariable(vnamep);
00311         if (!var_data || !var_data->getName())
00312         {
00313                 llerrs << vnamep << " not a variable in block " << mCurrentSBlockName << " of " << mCurrentSMessageTemplate->mName << llendl;
00314                 return;
00315         }
00316 
00317         // ok, it seems ok. . . are we the correct size?
00318         if (var_data->getType() == MVT_VARIABLE)
00319         {
00320                 // Variable 1 can only store 255 bytes, make sure our data is smaller
00321                 if ((var_data->getSize() == 1) &&
00322                         (size > 255))
00323                 {
00324                         llwarns << "Field " << varname << " is a Variable 1 but program "
00325                                << "attempted to stuff more than 255 bytes in "
00326                                << "(" << size << ").  Clamping size and truncating data." << llendl;
00327                         size = 255;
00328                         char *truncate = (char *)data;
00329                         truncate[255] = 0;
00330                 }
00331 
00332                 // no correct size for MVT_VARIABLE, instead we need to tell how many bytes the size will be encoded as
00333                 mCurrentSDataBlock->addData(vnamep, data, size, type, var_data->getSize());
00334                 mCurrentSendTotal += size;
00335         }
00336         else
00337         {
00338                 if (size != var_data->getSize())
00339                 {
00340                         llerrs << varname << " is type MVT_FIXED but request size " << size << " doesn't match template size "
00341                                    << var_data->getSize() << llendl;
00342                         return;
00343                 }
00344                 // alright, smash it in
00345                 mCurrentSDataBlock->addData(vnamep, data, size, type);
00346                 mCurrentSendTotal += size;
00347         }
00348 }
00349 
00350 // add data to variable in current block - fails if variable isn't MVT_FIXED
00351 void LLTemplateMessageBuilder::addData(const char *varname, const void *data, EMsgVariableType type)
00352 {
00353         char *vnamep = (char *)varname; 
00354 
00355         // do we have a current message?
00356         if (!mCurrentSMessageTemplate)
00357         {
00358                 llerrs << "newMessage not called prior to addData" << llendl;
00359                 return;
00360         }
00361 
00362         // do we have a current block?
00363         if (!mCurrentSDataBlock)
00364         {
00365                 llerrs << "setBlock not called prior to addData" << llendl;
00366                 return;
00367         }
00368 
00369         // kewl, add the data if it exists
00370         const LLMessageVariable* var_data = mCurrentSMessageTemplate->getBlock(mCurrentSBlockName)->getVariable(vnamep);
00371         if (!var_data->getName())
00372         {
00373                 llerrs << vnamep << " not a variable in block " << mCurrentSBlockName << " of " << mCurrentSMessageTemplate->mName << llendl;
00374                 return;
00375         }
00376 
00377         // ok, it seems ok. . . are we MVT_VARIABLE?
00378         if (var_data->getType() == MVT_VARIABLE)
00379         {
00380                 // nope
00381                 llerrs << vnamep << " is type MVT_VARIABLE. Call using addData(name, data, size)" << llendl;
00382                 return;
00383         }
00384         else
00385         {
00386                 mCurrentSDataBlock->addData(vnamep, data, var_data->getSize(), type);
00387                 mCurrentSendTotal += var_data->getSize();
00388         }
00389 }
00390 
00391 void LLTemplateMessageBuilder::addBinaryData(const char *varname, 
00392                                                                                         const void *data, S32 size)
00393 {
00394         addData(varname, data, MVT_FIXED, size);
00395 }
00396 
00397 void LLTemplateMessageBuilder::addS8(const char *varname, S8 s)
00398 {
00399         addData(varname, &s, MVT_S8, sizeof(s));
00400 }
00401 
00402 void LLTemplateMessageBuilder::addU8(const char *varname, U8 u)
00403 {
00404         addData(varname, &u, MVT_U8, sizeof(u));
00405 }
00406 
00407 void LLTemplateMessageBuilder::addS16(const char *varname, S16 i)
00408 {
00409         addData(varname, &i, MVT_S16, sizeof(i));
00410 }
00411 
00412 void LLTemplateMessageBuilder::addU16(const char *varname, U16 i)
00413 {
00414         addData(varname, &i, MVT_U16, sizeof(i));
00415 }
00416 
00417 void LLTemplateMessageBuilder::addF32(const char *varname, F32 f)
00418 {
00419         addData(varname, &f, MVT_F32, sizeof(f));
00420 }
00421 
00422 void LLTemplateMessageBuilder::addS32(const char *varname, S32 s)
00423 {
00424         addData(varname, &s, MVT_S32, sizeof(s));
00425 }
00426 
00427 void LLTemplateMessageBuilder::addU32(const char *varname, U32 u)
00428 {
00429         addData(varname, &u, MVT_U32, sizeof(u));
00430 }
00431 
00432 void LLTemplateMessageBuilder::addU64(const char *varname, U64 lu)
00433 {
00434         addData(varname, &lu, MVT_U64, sizeof(lu));
00435 }
00436 
00437 void LLTemplateMessageBuilder::addF64(const char *varname, F64 d)
00438 {
00439         addData(varname, &d, MVT_F64, sizeof(d));
00440 }
00441 
00442 void LLTemplateMessageBuilder::addIPAddr(const char *varname, U32 u)
00443 {
00444         addData(varname, &u, MVT_IP_ADDR, sizeof(u));
00445 }
00446 
00447 void LLTemplateMessageBuilder::addIPPort(const char *varname, U16 u)
00448 {
00449         u = htons(u);
00450         addData(varname, &u, MVT_IP_PORT, sizeof(u));
00451 }
00452 
00453 void LLTemplateMessageBuilder::addBOOL(const char* varname, BOOL b)
00454 {
00455         // Can't just cast a BOOL (actually a U32) to a U8.
00456         // In some cases the low order bits will be zero.
00457         U8 temp = (b != 0);
00458         addData(varname, &temp, MVT_BOOL, sizeof(temp));
00459 }
00460 
00461 void LLTemplateMessageBuilder::addString(const char* varname, const char* s)
00462 {
00463         if (s)
00464                 addData( varname, (void *)s, MVT_VARIABLE, (S32)strlen(s) + 1);  /* Flawfinder: ignore */  
00465         else
00466                 addData( varname, NULL, MVT_VARIABLE, 0); 
00467 }
00468 
00469 void LLTemplateMessageBuilder::addString(const char* varname, const std::string& s)
00470 {
00471         if (s.size())
00472                 addData( varname, (void *)s.c_str(), MVT_VARIABLE, (S32)(s.size()) + 1); 
00473         else
00474                 addData( varname, NULL, MVT_VARIABLE, 0); 
00475 }
00476 
00477 void LLTemplateMessageBuilder::addVector3(const char *varname, const LLVector3& vec)
00478 {
00479         addData(varname, vec.mV, MVT_LLVector3, sizeof(vec.mV));
00480 }
00481 
00482 void LLTemplateMessageBuilder::addVector4(const char *varname, const LLVector4& vec)
00483 {
00484         addData(varname, vec.mV, MVT_LLVector4, sizeof(vec.mV));
00485 }
00486 
00487 void LLTemplateMessageBuilder::addVector3d(const char *varname, const LLVector3d& vec)
00488 {
00489         addData(varname, vec.mdV, MVT_LLVector3d, sizeof(vec.mdV));
00490 }
00491 
00492 void LLTemplateMessageBuilder::addQuat(const char *varname, const LLQuaternion& quat)
00493 {
00494         addData(varname, quat.packToVector3().mV, MVT_LLQuaternion, sizeof(LLVector3));
00495 }
00496 
00497 void LLTemplateMessageBuilder::addUUID(const char *varname, const LLUUID& uuid)
00498 {
00499         addData(varname, uuid.mData, MVT_LLUUID, sizeof(uuid.mData));
00500 }
00501 
00502 static S32 zero_code(U8 **data, U32 *data_size)
00503 {
00504         // Encoded send buffer needs to be slightly larger since the zero
00505         // coding can potentially increase the size of the send data.
00506         static U8 encodedSendBuffer[2 * MAX_BUFFER_SIZE];
00507 
00508         S32 count = *data_size;
00509         
00510         S32 net_gain = 0;
00511         U8 num_zeroes = 0;
00512         
00513         U8 *inptr = (U8 *)*data;
00514         U8 *outptr = (U8 *)encodedSendBuffer;
00515 
00516 // skip the packet id field
00517 
00518         for (U32 ii = 0; ii < LL_PACKET_ID_SIZE ; ++ii)
00519         {
00520                 count--;
00521                 *outptr++ = *inptr++;
00522         }
00523 
00524 // build encoded packet, keeping track of net size gain
00525 
00526 // sequential zero bytes are encoded as 0 [U8 count] 
00527 // with 0 0 [count] representing wrap (>256 zeroes)
00528 
00529         while (count--)
00530         {
00531                 if (!(*inptr))   // in a zero count
00532                 {
00533                         if (num_zeroes)
00534                         {
00535                                 if (++num_zeroes > 254)
00536                                 {
00537                                         *outptr++ = num_zeroes;
00538                                         num_zeroes = 0;
00539                                 }
00540                                 net_gain--;   // subseqent zeroes save one
00541                         }
00542                         else
00543                         {
00544                                 *outptr++ = 0;
00545                                 net_gain++;  // starting a zero count adds one
00546                                 num_zeroes = 1;
00547                         }
00548                         inptr++;
00549                 }
00550                 else
00551                 {
00552                         if (num_zeroes)
00553                         {
00554                                 *outptr++ = num_zeroes;
00555                                 num_zeroes = 0;
00556                         }
00557                         *outptr++ = *inptr++;
00558                 }
00559         }
00560 
00561         if (num_zeroes)
00562         {
00563                 *outptr++ = num_zeroes;
00564         }
00565 
00566         if (net_gain < 0)
00567         {
00568                 // TODO: babbage: reinstate stat collecting...
00569                 //mCompressedPacketsOut++;
00570                 //mUncompressedBytesOut += *data_size;
00571 
00572                 *data = encodedSendBuffer;
00573                 *data_size += net_gain;
00574                 encodedSendBuffer[0] |= LL_ZERO_CODE_FLAG;          // set the head bit to indicate zero coding
00575 
00576                 //mCompressedBytesOut += *data_size;
00577 
00578         }
00579         //mTotalBytesOut += *data_size;
00580 
00581         return(net_gain);
00582 }
00583 
00584 void LLTemplateMessageBuilder::compressMessage(U8*& buf_ptr, U32& buffer_length)
00585 {
00586         if(ME_ZEROCODED == mCurrentSMessageTemplate->getEncoding())
00587         {
00588                 zero_code(&buf_ptr, &buffer_length);
00589         }
00590 }
00591 
00592 BOOL LLTemplateMessageBuilder::isMessageFull(const char* blockname) const
00593 {
00594         if(mCurrentSendTotal > MTUBYTES)
00595         {
00596                 return TRUE;
00597         }
00598         if(!blockname)
00599         {
00600                 return FALSE;
00601         }
00602         char* bnamep = (char*)blockname;
00603         S32 max;
00604 
00605         const LLMessageBlock* template_data = mCurrentSMessageTemplate->getBlock(bnamep);
00606         
00607         switch(template_data->mType)
00608         {
00609         case MBT_SINGLE:
00610                 max = 1;
00611                 break;
00612         case MBT_MULTIPLE:
00613                 max = template_data->mNumber;
00614                 break;
00615         case MBT_VARIABLE:
00616         default:
00617                 max = MAX_BLOCKS;
00618                 break;
00619         }
00620         if(mCurrentSMessageData->mMemberBlocks[bnamep]->mBlockNumber >= max)
00621         {
00622                 return TRUE;
00623         }
00624         return FALSE;
00625 }
00626 
00627 static S32 buildBlock(U8* buffer, S32 buffer_size, const LLMessageBlock* template_data, LLMsgData* message_data)
00628 {
00629         S32 result = 0;
00630         LLMsgData::msg_blk_data_map_t::const_iterator block_iter = message_data->mMemberBlocks.find(template_data->mName);
00631         const LLMsgBlkData* mbci = block_iter->second;
00632                 
00633         // ok, if this is the first block of a repeating pack, set
00634         // block_count and, if it's type MBT_VARIABLE encode a byte
00635         // for how many there are
00636         S32 block_count = mbci->mBlockNumber;
00637         if (template_data->mType == MBT_VARIABLE)
00638         {
00639                 // remember that mBlockNumber is a S32
00640                 U8 temp_block_number = (U8)mbci->mBlockNumber;
00641                 if ((S32)(result + sizeof(U8)) < MAX_BUFFER_SIZE)
00642                 {
00643                         memcpy(&buffer[result], &temp_block_number, sizeof(U8));
00644                         result += sizeof(U8);
00645                 }
00646                 else
00647                 {
00648                         // Just reporting error is likely not enough. Need
00649                         // to check how to abort or error out gracefully
00650                         // from this function. XXXTBD
00651                         llerrs << "buildBlock failed. Message excedding "
00652                                         << "sendBuffersize." << llendl;
00653                 }
00654         }
00655         else if (template_data->mType == MBT_MULTIPLE)
00656         {
00657                 if (block_count != template_data->mNumber)
00658                 {
00659                         // nope!  need to fill it in all the way!
00660                         llerrs << "Block " << mbci->mName
00661                                 << " is type MBT_MULTIPLE but only has data for "
00662                                 << block_count << " out of its "
00663                                 << template_data->mNumber << " blocks" << llendl;
00664                 }
00665         }
00666 
00667         while(block_count > 0)
00668         {
00669                 // now loop through the variables
00670                 for (LLMsgBlkData::msg_var_data_map_t::const_iterator iter = mbci->mMemberVarData.begin();
00671                          iter != mbci->mMemberVarData.end(); iter++)
00672                 {
00673                         const LLMsgVarData& mvci = *iter;
00674                         if (mvci.getSize() == -1)
00675                         {
00676                                 // oops, this variable wasn't ever set!
00677                                 llerrs << "The variable " << mvci.getName() << " in block "
00678                                         << mbci->mName << " of message "
00679                                         << template_data->mName
00680                                         << " wasn't set prior to buildMessage call" << llendl;
00681                         }
00682                         else
00683                         {
00684                                 S32 data_size = mvci.getDataSize();
00685                                 if(data_size > 0)
00686                                 {
00687                                         // The type is MVT_VARIABLE, which means that we
00688                                         // need to encode a size argument. Otherwise,
00689                                         // there is no need.
00690                                         S32 size = mvci.getSize();
00691                                         U8 sizeb;
00692                                         U16 sizeh;
00693                                         switch(data_size)
00694                                         {
00695                                         case 1:
00696                                                 sizeb = size;
00697                                                 htonmemcpy(&buffer[result], &sizeb, MVT_U8, 1);
00698                                                 break;
00699                                         case 2:
00700                                                 sizeh = size;
00701                                                 htonmemcpy(&buffer[result], &sizeh, MVT_U16, 2);
00702                                                 break;
00703                                         case 4:
00704                                                 htonmemcpy(&buffer[result], &size, MVT_S32, 4);
00705                                                 break;
00706                                         default:
00707                                                 llerrs << "Attempting to build variable field with unknown size of " << size << llendl;
00708                                                 break;
00709                                         }
00710                                         result += mvci.getDataSize();
00711                                 }
00712 
00713                                 // if there is any data to pack, pack it
00714                                 if((mvci.getData() != NULL) && mvci.getSize())
00715                                 {
00716                                         if(result + mvci.getSize() < buffer_size)
00717                                         {
00718                                             memcpy(
00719                                                         &buffer[result],
00720                                                         mvci.getData(),
00721                                                         mvci.getSize());
00722                                             result += mvci.getSize();
00723                                         }
00724                                         else
00725                                         {
00726                                             // Just reporting error is likely not
00727                                             // enough. Need to check how to abort or error
00728                                             // out gracefully from this function. XXXTBD
00729                                                 llerrs << "buildBlock failed. "
00730                                                         << "Attempted to pack "
00731                                                         << result + mvci.getSize()
00732                                                         << " bytes into a buffer with size "
00733                                                         << buffer_size << "." << llendl
00734                                         }                                               
00735                                 }
00736                         }
00737                 }
00738 
00739                 --block_count;
00740                 ++block_iter;
00741                 if (block_iter != message_data->mMemberBlocks.end())
00742                 {
00743                         mbci = block_iter->second;
00744                 }
00745         }
00746 
00747         return result;
00748 }
00749 
00750 
00751 // make sure that all the desired data is in place and then copy the data into MAX_BUFFER_SIZEd buffer
00752 U32 LLTemplateMessageBuilder::buildMessage(
00753         U8* buffer,
00754         U32 buffer_size,
00755         U8 offset_to_data)
00756 {
00757         // basic algorithm is to loop through the various pieces, building
00758         // size and offset info if we encounter a -1 for mSize at any
00759         // point that variable wasn't given data
00760 
00761         // do we have a current message?
00762         if (!mCurrentSMessageTemplate)
00763         {
00764                 llerrs << "newMessage not called prior to buildMessage" << llendl;
00765                 return 0;
00766         }
00767 
00768         // leave room for flags, packet sequence #, and data offset
00769         // information.
00770         buffer[PHL_OFFSET] = offset_to_data;
00771         U32 result = LL_PACKET_ID_SIZE;
00772 
00773         // encode message number and adjust total_offset
00774         if (mCurrentSMessageTemplate->mFrequency == MFT_HIGH)
00775         {
00776 // old, endian-dependant way
00777 //              memcpy(&buffer[result], &mCurrentMessageTemplate->mMessageNumber, sizeof(U8));
00778 
00779 // new, independant way
00780                 buffer[result] = (U8)mCurrentSMessageTemplate->mMessageNumber;
00781                 result += sizeof(U8);
00782         }
00783         else if (mCurrentSMessageTemplate->mFrequency == MFT_MEDIUM)
00784         {
00785                 U8 temp = 255;
00786                 memcpy(&buffer[result], &temp, sizeof(U8));  /*Flawfinder: ignore*/
00787                 result += sizeof(U8);
00788 
00789                 // mask off unsightly bits
00790                 temp = mCurrentSMessageTemplate->mMessageNumber & 255;
00791                 memcpy(&buffer[result], &temp, sizeof(U8));  /*Flawfinder: ignore*/
00792                 result += sizeof(U8);
00793         }
00794         else if (mCurrentSMessageTemplate->mFrequency == MFT_LOW)
00795         {
00796                 U8 temp = 255;
00797                 U16  message_num;
00798                 memcpy(&buffer[result], &temp, sizeof(U8));  /*Flawfinder: ignore*/
00799                 result += sizeof(U8);
00800                 memcpy(&buffer[result], &temp, sizeof(U8));  /*Flawfinder: ignore*/
00801                 result += sizeof(U8);
00802 
00803                 // mask off unsightly bits
00804                 message_num = mCurrentSMessageTemplate->mMessageNumber & 0xFFFF;
00805 
00806             // convert to network byte order
00807                 message_num = htons(message_num);
00808                 memcpy(&buffer[result], &message_num, sizeof(U16)); /*Flawfinder: ignore*/
00809                 result += sizeof(U16);
00810         }
00811         else
00812         {
00813                 llerrs << "unexpected message frequency in buildMessage" << llendl;
00814                 return 0;
00815         }
00816 
00817         // fast forward through the offset and build the message
00818         result += offset_to_data;
00819         for(LLMessageTemplate::message_block_map_t::const_iterator
00820                         iter = mCurrentSMessageTemplate->mMemberBlocks.begin(),
00821                         end = mCurrentSMessageTemplate->mMemberBlocks.end();
00822                  iter != end;
00823                 ++iter)
00824         {
00825                 result += buildBlock(buffer + result, buffer_size - result, *iter, mCurrentSMessageData);
00826         }
00827         mbSBuilt = TRUE;
00828 
00829         return result;
00830 }
00831 
00832 void LLTemplateMessageBuilder::copyFromMessageData(const LLMsgData& data)
00833 {
00834         // copy the blocks
00835         // counting variables used to encode multiple block info
00836         S32 block_count = 0;
00837     char *block_name = NULL;
00838 
00839         // loop through msg blocks to loop through variables, totalling up size
00840         // data and filling the new (send) message
00841         LLMsgData::msg_blk_data_map_t::const_iterator iter = 
00842                 data.mMemberBlocks.begin();
00843         LLMsgData::msg_blk_data_map_t::const_iterator end = 
00844                 data.mMemberBlocks.end();
00845         for(; iter != end; ++iter)
00846         {
00847                 const LLMsgBlkData* mbci = iter->second;
00848                 if(!mbci) continue;
00849 
00850                 // do we need to encode a block code?
00851                 if (block_count == 0)
00852                 {
00853                         block_count = mbci->mBlockNumber;
00854                         block_name = (char *)mbci->mName;
00855                 }
00856 
00857                 // counting down mutliple blocks
00858                 block_count--;
00859 
00860                 nextBlock(block_name);
00861 
00862                 // now loop through the variables
00863                 LLMsgBlkData::msg_var_data_map_t::const_iterator dit = mbci->mMemberVarData.begin();
00864                 LLMsgBlkData::msg_var_data_map_t::const_iterator dend = mbci->mMemberVarData.end();
00865                 
00866                 for(; dit != dend; ++dit)
00867                 {
00868                         const LLMsgVarData& mvci = *dit;
00869                         addData(mvci.getName(), mvci.getData(), mvci.getType(), mvci.getSize());
00870                 }
00871         }
00872 }
00873 
00874 //virtual 
00875 void LLTemplateMessageBuilder::copyFromLLSD(const LLSD&)
00876 {
00877         // TODO
00878 }
00879 
00880 //virtual
00881 void LLTemplateMessageBuilder::setBuilt(BOOL b) { mbSBuilt = b; }
00882 
00883 //virtual 
00884 BOOL LLTemplateMessageBuilder::isBuilt() const {return mbSBuilt;}
00885 
00886 //virtual 
00887 BOOL LLTemplateMessageBuilder::isClear() const {return mbSClear;}
00888 
00889 //virtual 
00890 S32 LLTemplateMessageBuilder::getMessageSize() {return mCurrentSendTotal;}
00891 
00892 //virtual 
00893 const char* LLTemplateMessageBuilder::getMessageName() const 
00894 {
00895         return mCurrentSMessageName;
00896 }

Generated on Thu Jul 1 06:09:15 2010 for Second Life Viewer by  doxygen 1.4.7