lltemplatemessagebuilder.cpp 23 KB

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