diff options
Diffstat (limited to '')
-rw-r--r-- | linden/indra/llmessage/lltemplatemessagebuilder.cpp | 856 |
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 | |||
12 | LLTemplateMessageBuilder::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 | ||
26 | LLTemplateMessageBuilder::~LLTemplateMessageBuilder() | ||
27 | { | ||
28 | delete mCurrentSMessageData; | ||
29 | mCurrentSMessageData = NULL; | ||
30 | } | ||
31 | |||
32 | |||
33 | // virtual | ||
34 | void 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 | ||
76 | void 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 | ||
94 | void 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... | ||
197 | BOOL 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 | ||
260 | void 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 | ||
320 | void 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 | |||
360 | void LLTemplateMessageBuilder::addBinaryData(const char *varname, | ||
361 | const void *data, S32 size) | ||
362 | { | ||
363 | addData(varname, data, MVT_FIXED, size); | ||
364 | } | ||
365 | |||
366 | void LLTemplateMessageBuilder::addS8(const char *varname, S8 s) | ||
367 | { | ||
368 | addData(varname, &s, MVT_S8, sizeof(s)); | ||
369 | } | ||
370 | |||
371 | void LLTemplateMessageBuilder::addU8(const char *varname, U8 u) | ||
372 | { | ||
373 | addData(varname, &u, MVT_U8, sizeof(u)); | ||
374 | } | ||
375 | |||
376 | void LLTemplateMessageBuilder::addS16(const char *varname, S16 i) | ||
377 | { | ||
378 | addData(varname, &i, MVT_S16, sizeof(i)); | ||
379 | } | ||
380 | |||
381 | void LLTemplateMessageBuilder::addU16(const char *varname, U16 i) | ||
382 | { | ||
383 | addData(varname, &i, MVT_U16, sizeof(i)); | ||
384 | } | ||
385 | |||
386 | void LLTemplateMessageBuilder::addF32(const char *varname, F32 f) | ||
387 | { | ||
388 | addData(varname, &f, MVT_F32, sizeof(f)); | ||
389 | } | ||
390 | |||
391 | void LLTemplateMessageBuilder::addS32(const char *varname, S32 s) | ||
392 | { | ||
393 | addData(varname, &s, MVT_S32, sizeof(s)); | ||
394 | } | ||
395 | |||
396 | void LLTemplateMessageBuilder::addU32(const char *varname, U32 u) | ||
397 | { | ||
398 | addData(varname, &u, MVT_U32, sizeof(u)); | ||
399 | } | ||
400 | |||
401 | void LLTemplateMessageBuilder::addU64(const char *varname, U64 lu) | ||
402 | { | ||
403 | addData(varname, &lu, MVT_U64, sizeof(lu)); | ||
404 | } | ||
405 | |||
406 | void LLTemplateMessageBuilder::addF64(const char *varname, F64 d) | ||
407 | { | ||
408 | addData(varname, &d, MVT_F64, sizeof(d)); | ||
409 | } | ||
410 | |||
411 | void LLTemplateMessageBuilder::addIPAddr(const char *varname, U32 u) | ||
412 | { | ||
413 | addData(varname, &u, MVT_IP_ADDR, sizeof(u)); | ||
414 | } | ||
415 | |||
416 | void LLTemplateMessageBuilder::addIPPort(const char *varname, U16 u) | ||
417 | { | ||
418 | u = htons(u); | ||
419 | addData(varname, &u, MVT_IP_PORT, sizeof(u)); | ||
420 | } | ||
421 | |||
422 | void 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 | |||
430 | void 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 | |||
438 | void 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 | |||
446 | void LLTemplateMessageBuilder::addVector3(const char *varname, const LLVector3& vec) | ||
447 | { | ||
448 | addData(varname, vec.mV, MVT_LLVector3, sizeof(vec.mV)); | ||
449 | } | ||
450 | |||
451 | void LLTemplateMessageBuilder::addVector4(const char *varname, const LLVector4& vec) | ||
452 | { | ||
453 | addData(varname, vec.mV, MVT_LLVector4, sizeof(vec.mV)); | ||
454 | } | ||
455 | |||
456 | void LLTemplateMessageBuilder::addVector3d(const char *varname, const LLVector3d& vec) | ||
457 | { | ||
458 | addData(varname, vec.mdV, MVT_LLVector3d, sizeof(vec.mdV)); | ||
459 | } | ||
460 | |||
461 | void LLTemplateMessageBuilder::addQuat(const char *varname, const LLQuaternion& quat) | ||
462 | { | ||
463 | addData(varname, quat.packToVector3().mV, MVT_LLQuaternion, sizeof(LLVector3)); | ||
464 | } | ||
465 | |||
466 | void LLTemplateMessageBuilder::addUUID(const char *varname, const LLUUID& uuid) | ||
467 | { | ||
468 | addData(varname, uuid.mData, MVT_LLUUID, sizeof(uuid.mData)); | ||
469 | } | ||
470 | |||
471 | static 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 | |||
553 | void 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 | |||
561 | BOOL 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 | ||
598 | U32 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 | |||
792 | void 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 | ||
835 | void LLTemplateMessageBuilder::copyFromLLSD(const LLSD&) | ||
836 | { | ||
837 | // TODO | ||
838 | } | ||
839 | |||
840 | //virtual | ||
841 | void LLTemplateMessageBuilder::setBuilt(BOOL b) { mbSBuilt = b; } | ||
842 | |||
843 | //virtual | ||
844 | BOOL LLTemplateMessageBuilder::isBuilt() const {return mbSBuilt;} | ||
845 | |||
846 | //virtual | ||
847 | BOOL LLTemplateMessageBuilder::isClear() const {return mbSClear;} | ||
848 | |||
849 | //virtual | ||
850 | S32 LLTemplateMessageBuilder::getMessageSize() {return mCurrentSendTotal;} | ||
851 | |||
852 | //virtual | ||
853 | const char* LLTemplateMessageBuilder::getMessageName() const | ||
854 | { | ||
855 | return mCurrentSMessageName; | ||
856 | } | ||