diff options
Diffstat (limited to 'linden/indra/llmessage/lltemplatemessagereader.cpp')
-rw-r--r-- | linden/indra/llmessage/lltemplatemessagereader.cpp | 750 |
1 files changed, 750 insertions, 0 deletions
diff --git a/linden/indra/llmessage/lltemplatemessagereader.cpp b/linden/indra/llmessage/lltemplatemessagereader.cpp new file mode 100644 index 0000000..892efb8 --- /dev/null +++ b/linden/indra/llmessage/lltemplatemessagereader.cpp | |||
@@ -0,0 +1,750 @@ | |||
1 | #include "lltemplatemessagereader.h" | ||
2 | |||
3 | #include "llfasttimer.h" | ||
4 | #include "llmessagebuilder.h" | ||
5 | #include "llmessagetemplate.h" | ||
6 | #include "llquaternion.h" | ||
7 | #include "message.h" | ||
8 | #include "u64.h" | ||
9 | #include "v3dmath.h" | ||
10 | #include "v3math.h" | ||
11 | #include "v4math.h" | ||
12 | |||
13 | LLTemplateMessageReader::LLTemplateMessageReader(message_template_number_map_t& | ||
14 | number_template_map) : | ||
15 | mReceiveSize(0), | ||
16 | mCurrentRMessageTemplate(NULL), | ||
17 | mCurrentRMessageData(NULL), | ||
18 | mMessageNumbers(number_template_map) | ||
19 | { | ||
20 | } | ||
21 | |||
22 | //virtual | ||
23 | LLTemplateMessageReader::~LLTemplateMessageReader() | ||
24 | { | ||
25 | delete mCurrentRMessageData; | ||
26 | mCurrentRMessageData = NULL; | ||
27 | } | ||
28 | |||
29 | //virtual | ||
30 | void LLTemplateMessageReader::clearMessage() | ||
31 | { | ||
32 | mReceiveSize = -1; | ||
33 | mCurrentRMessageTemplate = NULL; | ||
34 | delete mCurrentRMessageData; | ||
35 | mCurrentRMessageData = NULL; | ||
36 | } | ||
37 | |||
38 | void LLTemplateMessageReader::getData(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum, S32 max_size) | ||
39 | { | ||
40 | // is there a message ready to go? | ||
41 | if (mReceiveSize == -1) | ||
42 | { | ||
43 | llerrs << "No message waiting for decode 2!" << llendl; | ||
44 | return; | ||
45 | } | ||
46 | |||
47 | if (!mCurrentRMessageData) | ||
48 | { | ||
49 | llerrs << "Invalid mCurrentMessageData in getData!" << llendl; | ||
50 | return; | ||
51 | } | ||
52 | |||
53 | char *bnamep = (char *)blockname + blocknum; // this works because it's just a hash. The bnamep is never derefference | ||
54 | char *vnamep = (char *)varname; | ||
55 | |||
56 | LLMsgData::msg_blk_data_map_t::iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep); | ||
57 | |||
58 | if (iter == mCurrentRMessageData->mMemberBlocks.end()) | ||
59 | { | ||
60 | llerrs << "Block " << blockname << " #" << blocknum | ||
61 | << " not in message " << mCurrentRMessageData->mName << llendl; | ||
62 | return; | ||
63 | } | ||
64 | |||
65 | LLMsgBlkData *msg_block_data = iter->second; | ||
66 | LLMsgVarData& vardata = msg_block_data->mMemberVarData[vnamep]; | ||
67 | |||
68 | if (!vardata.getName()) | ||
69 | { | ||
70 | llerrs << "Variable "<< vnamep << " not in message " | ||
71 | << mCurrentRMessageData->mName<< " block " << bnamep << llendl; | ||
72 | return; | ||
73 | } | ||
74 | |||
75 | if (size && size != vardata.getSize()) | ||
76 | { | ||
77 | llerrs << "Msg " << mCurrentRMessageData->mName | ||
78 | << " variable " << vnamep | ||
79 | << " is size " << vardata.getSize() | ||
80 | << " but copying into buffer of size " << size | ||
81 | << llendl; | ||
82 | return; | ||
83 | } | ||
84 | |||
85 | |||
86 | const S32 vardata_size = vardata.getSize(); | ||
87 | if( max_size >= vardata_size ) | ||
88 | { | ||
89 | switch( vardata_size ) | ||
90 | { | ||
91 | case 1: | ||
92 | *((U8*)datap) = *((U8*)vardata.getData()); | ||
93 | break; | ||
94 | case 2: | ||
95 | *((U16*)datap) = *((U16*)vardata.getData()); | ||
96 | break; | ||
97 | case 4: | ||
98 | *((U32*)datap) = *((U32*)vardata.getData()); | ||
99 | break; | ||
100 | case 8: | ||
101 | ((U32*)datap)[0] = ((U32*)vardata.getData())[0]; | ||
102 | ((U32*)datap)[1] = ((U32*)vardata.getData())[1]; | ||
103 | break; | ||
104 | default: | ||
105 | memcpy(datap, vardata.getData(), vardata_size); | ||
106 | break; | ||
107 | } | ||
108 | } | ||
109 | else | ||
110 | { | ||
111 | llwarns << "Msg " << mCurrentRMessageData->mName | ||
112 | << " variable " << vnamep | ||
113 | << " is size " << vardata.getSize() | ||
114 | << " but truncated to max size of " << max_size | ||
115 | << llendl; | ||
116 | |||
117 | memcpy(datap, vardata.getData(), max_size); | ||
118 | } | ||
119 | } | ||
120 | |||
121 | S32 LLTemplateMessageReader::getNumberOfBlocks(const char *blockname) | ||
122 | { | ||
123 | // is there a message ready to go? | ||
124 | if (mReceiveSize == -1) | ||
125 | { | ||
126 | llerrs << "No message waiting for decode 3!" << llendl; | ||
127 | return -1; | ||
128 | } | ||
129 | |||
130 | if (!mCurrentRMessageData) | ||
131 | { | ||
132 | llerrs << "Invalid mCurrentRMessageData in getData!" << llendl; | ||
133 | return -1; | ||
134 | } | ||
135 | |||
136 | char *bnamep = (char *)blockname; | ||
137 | |||
138 | LLMsgData::msg_blk_data_map_t::iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep); | ||
139 | |||
140 | if (iter == mCurrentRMessageData->mMemberBlocks.end()) | ||
141 | { | ||
142 | // sprintf(errmsg, "Block %s not in message %s", bnamep, mCurrentRMessageData->mName); | ||
143 | // llerrs << errmsg << llendl; | ||
144 | // return -1; | ||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | return (iter->second)->mBlockNumber; | ||
149 | } | ||
150 | |||
151 | S32 LLTemplateMessageReader::getSize(const char *blockname, const char *varname) | ||
152 | { | ||
153 | // is there a message ready to go? | ||
154 | if (mReceiveSize == -1) | ||
155 | { | ||
156 | llerrs << "No message waiting for decode 4!" << llendl; | ||
157 | return -1; | ||
158 | } | ||
159 | |||
160 | if (!mCurrentRMessageData) | ||
161 | { | ||
162 | llerrs << "Invalid mCurrentRMessageData in getData!" << llendl; | ||
163 | return -1; | ||
164 | } | ||
165 | |||
166 | char *bnamep = (char *)blockname; | ||
167 | |||
168 | LLMsgData::msg_blk_data_map_t::iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep); | ||
169 | |||
170 | if (iter == mCurrentRMessageData->mMemberBlocks.end()) | ||
171 | { | ||
172 | llerrs << "Block " << bnamep << " not in message " | ||
173 | << mCurrentRMessageData->mName << llendl; | ||
174 | return -1; | ||
175 | } | ||
176 | |||
177 | char *vnamep = (char *)varname; | ||
178 | |||
179 | LLMsgBlkData* msg_data = iter->second; | ||
180 | LLMsgVarData& vardata = msg_data->mMemberVarData[vnamep]; | ||
181 | |||
182 | if (!vardata.getName()) | ||
183 | { | ||
184 | llerrs << "Variable " << varname << " not in message " | ||
185 | << mCurrentRMessageData->mName << " block " << bnamep << llendl; | ||
186 | return -1; | ||
187 | } | ||
188 | |||
189 | if (mCurrentRMessageTemplate->mMemberBlocks[bnamep]->mType != MBT_SINGLE) | ||
190 | { | ||
191 | llerrs << "Block " << bnamep << " isn't type MBT_SINGLE," | ||
192 | " use getSize with blocknum argument!" << llendl; | ||
193 | return -1; | ||
194 | } | ||
195 | |||
196 | return vardata.getSize(); | ||
197 | } | ||
198 | |||
199 | S32 LLTemplateMessageReader::getSize(const char *blockname, S32 blocknum, const char *varname) | ||
200 | { | ||
201 | // is there a message ready to go? | ||
202 | if (mReceiveSize == -1) | ||
203 | { | ||
204 | llerrs << "No message waiting for decode 5!" << llendl; | ||
205 | return -1; | ||
206 | } | ||
207 | |||
208 | if (!mCurrentRMessageData) | ||
209 | { | ||
210 | llerrs << "Invalid mCurrentRMessageData in getData!" << llendl; | ||
211 | return -1; | ||
212 | } | ||
213 | |||
214 | char *bnamep = (char *)blockname + blocknum; | ||
215 | char *vnamep = (char *)varname; | ||
216 | |||
217 | LLMsgData::msg_blk_data_map_t::iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep); | ||
218 | |||
219 | if (iter == mCurrentRMessageData->mMemberBlocks.end()) | ||
220 | { | ||
221 | llerrs << "Block " << bnamep << " not in message " | ||
222 | << mCurrentRMessageData->mName << llendl; | ||
223 | return -1; | ||
224 | } | ||
225 | |||
226 | LLMsgBlkData* msg_data = iter->second; | ||
227 | LLMsgVarData& vardata = msg_data->mMemberVarData[vnamep]; | ||
228 | |||
229 | if (!vardata.getName()) | ||
230 | { | ||
231 | llerrs << "Variable " << vnamep << " not in message " | ||
232 | << mCurrentRMessageData->mName << " block " << bnamep << llendl; | ||
233 | return -1; | ||
234 | } | ||
235 | |||
236 | return vardata.getSize(); | ||
237 | } | ||
238 | |||
239 | void LLTemplateMessageReader::getBinaryData(const char *blockname, | ||
240 | const char *varname, void *datap, | ||
241 | S32 size, S32 blocknum, | ||
242 | S32 max_size) | ||
243 | { | ||
244 | getData(blockname, varname, datap, size, blocknum, max_size); | ||
245 | } | ||
246 | |||
247 | void LLTemplateMessageReader::getS8(const char *block, const char *var, | ||
248 | S8 &u, S32 blocknum) | ||
249 | { | ||
250 | getData(block, var, &u, sizeof(S8), blocknum); | ||
251 | } | ||
252 | |||
253 | void LLTemplateMessageReader::getU8(const char *block, const char *var, | ||
254 | U8 &u, S32 blocknum) | ||
255 | { | ||
256 | getData(block, var, &u, sizeof(U8), blocknum); | ||
257 | } | ||
258 | |||
259 | void LLTemplateMessageReader::getBOOL(const char *block, const char *var, | ||
260 | BOOL &b, S32 blocknum ) | ||
261 | { | ||
262 | U8 value; | ||
263 | getData(block, var, &value, sizeof(U8), blocknum); | ||
264 | b = (BOOL) value; | ||
265 | } | ||
266 | |||
267 | void LLTemplateMessageReader::getS16(const char *block, const char *var, | ||
268 | S16 &d, S32 blocknum) | ||
269 | { | ||
270 | getData(block, var, &d, sizeof(S16), blocknum); | ||
271 | } | ||
272 | |||
273 | void LLTemplateMessageReader::getU16(const char *block, const char *var, | ||
274 | U16 &d, S32 blocknum) | ||
275 | { | ||
276 | getData(block, var, &d, sizeof(U16), blocknum); | ||
277 | } | ||
278 | |||
279 | void LLTemplateMessageReader::getS32(const char *block, const char *var, | ||
280 | S32 &d, S32 blocknum) | ||
281 | { | ||
282 | getData(block, var, &d, sizeof(S32), blocknum); | ||
283 | } | ||
284 | |||
285 | void LLTemplateMessageReader::getU32(const char *block, const char *var, | ||
286 | U32 &d, S32 blocknum) | ||
287 | { | ||
288 | getData(block, var, &d, sizeof(U32), blocknum); | ||
289 | } | ||
290 | |||
291 | void LLTemplateMessageReader::getU64(const char *block, const char *var, | ||
292 | U64 &d, S32 blocknum) | ||
293 | { | ||
294 | getData(block, var, &d, sizeof(U64), blocknum); | ||
295 | } | ||
296 | |||
297 | void LLTemplateMessageReader::getF32(const char *block, const char *var, | ||
298 | F32 &d, S32 blocknum) | ||
299 | { | ||
300 | getData(block, var, &d, sizeof(F32), blocknum); | ||
301 | |||
302 | if( !llfinite( d ) ) | ||
303 | { | ||
304 | llwarns << "non-finite in getF32Fast " << block << " " << var | ||
305 | << llendl; | ||
306 | d = 0; | ||
307 | } | ||
308 | } | ||
309 | |||
310 | void LLTemplateMessageReader::getF64(const char *block, const char *var, | ||
311 | F64 &d, S32 blocknum) | ||
312 | { | ||
313 | getData(block, var, &d, sizeof(F64), blocknum); | ||
314 | |||
315 | if( !llfinite( d ) ) | ||
316 | { | ||
317 | llwarns << "non-finite in getF64Fast " << block << " " << var | ||
318 | << llendl; | ||
319 | d = 0; | ||
320 | } | ||
321 | } | ||
322 | |||
323 | void LLTemplateMessageReader::getVector3(const char *block, const char *var, | ||
324 | LLVector3 &v, S32 blocknum ) | ||
325 | { | ||
326 | getData(block, var, v.mV, sizeof(v.mV), blocknum); | ||
327 | |||
328 | if( !v.isFinite() ) | ||
329 | { | ||
330 | llwarns << "non-finite in getVector3Fast " << block << " " | ||
331 | << var << llendl; | ||
332 | v.zeroVec(); | ||
333 | } | ||
334 | } | ||
335 | |||
336 | void LLTemplateMessageReader::getVector4(const char *block, const char *var, | ||
337 | LLVector4 &v, S32 blocknum) | ||
338 | { | ||
339 | getData(block, var, v.mV, sizeof(v.mV), blocknum); | ||
340 | |||
341 | if( !v.isFinite() ) | ||
342 | { | ||
343 | llwarns << "non-finite in getVector4Fast " << block << " " | ||
344 | << var << llendl; | ||
345 | v.zeroVec(); | ||
346 | } | ||
347 | } | ||
348 | |||
349 | void LLTemplateMessageReader::getVector3d(const char *block, const char *var, | ||
350 | LLVector3d &v, S32 blocknum ) | ||
351 | { | ||
352 | getData(block, var, v.mdV, sizeof(v.mdV), blocknum); | ||
353 | |||
354 | if( !v.isFinite() ) | ||
355 | { | ||
356 | llwarns << "non-finite in getVector3dFast " << block << " " | ||
357 | << var << llendl; | ||
358 | v.zeroVec(); | ||
359 | } | ||
360 | |||
361 | } | ||
362 | |||
363 | void LLTemplateMessageReader::getQuat(const char *block, const char *var, | ||
364 | LLQuaternion &q, S32 blocknum) | ||
365 | { | ||
366 | LLVector3 vec; | ||
367 | getData(block, var, vec.mV, sizeof(vec.mV), blocknum); | ||
368 | if( vec.isFinite() ) | ||
369 | { | ||
370 | q.unpackFromVector3( vec ); | ||
371 | } | ||
372 | else | ||
373 | { | ||
374 | llwarns << "non-finite in getQuatFast " << block << " " << var | ||
375 | << llendl; | ||
376 | q.loadIdentity(); | ||
377 | } | ||
378 | } | ||
379 | |||
380 | void LLTemplateMessageReader::getUUID(const char *block, const char *var, | ||
381 | LLUUID &u, S32 blocknum) | ||
382 | { | ||
383 | getData(block, var, u.mData, sizeof(u.mData), blocknum); | ||
384 | } | ||
385 | |||
386 | inline void LLTemplateMessageReader::getIPAddr(const char *block, const char *var, U32 &u, S32 blocknum) | ||
387 | { | ||
388 | getData(block, var, &u, sizeof(U32), blocknum); | ||
389 | } | ||
390 | |||
391 | inline void LLTemplateMessageReader::getIPPort(const char *block, const char *var, U16 &u, S32 blocknum) | ||
392 | { | ||
393 | getData(block, var, &u, sizeof(U16), blocknum); | ||
394 | u = ntohs(u); | ||
395 | } | ||
396 | |||
397 | inline void LLTemplateMessageReader::getString(const char *block, const char *var, S32 buffer_size, char *s, S32 blocknum ) | ||
398 | { | ||
399 | s[0] = '\0'; | ||
400 | getData(block, var, s, 0, blocknum, buffer_size); | ||
401 | s[buffer_size - 1] = '\0'; | ||
402 | } | ||
403 | |||
404 | //virtual | ||
405 | S32 LLTemplateMessageReader::getMessageSize() const | ||
406 | { | ||
407 | return mReceiveSize; | ||
408 | } | ||
409 | |||
410 | // Returns template for the message contained in buffer | ||
411 | BOOL LLTemplateMessageReader::decodeTemplate( | ||
412 | const U8* buffer, S32 buffer_size, // inputs | ||
413 | LLMessageTemplate** msg_template ) // outputs | ||
414 | { | ||
415 | const U8* header = buffer + LL_PACKET_ID_SIZE; | ||
416 | |||
417 | // is there a message ready to go? | ||
418 | if (buffer_size <= 0) | ||
419 | { | ||
420 | llwarns << "No message waiting for decode!" << llendl; | ||
421 | return(FALSE); | ||
422 | } | ||
423 | |||
424 | U32 num = 0; | ||
425 | |||
426 | if (header[0] != 255) | ||
427 | { | ||
428 | // high frequency message | ||
429 | num = header[0]; | ||
430 | } | ||
431 | else if ((buffer_size >= ((S32) LL_MINIMUM_VALID_PACKET_SIZE + 1)) && (header[1] != 255)) | ||
432 | { | ||
433 | // medium frequency message | ||
434 | num = (255 << 8) | header[1]; | ||
435 | } | ||
436 | else if ((buffer_size >= ((S32) LL_MINIMUM_VALID_PACKET_SIZE + 3)) && (header[1] == 255)) | ||
437 | { | ||
438 | // low frequency message | ||
439 | U16 message_id_U16 = 0; | ||
440 | // I think this check busts the message system. | ||
441 | // it appears that if there is a NULL in the message #, it won't copy it.... | ||
442 | // what was the goal? | ||
443 | //if(header[2]) | ||
444 | memcpy(&message_id_U16, &header[2], 2); | ||
445 | |||
446 | // dependant on endian-ness: | ||
447 | // U32 temp = (255 << 24) | (255 << 16) | header[2]; | ||
448 | |||
449 | // independant of endian-ness: | ||
450 | message_id_U16 = ntohs(message_id_U16); | ||
451 | num = 0xFFFF0000 | message_id_U16; | ||
452 | } | ||
453 | else // bogus packet received (too short) | ||
454 | { | ||
455 | llwarns << "Packet with unusable length received (too short): " | ||
456 | << buffer_size << llendl; | ||
457 | return(FALSE); | ||
458 | } | ||
459 | |||
460 | LLMessageTemplate* temp = get_ptr_in_map(mMessageNumbers,num); | ||
461 | if (temp) | ||
462 | { | ||
463 | *msg_template = temp; | ||
464 | } | ||
465 | else | ||
466 | { | ||
467 | llwarns << "Message #" << std::hex << num << std::dec | ||
468 | << " received but not registered!" << llendl; | ||
469 | gMessageSystem->callExceptionFunc(MX_UNREGISTERED_MESSAGE); | ||
470 | return(FALSE); | ||
471 | } | ||
472 | |||
473 | return(TRUE); | ||
474 | } | ||
475 | |||
476 | void LLTemplateMessageReader::logRanOffEndOfPacket( const LLHost& host ) | ||
477 | { | ||
478 | // we've run off the end of the packet! | ||
479 | llwarns << "Ran off end of packet " << mCurrentRMessageTemplate->mName | ||
480 | // << " with id " << mCurrentRecvPacketID | ||
481 | << " from " << host | ||
482 | << llendl; | ||
483 | if(gMessageSystem->mVerboseLog) | ||
484 | { | ||
485 | llinfos << "MSG: -> " << host << "\tREAD PAST END:\t" | ||
486 | // << mCurrentRecvPacketID << " " | ||
487 | << getMessageName() << llendl; | ||
488 | } | ||
489 | gMessageSystem->callExceptionFunc(MX_RAN_OFF_END_OF_PACKET); | ||
490 | } | ||
491 | |||
492 | // decode a given message | ||
493 | BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender ) | ||
494 | { | ||
495 | llassert( mReceiveSize >= 0 ); | ||
496 | llassert( mCurrentRMessageTemplate); | ||
497 | llassert( !mCurrentRMessageData ); | ||
498 | delete mCurrentRMessageData; // just to make sure | ||
499 | |||
500 | S32 decode_pos = LL_PACKET_ID_SIZE + (S32)(mCurrentRMessageTemplate->mFrequency); | ||
501 | |||
502 | // create base working data set | ||
503 | mCurrentRMessageData = new LLMsgData(mCurrentRMessageTemplate->mName); | ||
504 | |||
505 | // loop through the template building the data structure as we go | ||
506 | for (LLMessageTemplate::message_block_map_t::iterator iter = mCurrentRMessageTemplate->mMemberBlocks.begin(); | ||
507 | iter != mCurrentRMessageTemplate->mMemberBlocks.end(); iter++) | ||
508 | { | ||
509 | LLMessageBlock* mbci = iter->second; | ||
510 | U8 repeat_number; | ||
511 | S32 i; | ||
512 | |||
513 | // how many of this block? | ||
514 | |||
515 | if (mbci->mType == MBT_SINGLE) | ||
516 | { | ||
517 | // just one | ||
518 | repeat_number = 1; | ||
519 | } | ||
520 | else if (mbci->mType == MBT_MULTIPLE) | ||
521 | { | ||
522 | // a known number | ||
523 | repeat_number = mbci->mNumber; | ||
524 | } | ||
525 | else if (mbci->mType == MBT_VARIABLE) | ||
526 | { | ||
527 | // need to read the number from the message | ||
528 | // repeat number is a single byte | ||
529 | if (decode_pos >= mReceiveSize) | ||
530 | { | ||
531 | logRanOffEndOfPacket( sender ); | ||
532 | return FALSE; | ||
533 | } | ||
534 | repeat_number = buffer[decode_pos]; | ||
535 | decode_pos++; | ||
536 | } | ||
537 | else | ||
538 | { | ||
539 | llerrs << "Unknown block type" << llendl; | ||
540 | return FALSE; | ||
541 | } | ||
542 | |||
543 | LLMsgBlkData* cur_data_block = NULL; | ||
544 | |||
545 | // now loop through the block | ||
546 | for (i = 0; i < repeat_number; i++) | ||
547 | { | ||
548 | if (i) | ||
549 | { | ||
550 | // build new name to prevent collisions | ||
551 | // TODO: This should really change to a vector | ||
552 | cur_data_block = new LLMsgBlkData(mbci->mName, repeat_number); | ||
553 | cur_data_block->mName = mbci->mName + i; | ||
554 | } | ||
555 | else | ||
556 | { | ||
557 | cur_data_block = new LLMsgBlkData(mbci->mName, repeat_number); | ||
558 | } | ||
559 | |||
560 | // add the block to the message | ||
561 | mCurrentRMessageData->addBlock(cur_data_block); | ||
562 | |||
563 | // now read the variables | ||
564 | for (LLMessageBlock::message_variable_map_t::iterator iter = mbci->mMemberVariables.begin(); | ||
565 | iter != mbci->mMemberVariables.end(); iter++) | ||
566 | { | ||
567 | LLMessageVariable& mvci = *(iter->second); | ||
568 | // ok, build out the variables | ||
569 | // add variable block | ||
570 | cur_data_block->addVariable(mvci.getName(), mvci.getType()); | ||
571 | |||
572 | // what type of variable? | ||
573 | if (mvci.getType() == MVT_VARIABLE) | ||
574 | { | ||
575 | // variable, get the number of bytes to read from the template | ||
576 | S32 data_size = mvci.getSize(); | ||
577 | U8 tsizeb = 0; | ||
578 | U16 tsizeh = 0; | ||
579 | U32 tsize = 0; | ||
580 | |||
581 | if ((decode_pos + data_size) > mReceiveSize) | ||
582 | { | ||
583 | logRanOffEndOfPacket( sender ); | ||
584 | return FALSE; | ||
585 | } | ||
586 | switch(data_size) | ||
587 | { | ||
588 | case 1: | ||
589 | htonmemcpy(&tsizeb, &buffer[decode_pos], MVT_U8, 1); | ||
590 | tsize = tsizeb; | ||
591 | break; | ||
592 | case 2: | ||
593 | htonmemcpy(&tsizeh, &buffer[decode_pos], MVT_U16, 2); | ||
594 | tsize = tsizeh; | ||
595 | break; | ||
596 | case 4: | ||
597 | htonmemcpy(&tsizeb, &buffer[decode_pos], MVT_U32, 4); | ||
598 | break; | ||
599 | default: | ||
600 | llerrs << "Attempting to read variable field with unknown size of " << data_size << llendl; | ||
601 | break; | ||
602 | |||
603 | } | ||
604 | decode_pos += data_size; | ||
605 | |||
606 | if ((decode_pos + (S32)tsize) > mReceiveSize) | ||
607 | { | ||
608 | logRanOffEndOfPacket( sender ); | ||
609 | return FALSE; | ||
610 | } | ||
611 | cur_data_block->addData(mvci.getName(), &buffer[decode_pos], tsize, mvci.getType()); | ||
612 | decode_pos += tsize; | ||
613 | } | ||
614 | else | ||
615 | { | ||
616 | // fixed! | ||
617 | // so, copy data pointer and set data size to fixed size | ||
618 | |||
619 | if ((decode_pos + mvci.getSize()) > mReceiveSize) | ||
620 | { | ||
621 | logRanOffEndOfPacket( sender ); | ||
622 | return FALSE; | ||
623 | } | ||
624 | |||
625 | cur_data_block->addData(mvci.getName(), &buffer[decode_pos], mvci.getSize(), mvci.getType()); | ||
626 | decode_pos += mvci.getSize(); | ||
627 | } | ||
628 | } | ||
629 | } | ||
630 | } | ||
631 | |||
632 | if (mCurrentRMessageData->mMemberBlocks.empty() | ||
633 | && !mCurrentRMessageTemplate->mMemberBlocks.empty()) | ||
634 | { | ||
635 | lldebugs << "Empty message '" << mCurrentRMessageTemplate->mName << "' (no blocks)" << llendl; | ||
636 | return FALSE; | ||
637 | } | ||
638 | |||
639 | { | ||
640 | static LLTimer decode_timer; | ||
641 | |||
642 | if(LLMessageReader::getTimeDecodes() || gMessageSystem->getTimingCallback()) | ||
643 | { | ||
644 | decode_timer.reset(); | ||
645 | } | ||
646 | |||
647 | // if( mCurrentRMessageTemplate->mName == _PREHASH_AgentToNewRegion ) | ||
648 | // { | ||
649 | // VTResume(); // VTune | ||
650 | // } | ||
651 | |||
652 | { | ||
653 | LLFastTimer t(LLFastTimer::FTM_PROCESS_MESSAGES); | ||
654 | if( !mCurrentRMessageTemplate->callHandlerFunc(gMessageSystem) ) | ||
655 | { | ||
656 | llwarns << "Message from " << sender << " with no handler function received: " << mCurrentRMessageTemplate->mName << llendl; | ||
657 | } | ||
658 | } | ||
659 | |||
660 | // if( mCurrentRMessageTemplate->mName == _PREHASH_AgentToNewRegion ) | ||
661 | // { | ||
662 | // VTPause(); // VTune | ||
663 | // } | ||
664 | |||
665 | if(LLMessageReader::getTimeDecodes() || gMessageSystem->getTimingCallback()) | ||
666 | { | ||
667 | F32 decode_time = decode_timer.getElapsedTimeF32(); | ||
668 | |||
669 | if (gMessageSystem->getTimingCallback()) | ||
670 | { | ||
671 | (gMessageSystem->getTimingCallback())(mCurrentRMessageTemplate->mName, | ||
672 | decode_time, | ||
673 | gMessageSystem->getTimingCallbackData()); | ||
674 | } | ||
675 | |||
676 | if (LLMessageReader::getTimeDecodes()) | ||
677 | { | ||
678 | mCurrentRMessageTemplate->mDecodeTimeThisFrame += decode_time; | ||
679 | |||
680 | mCurrentRMessageTemplate->mTotalDecoded++; | ||
681 | mCurrentRMessageTemplate->mTotalDecodeTime += decode_time; | ||
682 | |||
683 | if( mCurrentRMessageTemplate->mMaxDecodeTimePerMsg < decode_time ) | ||
684 | { | ||
685 | mCurrentRMessageTemplate->mMaxDecodeTimePerMsg = decode_time; | ||
686 | } | ||
687 | |||
688 | |||
689 | if(decode_time > LLMessageReader::getTimeDecodesSpamThreshold()) | ||
690 | { | ||
691 | lldebugs << "--------- Message " << mCurrentRMessageTemplate->mName << " decode took " << decode_time << " seconds. (" << | ||
692 | mCurrentRMessageTemplate->mMaxDecodeTimePerMsg << " max, " << | ||
693 | (mCurrentRMessageTemplate->mTotalDecodeTime / mCurrentRMessageTemplate->mTotalDecoded) << " avg)" << llendl; | ||
694 | } | ||
695 | } | ||
696 | } | ||
697 | } | ||
698 | return TRUE; | ||
699 | } | ||
700 | |||
701 | BOOL LLTemplateMessageReader::validateMessage(const U8* buffer, | ||
702 | S32 buffer_size, | ||
703 | const LLHost& sender) | ||
704 | { | ||
705 | mReceiveSize = buffer_size; | ||
706 | BOOL result = decodeTemplate(buffer, buffer_size, &mCurrentRMessageTemplate ); | ||
707 | if(result) | ||
708 | { | ||
709 | mCurrentRMessageTemplate->mReceiveCount++; | ||
710 | lldebugst(LLERR_MESSAGE) << "MessageRecvd:" | ||
711 | << mCurrentRMessageTemplate->mName | ||
712 | << " from " << sender << llendl; | ||
713 | } | ||
714 | return result; | ||
715 | } | ||
716 | |||
717 | BOOL LLTemplateMessageReader::readMessage(const U8* buffer, | ||
718 | const LLHost& sender) | ||
719 | { | ||
720 | return decodeData(buffer, sender); | ||
721 | } | ||
722 | |||
723 | //virtual | ||
724 | const char* LLTemplateMessageReader::getMessageName() const | ||
725 | { | ||
726 | static char empty_string[] = ""; | ||
727 | return mCurrentRMessageTemplate ? mCurrentRMessageTemplate->mName : empty_string; | ||
728 | } | ||
729 | |||
730 | //virtual | ||
731 | bool LLTemplateMessageReader::isTrusted() const | ||
732 | { | ||
733 | return mCurrentRMessageTemplate->getTrust() == MT_TRUST; | ||
734 | } | ||
735 | |||
736 | //virtual | ||
737 | bool LLTemplateMessageReader::isBanned(bool trustedSource) const | ||
738 | { | ||
739 | return mCurrentRMessageTemplate->isBanned(trustedSource); | ||
740 | } | ||
741 | |||
742 | //virtual | ||
743 | void LLTemplateMessageReader::copyToBuilder(LLMessageBuilder& builder) const | ||
744 | { | ||
745 | if(NULL == mCurrentRMessageTemplate) | ||
746 | { | ||
747 | return; | ||
748 | } | ||
749 | builder.copyFromMessageData(*mCurrentRMessageData); | ||
750 | } | ||