lltemplatemessagebuilder.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:24k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file lltemplatemessagebuilder.cpp
  3.  * @brief LLTemplateMessageBuilder class implementation.
  4.  *
  5.  * $LicenseInfo:firstyear=2007&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2007-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "linden_common.h"
  33. #include "lltemplatemessagebuilder.h"
  34. #include "llmessagetemplate.h"
  35. #include "llquaternion.h"
  36. #include "u64.h"
  37. #include "v3dmath.h"
  38. #include "v3math.h"
  39. #include "v4math.h"
  40. LLTemplateMessageBuilder::LLTemplateMessageBuilder(const message_template_name_map_t& name_template_map) :
  41. mCurrentSMessageData(NULL),
  42. mCurrentSMessageTemplate(NULL),
  43. mCurrentSDataBlock(NULL),
  44. mCurrentSMessageName(NULL),
  45. mCurrentSBlockName(NULL),
  46. mbSBuilt(FALSE),
  47. mbSClear(TRUE),
  48. mCurrentSendTotal(0),
  49. mMessageTemplates(name_template_map)
  50. {
  51. }
  52. //virtual
  53. LLTemplateMessageBuilder::~LLTemplateMessageBuilder()
  54. {
  55. delete mCurrentSMessageData;
  56. mCurrentSMessageData = NULL;
  57. }
  58. // virtual
  59. void LLTemplateMessageBuilder::newMessage(const char *name)
  60. {
  61. mbSBuilt = FALSE;
  62. mbSClear = FALSE;
  63. mCurrentSendTotal = 0;
  64. delete mCurrentSMessageData;
  65. mCurrentSMessageData = NULL;
  66. char* namep = (char*)name; 
  67. if (mMessageTemplates.count(namep) > 0)
  68. {
  69. mCurrentSMessageTemplate = mMessageTemplates.find(name)->second;
  70. mCurrentSMessageData = new LLMsgData(namep);
  71. mCurrentSMessageName = namep;
  72. mCurrentSDataBlock = NULL;
  73. mCurrentSBlockName = NULL;
  74. // add at one of each block
  75. const LLMessageTemplate* msg_template = mMessageTemplates.find(name)->second;
  76. if (msg_template->getDeprecation() != MD_NOTDEPRECATED)
  77. {
  78. llwarns << "Sending deprecated message " << namep << llendl;
  79. }
  80. LLMessageTemplate::message_block_map_t::const_iterator iter;
  81. for(iter = msg_template->mMemberBlocks.begin();
  82. iter != msg_template->mMemberBlocks.end();
  83. ++iter)
  84. {
  85. LLMessageBlock* ci = *iter;
  86. LLMsgBlkData* tblockp = new LLMsgBlkData(ci->mName, 0);
  87. mCurrentSMessageData->addBlock(tblockp);
  88. }
  89. }
  90. else
  91. {
  92. llerrs << "newMessage - Message " << name << " not registered" << llendl;
  93. }
  94. }
  95. // virtual
  96. void LLTemplateMessageBuilder::clearMessage()
  97. {
  98. mbSBuilt = FALSE;
  99. mbSClear = TRUE;
  100. mCurrentSendTotal = 0;
  101. mCurrentSMessageTemplate = NULL;
  102. delete mCurrentSMessageData;
  103. mCurrentSMessageData = NULL;
  104. mCurrentSMessageName = NULL;
  105. mCurrentSDataBlock = NULL;
  106. mCurrentSBlockName = NULL;
  107. }
  108. // virtual
  109. void LLTemplateMessageBuilder::nextBlock(const char* blockname)
  110. {
  111. char *bnamep = (char *)blockname; 
  112. if (!mCurrentSMessageTemplate)
  113. {
  114. llerrs << "newMessage not called prior to setBlock" << llendl;
  115. return;
  116. }
  117. // now, does this block exist?
  118. const LLMessageBlock* template_data = mCurrentSMessageTemplate->getBlock(bnamep);
  119. if (!template_data)
  120. {
  121. llerrs << "LLTemplateMessageBuilder::nextBlock " << bnamep
  122. << " not a block in " << mCurrentSMessageTemplate->mName << llendl;
  123. return;
  124. }
  125. // ok, have we already set this block?
  126. LLMsgBlkData* block_data = mCurrentSMessageData->mMemberBlocks[bnamep];
  127. if (block_data->mBlockNumber == 0)
  128. {
  129. // nope! set this as the current block
  130. block_data->mBlockNumber = 1;
  131. mCurrentSDataBlock = block_data;
  132. mCurrentSBlockName = bnamep;
  133. // add placeholders for each of the variables
  134. for (LLMessageBlock::message_variable_map_t::const_iterator iter = template_data->mMemberVariables.begin();
  135.  iter != template_data->mMemberVariables.end(); iter++)
  136. {
  137. LLMessageVariable& ci = **iter;
  138. mCurrentSDataBlock->addVariable(ci.getName(), ci.getType());
  139. }
  140. return;
  141. }
  142. else
  143. {
  144. // already have this block. . . 
  145. // are we supposed to have a new one?
  146. // if the block is type MBT_SINGLE this is bad!
  147. if (template_data->mType == MBT_SINGLE)
  148. {
  149. llerrs << "LLTemplateMessageBuilder::nextBlock called multiple times"
  150. << " for " << bnamep << " but is type MBT_SINGLE" << llendl;
  151. return;
  152. }
  153. // if the block is type MBT_MULTIPLE then we need a known number, 
  154. // make sure that we're not exceeding it
  155. if (  (template_data->mType == MBT_MULTIPLE)
  156. &&(mCurrentSDataBlock->mBlockNumber == template_data->mNumber))
  157. {
  158. llerrs << "LLTemplateMessageBuilder::nextBlock called "
  159. << mCurrentSDataBlock->mBlockNumber << " times for " << bnamep
  160. << " exceeding " << template_data->mNumber
  161. << " specified in type MBT_MULTIPLE." << llendl;
  162. return;
  163. }
  164. // ok, we can make a new one
  165. // modify the name to avoid name collision by adding number to end
  166. S32  count = block_data->mBlockNumber;
  167. // incrememt base name's count
  168. block_data->mBlockNumber++;
  169. if (block_data->mBlockNumber > MAX_BLOCKS)
  170. {
  171. llerrs << "Trying to pack too many blocks into MBT_VARIABLE type "
  172.    << "(limited to " << MAX_BLOCKS << ")" << llendl;
  173. }
  174. // create new name
  175. // Nota Bene: if things are working correctly, 
  176. // mCurrentMessageData->mMemberBlocks[blockname]->mBlockNumber == 
  177. // mCurrentDataBlock->mBlockNumber + 1
  178. char *nbnamep = bnamep + count;
  179. mCurrentSDataBlock = new LLMsgBlkData(bnamep, count);
  180. mCurrentSDataBlock->mName = nbnamep;
  181. mCurrentSMessageData->mMemberBlocks[nbnamep] = mCurrentSDataBlock;
  182. // add placeholders for each of the variables
  183. for (LLMessageBlock::message_variable_map_t::const_iterator
  184.  iter = template_data->mMemberVariables.begin(),
  185.  end = template_data->mMemberVariables.end();
  186.  iter != end; iter++)
  187. {
  188. LLMessageVariable& ci = **iter;
  189. mCurrentSDataBlock->addVariable(ci.getName(), ci.getType());
  190. }
  191. return;
  192. }
  193. }
  194. // TODO: Remove this horror...
  195. BOOL LLTemplateMessageBuilder::removeLastBlock()
  196. {
  197. if (mCurrentSBlockName)
  198. {
  199. if (  (mCurrentSMessageData)
  200. &&(mCurrentSMessageTemplate))
  201. {
  202. if (mCurrentSMessageData->mMemberBlocks[mCurrentSBlockName]->mBlockNumber >= 1)
  203. {
  204. // At least one block for the current block name.
  205. // Store the current block name for future reference.
  206. char *block_name = mCurrentSBlockName;
  207. // Decrement the sent total by the size of the
  208. // data in the message block that we're currently building.
  209. const LLMessageBlock* template_data = mCurrentSMessageTemplate->getBlock(mCurrentSBlockName);
  210. for (LLMessageBlock::message_variable_map_t::const_iterator iter = template_data->mMemberVariables.begin();
  211.  iter != template_data->mMemberVariables.end(); iter++)
  212. {
  213. LLMessageVariable& ci = **iter;
  214. mCurrentSendTotal -= ci.getSize();
  215. }
  216. // Now we want to find the block that we're blowing away.
  217. // Get the number of blocks.
  218. LLMsgBlkData* block_data = mCurrentSMessageData->mMemberBlocks[block_name];
  219. S32 num_blocks = block_data->mBlockNumber;
  220. // Use the same (suspect?) algorithm that's used to generate
  221. // the names in the nextBlock method to find it.
  222. char *block_getting_whacked = block_name + num_blocks - 1;
  223. LLMsgBlkData* whacked_data = mCurrentSMessageData->mMemberBlocks[block_getting_whacked];
  224. delete whacked_data;
  225. mCurrentSMessageData->mMemberBlocks.erase(block_getting_whacked);
  226. if (num_blocks <= 1)
  227. {
  228. // we just blew away the last one, so return FALSE
  229. llwarns << "not blowing away the only block of message "
  230. << mCurrentSMessageName
  231. << ". Block: " << block_name
  232. << ". Number: " << num_blocks
  233. << llendl;
  234. return FALSE;
  235. }
  236. else
  237. {
  238. // Decrement the counter.
  239. block_data->mBlockNumber--;
  240. return TRUE;
  241. }
  242. }
  243. }
  244. }
  245. return FALSE;
  246. }
  247. // add data to variable in current block
  248. void LLTemplateMessageBuilder::addData(const char *varname, const void *data, EMsgVariableType type, S32 size)
  249. {
  250. char *vnamep = (char *)varname; 
  251. // do we have a current message?
  252. if (!mCurrentSMessageTemplate)
  253. {
  254. llerrs << "newMessage not called prior to addData" << llendl;
  255. return;
  256. }
  257. // do we have a current block?
  258. if (!mCurrentSDataBlock)
  259. {
  260. llerrs << "setBlock not called prior to addData" << llendl;
  261. return;
  262. }
  263. // kewl, add the data if it exists
  264. const LLMessageVariable* var_data = mCurrentSMessageTemplate->getBlock(mCurrentSBlockName)->getVariable(vnamep);
  265. if (!var_data || !var_data->getName())
  266. {
  267. llerrs << vnamep << " not a variable in block " << mCurrentSBlockName << " of " << mCurrentSMessageTemplate->mName << llendl;
  268. return;
  269. }
  270. // ok, it seems ok. . . are we the correct size?
  271. if (var_data->getType() == MVT_VARIABLE)
  272. {
  273. // Variable 1 can only store 255 bytes, make sure our data is smaller
  274. if ((var_data->getSize() == 1) &&
  275. (size > 255))
  276. {
  277. llwarns << "Field " << varname << " is a Variable 1 but program "
  278.        << "attempted to stuff more than 255 bytes in "
  279.        << "(" << size << ").  Clamping size and truncating data." << llendl;
  280. size = 255;
  281. char *truncate = (char *)data;
  282. truncate[255] = 0;
  283. }
  284. // no correct size for MVT_VARIABLE, instead we need to tell how many bytes the size will be encoded as
  285. mCurrentSDataBlock->addData(vnamep, data, size, type, var_data->getSize());
  286. mCurrentSendTotal += size;
  287. }
  288. else
  289. {
  290. if (size != var_data->getSize())
  291. {
  292. llerrs << varname << " is type MVT_FIXED but request size " << size << " doesn't match template size "
  293.    << var_data->getSize() << llendl;
  294. return;
  295. }
  296. // alright, smash it in
  297. mCurrentSDataBlock->addData(vnamep, data, size, type);
  298. mCurrentSendTotal += size;
  299. }
  300. }
  301. // add data to variable in current block - fails if variable isn't MVT_FIXED
  302. void LLTemplateMessageBuilder::addData(const char *varname, const void *data, EMsgVariableType type)
  303. {
  304. char *vnamep = (char *)varname; 
  305. // do we have a current message?
  306. if (!mCurrentSMessageTemplate)
  307. {
  308. llerrs << "newMessage not called prior to addData" << llendl;
  309. return;
  310. }
  311. // do we have a current block?
  312. if (!mCurrentSDataBlock)
  313. {
  314. llerrs << "setBlock not called prior to addData" << llendl;
  315. return;
  316. }
  317. // kewl, add the data if it exists
  318. const LLMessageVariable* var_data = mCurrentSMessageTemplate->getBlock(mCurrentSBlockName)->getVariable(vnamep);
  319. if (!var_data->getName())
  320. {
  321. llerrs << vnamep << " not a variable in block " << mCurrentSBlockName << " of " << mCurrentSMessageTemplate->mName << llendl;
  322. return;
  323. }
  324. // ok, it seems ok. . . are we MVT_VARIABLE?
  325. if (var_data->getType() == MVT_VARIABLE)
  326. {
  327. // nope
  328. llerrs << vnamep << " is type MVT_VARIABLE. Call using addData(name, data, size)" << llendl;
  329. return;
  330. }
  331. else
  332. {
  333. mCurrentSDataBlock->addData(vnamep, data, var_data->getSize(), type);
  334. mCurrentSendTotal += var_data->getSize();
  335. }
  336. }
  337. void LLTemplateMessageBuilder::addBinaryData(const char *varname, 
  338. const void *data, S32 size)
  339. {
  340. addData(varname, data, MVT_FIXED, size);
  341. }
  342. void LLTemplateMessageBuilder::addS8(const char *varname, S8 s)
  343. {
  344. addData(varname, &s, MVT_S8, sizeof(s));
  345. }
  346. void LLTemplateMessageBuilder::addU8(const char *varname, U8 u)
  347. {
  348. addData(varname, &u, MVT_U8, sizeof(u));
  349. }
  350. void LLTemplateMessageBuilder::addS16(const char *varname, S16 i)
  351. {
  352. addData(varname, &i, MVT_S16, sizeof(i));
  353. }
  354. void LLTemplateMessageBuilder::addU16(const char *varname, U16 i)
  355. {
  356. addData(varname, &i, MVT_U16, sizeof(i));
  357. }
  358. void LLTemplateMessageBuilder::addF32(const char *varname, F32 f)
  359. {
  360. addData(varname, &f, MVT_F32, sizeof(f));
  361. }
  362. void LLTemplateMessageBuilder::addS32(const char *varname, S32 s)
  363. {
  364. addData(varname, &s, MVT_S32, sizeof(s));
  365. }
  366. void LLTemplateMessageBuilder::addU32(const char *varname, U32 u)
  367. {
  368. addData(varname, &u, MVT_U32, sizeof(u));
  369. }
  370. void LLTemplateMessageBuilder::addU64(const char *varname, U64 lu)
  371. {
  372. addData(varname, &lu, MVT_U64, sizeof(lu));
  373. }
  374. void LLTemplateMessageBuilder::addF64(const char *varname, F64 d)
  375. {
  376. addData(varname, &d, MVT_F64, sizeof(d));
  377. }
  378. void LLTemplateMessageBuilder::addIPAddr(const char *varname, U32 u)
  379. {
  380. addData(varname, &u, MVT_IP_ADDR, sizeof(u));
  381. }
  382. void LLTemplateMessageBuilder::addIPPort(const char *varname, U16 u)
  383. {
  384. u = htons(u);
  385. addData(varname, &u, MVT_IP_PORT, sizeof(u));
  386. }
  387. void LLTemplateMessageBuilder::addBOOL(const char* varname, BOOL b)
  388. {
  389. // Can't just cast a BOOL (actually a U32) to a U8.
  390. // In some cases the low order bits will be zero.
  391. U8 temp = (b != 0);
  392. addData(varname, &temp, MVT_BOOL, sizeof(temp));
  393. }
  394. void LLTemplateMessageBuilder::addString(const char* varname, const char* s)
  395. {
  396. if (s)
  397. addData( varname, (void *)s, MVT_VARIABLE, (S32)strlen(s) + 1);  /* Flawfinder: ignore */  
  398. else
  399. addData( varname, NULL, MVT_VARIABLE, 0); 
  400. }
  401. void LLTemplateMessageBuilder::addString(const char* varname, const std::string& s)
  402. {
  403. if (s.size())
  404. addData( varname, (void *)s.c_str(), MVT_VARIABLE, (S32)(s.size()) + 1); 
  405. else
  406. addData( varname, NULL, MVT_VARIABLE, 0); 
  407. }
  408. void LLTemplateMessageBuilder::addVector3(const char *varname, const LLVector3& vec)
  409. {
  410. addData(varname, vec.mV, MVT_LLVector3, sizeof(vec.mV));
  411. }
  412. void LLTemplateMessageBuilder::addVector4(const char *varname, const LLVector4& vec)
  413. {
  414. addData(varname, vec.mV, MVT_LLVector4, sizeof(vec.mV));
  415. }
  416. void LLTemplateMessageBuilder::addVector3d(const char *varname, const LLVector3d& vec)
  417. {
  418. addData(varname, vec.mdV, MVT_LLVector3d, sizeof(vec.mdV));
  419. }
  420. void LLTemplateMessageBuilder::addQuat(const char *varname, const LLQuaternion& quat)
  421. {
  422. addData(varname, quat.packToVector3().mV, MVT_LLQuaternion, sizeof(LLVector3));
  423. }
  424. void LLTemplateMessageBuilder::addUUID(const char *varname, const LLUUID& uuid)
  425. {
  426. addData(varname, uuid.mData, MVT_LLUUID, sizeof(uuid.mData));
  427. }
  428. static S32 zero_code(U8 **data, U32 *data_size)
  429. {
  430. // Encoded send buffer needs to be slightly larger since the zero
  431. // coding can potentially increase the size of the send data.
  432. static U8 encodedSendBuffer[2 * MAX_BUFFER_SIZE];
  433. S32 count = *data_size;
  434. S32 net_gain = 0;
  435. U8 num_zeroes = 0;
  436. U8 *inptr = (U8 *)*data;
  437. U8 *outptr = (U8 *)encodedSendBuffer;
  438. // skip the packet id field
  439. for (U32 ii = 0; ii < LL_PACKET_ID_SIZE ; ++ii)
  440. {
  441. count--;
  442. *outptr++ = *inptr++;
  443. }
  444. // build encoded packet, keeping track of net size gain
  445. // sequential zero bytes are encoded as 0 [U8 count] 
  446. // with 0 0 [count] representing wrap (>256 zeroes)
  447. while (count--)
  448. {
  449. if (!(*inptr))   // in a zero count
  450. {
  451. if (num_zeroes)
  452. {
  453. if (++num_zeroes > 254)
  454. {
  455. *outptr++ = num_zeroes;
  456. num_zeroes = 0;
  457. }
  458. net_gain--;   // subseqent zeroes save one
  459. }
  460. else
  461. {
  462. *outptr++ = 0;
  463. net_gain++;  // starting a zero count adds one
  464. num_zeroes = 1;
  465. }
  466. inptr++;
  467. }
  468. else
  469. {
  470. if (num_zeroes)
  471. {
  472. *outptr++ = num_zeroes;
  473. num_zeroes = 0;
  474. }
  475. *outptr++ = *inptr++;
  476. }
  477. }
  478. if (num_zeroes)
  479. {
  480. *outptr++ = num_zeroes;
  481. }
  482. if (net_gain < 0)
  483. {
  484. // TODO: babbage: reinstate stat collecting...
  485. //mCompressedPacketsOut++;
  486. //mUncompressedBytesOut += *data_size;
  487. *data = encodedSendBuffer;
  488. *data_size += net_gain;
  489. encodedSendBuffer[0] |= LL_ZERO_CODE_FLAG;          // set the head bit to indicate zero coding
  490. //mCompressedBytesOut += *data_size;
  491. }
  492. //mTotalBytesOut += *data_size;
  493. return(net_gain);
  494. }
  495. void LLTemplateMessageBuilder::compressMessage(U8*& buf_ptr, U32& buffer_length)
  496. {
  497. if(ME_ZEROCODED == mCurrentSMessageTemplate->getEncoding())
  498. {
  499. zero_code(&buf_ptr, &buffer_length);
  500. }
  501. }
  502. BOOL LLTemplateMessageBuilder::isMessageFull(const char* blockname) const
  503. {
  504. if(mCurrentSendTotal > MTUBYTES)
  505. {
  506. return TRUE;
  507. }
  508. if(!blockname)
  509. {
  510. return FALSE;
  511. }
  512. char* bnamep = (char*)blockname;
  513. S32 max;
  514. const LLMessageBlock* template_data = mCurrentSMessageTemplate->getBlock(bnamep);
  515. switch(template_data->mType)
  516. {
  517. case MBT_SINGLE:
  518. max = 1;
  519. break;
  520. case MBT_MULTIPLE:
  521. max = template_data->mNumber;
  522. break;
  523. case MBT_VARIABLE:
  524. default:
  525. max = MAX_BLOCKS;
  526. break;
  527. }
  528. if(mCurrentSMessageData->mMemberBlocks[bnamep]->mBlockNumber >= max)
  529. {
  530. return TRUE;
  531. }
  532. return FALSE;
  533. }
  534. static S32 buildBlock(U8* buffer, S32 buffer_size, const LLMessageBlock* template_data, LLMsgData* message_data)
  535. {
  536. S32 result = 0;
  537. LLMsgData::msg_blk_data_map_t::const_iterator block_iter = message_data->mMemberBlocks.find(template_data->mName);
  538. const LLMsgBlkData* mbci = block_iter->second;
  539. // ok, if this is the first block of a repeating pack, set
  540. // block_count and, if it's type MBT_VARIABLE encode a byte
  541. // for how many there are
  542. S32 block_count = mbci->mBlockNumber;
  543. if (template_data->mType == MBT_VARIABLE)
  544. {
  545. // remember that mBlockNumber is a S32
  546. U8 temp_block_number = (U8)mbci->mBlockNumber;
  547. if ((S32)(result + sizeof(U8)) < MAX_BUFFER_SIZE)
  548. {
  549. memcpy(&buffer[result], &temp_block_number, sizeof(U8));
  550. result += sizeof(U8);
  551. }
  552. else
  553. {
  554. // Just reporting error is likely not enough. Need
  555. // to check how to abort or error out gracefully
  556. // from this function. XXXTBD
  557. llerrs << "buildBlock failed. Message excedding "
  558. << "sendBuffersize." << llendl;
  559. }
  560. }
  561. else if (template_data->mType == MBT_MULTIPLE)
  562. {
  563. if (block_count != template_data->mNumber)
  564. {
  565. // nope!  need to fill it in all the way!
  566. llerrs << "Block " << mbci->mName
  567. << " is type MBT_MULTIPLE but only has data for "
  568. << block_count << " out of its "
  569. << template_data->mNumber << " blocks" << llendl;
  570. }
  571. }
  572. while(block_count > 0)
  573. {
  574. // now loop through the variables
  575. for (LLMsgBlkData::msg_var_data_map_t::const_iterator iter = mbci->mMemberVarData.begin();
  576.  iter != mbci->mMemberVarData.end(); iter++)
  577. {
  578. const LLMsgVarData& mvci = *iter;
  579. if (mvci.getSize() == -1)
  580. {
  581. // oops, this variable wasn't ever set!
  582. llerrs << "The variable " << mvci.getName() << " in block "
  583. << mbci->mName << " of message "
  584. << template_data->mName
  585. << " wasn't set prior to buildMessage call" << llendl;
  586. }
  587. else
  588. {
  589. S32 data_size = mvci.getDataSize();
  590. if(data_size > 0)
  591. {
  592. // The type is MVT_VARIABLE, which means that we
  593. // need to encode a size argument. Otherwise,
  594. // there is no need.
  595. S32 size = mvci.getSize();
  596. U8 sizeb;
  597. U16 sizeh;
  598. switch(data_size)
  599. {
  600. case 1:
  601. sizeb = size;
  602. htonmemcpy(&buffer[result], &sizeb, MVT_U8, 1);
  603. break;
  604. case 2:
  605. sizeh = size;
  606. htonmemcpy(&buffer[result], &sizeh, MVT_U16, 2);
  607. break;
  608. case 4:
  609. htonmemcpy(&buffer[result], &size, MVT_S32, 4);
  610. break;
  611. default:
  612. llerrs << "Attempting to build variable field with unknown size of " << size << llendl;
  613. break;
  614. }
  615. result += mvci.getDataSize();
  616. }
  617. // if there is any data to pack, pack it
  618. if((mvci.getData() != NULL) && mvci.getSize())
  619. {
  620. if(result + mvci.getSize() < buffer_size)
  621. {
  622.     memcpy(
  623. &buffer[result],
  624. mvci.getData(),
  625. mvci.getSize());
  626.     result += mvci.getSize();
  627. }
  628. else
  629. {
  630.     // Just reporting error is likely not
  631.     // enough. Need to check how to abort or error
  632.     // out gracefully from this function. XXXTBD
  633. llerrs << "buildBlock failed. "
  634. << "Attempted to pack "
  635. << (result + mvci.getSize())
  636. << " bytes into a buffer with size "
  637. << buffer_size << "." << llendl;
  638. }
  639. }
  640. }
  641. }
  642. --block_count;
  643. if (block_iter != message_data->mMemberBlocks.end())
  644. {
  645. ++block_iter;
  646. if (block_iter != message_data->mMemberBlocks.end())
  647. {
  648. mbci = block_iter->second;
  649. }
  650. }
  651. }
  652. return result;
  653. }
  654. // make sure that all the desired data is in place and then copy the data into MAX_BUFFER_SIZEd buffer
  655. U32 LLTemplateMessageBuilder::buildMessage(
  656. U8* buffer,
  657. U32 buffer_size,
  658. U8 offset_to_data)
  659. {
  660. // basic algorithm is to loop through the various pieces, building
  661. // size and offset info if we encounter a -1 for mSize at any
  662. // point that variable wasn't given data
  663. // do we have a current message?
  664. if (!mCurrentSMessageTemplate)
  665. {
  666. llerrs << "newMessage not called prior to buildMessage" << llendl;
  667. return 0;
  668. }
  669. // leave room for flags, packet sequence #, and data offset
  670. // information.
  671. buffer[PHL_OFFSET] = offset_to_data;
  672. U32 result = LL_PACKET_ID_SIZE;
  673. // encode message number and adjust total_offset
  674. if (mCurrentSMessageTemplate->mFrequency == MFT_HIGH)
  675. {
  676. // old, endian-dependant way
  677. // memcpy(&buffer[result], &mCurrentMessageTemplate->mMessageNumber, sizeof(U8));
  678. // new, independant way
  679. buffer[result] = (U8)mCurrentSMessageTemplate->mMessageNumber;
  680. result += sizeof(U8);
  681. }
  682. else if (mCurrentSMessageTemplate->mFrequency == MFT_MEDIUM)
  683. {
  684. U8 temp = 255;
  685. memcpy(&buffer[result], &temp, sizeof(U8));  /*Flawfinder: ignore*/
  686. result += sizeof(U8);
  687. // mask off unsightly bits
  688. temp = mCurrentSMessageTemplate->mMessageNumber & 255;
  689. memcpy(&buffer[result], &temp, sizeof(U8));  /*Flawfinder: ignore*/
  690. result += sizeof(U8);
  691. }
  692. else if (mCurrentSMessageTemplate->mFrequency == MFT_LOW)
  693. {
  694. U8 temp = 255;
  695. U16  message_num;
  696. memcpy(&buffer[result], &temp, sizeof(U8));  /*Flawfinder: ignore*/
  697. result += sizeof(U8);
  698. memcpy(&buffer[result], &temp, sizeof(U8));  /*Flawfinder: ignore*/
  699. result += sizeof(U8);
  700. // mask off unsightly bits
  701. message_num = mCurrentSMessageTemplate->mMessageNumber & 0xFFFF;
  702.     // convert to network byte order
  703. message_num = htons(message_num);
  704. memcpy(&buffer[result], &message_num, sizeof(U16)); /*Flawfinder: ignore*/
  705. result += sizeof(U16);
  706. }
  707. else
  708. {
  709. llerrs << "unexpected message frequency in buildMessage" << llendl;
  710. return 0;
  711. }
  712. // fast forward through the offset and build the message
  713. result += offset_to_data;
  714. for(LLMessageTemplate::message_block_map_t::const_iterator
  715. iter = mCurrentSMessageTemplate->mMemberBlocks.begin(),
  716. end = mCurrentSMessageTemplate->mMemberBlocks.end();
  717.  iter != end;
  718. ++iter)
  719. {
  720. result += buildBlock(buffer + result, buffer_size - result, *iter, mCurrentSMessageData);
  721. }
  722. mbSBuilt = TRUE;
  723. return result;
  724. }
  725. void LLTemplateMessageBuilder::copyFromMessageData(const LLMsgData& data)
  726. {
  727. // copy the blocks
  728. // counting variables used to encode multiple block info
  729. S32 block_count = 0;
  730.     char *block_name = NULL;
  731. // loop through msg blocks to loop through variables, totalling up size
  732. // data and filling the new (send) message
  733. LLMsgData::msg_blk_data_map_t::const_iterator iter = 
  734. data.mMemberBlocks.begin();
  735. LLMsgData::msg_blk_data_map_t::const_iterator end = 
  736. data.mMemberBlocks.end();
  737. for(; iter != end; ++iter)
  738. {
  739. const LLMsgBlkData* mbci = iter->second;
  740. if(!mbci) continue;
  741. // do we need to encode a block code?
  742. if (block_count == 0)
  743. {
  744. block_count = mbci->mBlockNumber;
  745. block_name = (char *)mbci->mName;
  746. }
  747. // counting down mutliple blocks
  748. block_count--;
  749. nextBlock(block_name);
  750. // now loop through the variables
  751. LLMsgBlkData::msg_var_data_map_t::const_iterator dit = mbci->mMemberVarData.begin();
  752. LLMsgBlkData::msg_var_data_map_t::const_iterator dend = mbci->mMemberVarData.end();
  753. for(; dit != dend; ++dit)
  754. {
  755. const LLMsgVarData& mvci = *dit;
  756. addData(mvci.getName(), mvci.getData(), mvci.getType(), mvci.getSize());
  757. }
  758. }
  759. }
  760. //virtual 
  761. void LLTemplateMessageBuilder::copyFromLLSD(const LLSD&)
  762. {
  763. // TODO
  764. }
  765. //virtual
  766. void LLTemplateMessageBuilder::setBuilt(BOOL b) { mbSBuilt = b; }
  767. //virtual 
  768. BOOL LLTemplateMessageBuilder::isBuilt() const {return mbSBuilt;}
  769. //virtual 
  770. BOOL LLTemplateMessageBuilder::isClear() const {return mbSClear;}
  771. //virtual 
  772. S32 LLTemplateMessageBuilder::getMessageSize() {return mCurrentSendTotal;}
  773. //virtual 
  774. const char* LLTemplateMessageBuilder::getMessageName() const 
  775. {
  776. return mCurrentSMessageName;
  777. }