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