PageRenderTime 123ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/llmessage/lltemplatemessagebuilder.cpp

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