diff options
Diffstat (limited to 'linden/indra/llmessage/message.cpp')
-rw-r--r-- | linden/indra/llmessage/message.cpp | 5907 |
1 files changed, 5907 insertions, 0 deletions
diff --git a/linden/indra/llmessage/message.cpp b/linden/indra/llmessage/message.cpp new file mode 100644 index 0000000..5baefff --- /dev/null +++ b/linden/indra/llmessage/message.cpp | |||
@@ -0,0 +1,5907 @@ | |||
1 | /** | ||
2 | * @file message.cpp | ||
3 | * @brief LLMessageSystem class implementation | ||
4 | * | ||
5 | * Copyright (c) 2001-2007, Linden Research, Inc. | ||
6 | * | ||
7 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
8 | * to you under the terms of the GNU General Public License, version 2.0 | ||
9 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
10 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
11 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
12 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
13 | * | ||
14 | * There are special exceptions to the terms and conditions of the GPL as | ||
15 | * it is applied to this Source Code. View the full text of the exception | ||
16 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
17 | * online at http://secondlife.com/developers/opensource/flossexception | ||
18 | * | ||
19 | * By copying, modifying or distributing this software, you acknowledge | ||
20 | * that you have read and understood your obligations described above, | ||
21 | * and agree to abide by those obligations. | ||
22 | * | ||
23 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
24 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
25 | * COMPLETENESS OR PERFORMANCE. | ||
26 | */ | ||
27 | |||
28 | #include "linden_common.h" | ||
29 | |||
30 | #include "message.h" | ||
31 | |||
32 | // system library includes | ||
33 | #if !LL_WINDOWS | ||
34 | // following header files required for inet_addr() | ||
35 | #include <sys/types.h> | ||
36 | #include <sys/socket.h> | ||
37 | #include <netinet/in.h> | ||
38 | #include <arpa/inet.h> | ||
39 | #endif | ||
40 | #include <stdio.h> | ||
41 | #include <stdlib.h> | ||
42 | #include <cstring> | ||
43 | #include <time.h> | ||
44 | #include <iomanip> | ||
45 | #include <iterator> | ||
46 | #include <sstream> | ||
47 | |||
48 | #include "llapr.h" | ||
49 | #include "apr-1/apr_portable.h" | ||
50 | #include "apr-1/apr_network_io.h" | ||
51 | #include "apr-1/apr_poll.h" | ||
52 | |||
53 | // linden library headers | ||
54 | #include "indra_constants.h" | ||
55 | #include "lldir.h" | ||
56 | #include "llerror.h" | ||
57 | #include "llfasttimer.h" | ||
58 | #include "llmd5.h" | ||
59 | #include "llsd.h" | ||
60 | #include "lltransfermanager.h" | ||
61 | #include "lluuid.h" | ||
62 | #include "llxfermanager.h" | ||
63 | #include "timing.h" | ||
64 | #include "llquaternion.h" | ||
65 | #include "u64.h" | ||
66 | #include "v3dmath.h" | ||
67 | #include "v3math.h" | ||
68 | #include "v4math.h" | ||
69 | #include "lltransfertargetvfile.h" | ||
70 | |||
71 | // Constants | ||
72 | //const char* MESSAGE_LOG_FILENAME = "message.log"; | ||
73 | static const F32 CIRCUIT_DUMP_TIMEOUT = 30.f; | ||
74 | static const S32 TRUST_TIME_WINDOW = 3; | ||
75 | |||
76 | class LLMsgVarData | ||
77 | { | ||
78 | public: | ||
79 | LLMsgVarData() : mName(NULL), mSize(-1), mDataSize(-1), mData(NULL), mType(MVT_U8) | ||
80 | { | ||
81 | } | ||
82 | |||
83 | LLMsgVarData(const char *name, EMsgVariableType type) : mSize(-1), mDataSize(-1), mData(NULL), mType(type) | ||
84 | { | ||
85 | mName = (char *)name; | ||
86 | } | ||
87 | |||
88 | ~LLMsgVarData() | ||
89 | { | ||
90 | // copy constructor just copies the mData pointer, so only delete mData explicitly | ||
91 | } | ||
92 | |||
93 | void deleteData() | ||
94 | { | ||
95 | delete[] mData; | ||
96 | mData = NULL; | ||
97 | } | ||
98 | |||
99 | void addData(const void *indata, S32 size, EMsgVariableType type, S32 data_size = -1); | ||
100 | |||
101 | char *getName() const { return mName; } | ||
102 | S32 getSize() const { return mSize; } | ||
103 | void *getData() { return (void*)mData; } | ||
104 | S32 getDataSize() const { return mDataSize; } | ||
105 | EMsgVariableType getType() const { return mType; } | ||
106 | |||
107 | protected: | ||
108 | char *mName; | ||
109 | S32 mSize; | ||
110 | S32 mDataSize; | ||
111 | |||
112 | U8 *mData; | ||
113 | EMsgVariableType mType; | ||
114 | }; | ||
115 | |||
116 | |||
117 | class LLMsgBlkData | ||
118 | { | ||
119 | public: | ||
120 | LLMsgBlkData(const char *name, S32 blocknum) : mOffset(-1), mBlockNumber(blocknum), mTotalSize(-1) | ||
121 | { | ||
122 | mName = (char *)name; | ||
123 | } | ||
124 | |||
125 | ~LLMsgBlkData() | ||
126 | { | ||
127 | for (msg_var_data_map_t::iterator iter = mMemberVarData.begin(); | ||
128 | iter != mMemberVarData.end(); iter++) | ||
129 | { | ||
130 | iter->deleteData(); | ||
131 | } | ||
132 | } | ||
133 | |||
134 | void addVariable(const char *name, EMsgVariableType type) | ||
135 | { | ||
136 | LLMsgVarData tmp(name,type); | ||
137 | mMemberVarData[name] = tmp; | ||
138 | } | ||
139 | |||
140 | void addData(char *name, const void *data, S32 size, EMsgVariableType type, S32 data_size = -1) | ||
141 | { | ||
142 | LLMsgVarData* temp = &mMemberVarData[name]; // creates a new entry if one doesn't exist | ||
143 | temp->addData(data, size, type, data_size); | ||
144 | } | ||
145 | |||
146 | S32 mOffset; | ||
147 | S32 mBlockNumber; | ||
148 | typedef LLDynamicArrayIndexed<LLMsgVarData, const char *, 8> msg_var_data_map_t; | ||
149 | msg_var_data_map_t mMemberVarData; | ||
150 | char *mName; | ||
151 | S32 mTotalSize; | ||
152 | }; | ||
153 | |||
154 | |||
155 | class LLMsgData | ||
156 | { | ||
157 | public: | ||
158 | LLMsgData(const char *name) : mTotalSize(-1) | ||
159 | { | ||
160 | mName = (char *)name; | ||
161 | } | ||
162 | ~LLMsgData() | ||
163 | { | ||
164 | for_each(mMemberBlocks.begin(), mMemberBlocks.end(), DeletePairedPointer()); | ||
165 | } | ||
166 | |||
167 | void addBlock(LLMsgBlkData *blockp) | ||
168 | { | ||
169 | mMemberBlocks[blockp->mName] = blockp; | ||
170 | } | ||
171 | |||
172 | void addDataFast(char *blockname, char *varname, const void *data, S32 size, EMsgVariableType type, S32 data_size = -1); | ||
173 | |||
174 | public: | ||
175 | S32 mOffset; | ||
176 | typedef std::map<char*, LLMsgBlkData*> msg_blk_data_map_t; | ||
177 | msg_blk_data_map_t mMemberBlocks; | ||
178 | char *mName; | ||
179 | S32 mTotalSize; | ||
180 | }; | ||
181 | |||
182 | inline void LLMsgVarData::addData(const void *data, S32 size, EMsgVariableType type, S32 data_size) | ||
183 | { | ||
184 | mSize = size; | ||
185 | mDataSize = data_size; | ||
186 | if ( (type != MVT_VARIABLE) && (type != MVT_FIXED) | ||
187 | && (mType != MVT_VARIABLE) && (mType != MVT_FIXED)) | ||
188 | { | ||
189 | if (mType != type) | ||
190 | { | ||
191 | llwarns << "Type mismatch in addData for " << mName | ||
192 | << " message: " << gMessageSystem->getCurrentSMessageName() | ||
193 | << " block: " << gMessageSystem->getCurrentSBlockName() | ||
194 | << llendl; | ||
195 | } | ||
196 | } | ||
197 | if(size) | ||
198 | { | ||
199 | delete mData; // Delete it if it already exists | ||
200 | mData = new U8[size]; | ||
201 | htonmemcpy(mData, data, mType, size); | ||
202 | } | ||
203 | } | ||
204 | |||
205 | |||
206 | |||
207 | inline void LLMsgData::addDataFast(char *blockname, char *varname, const void *data, S32 size, EMsgVariableType type, S32 data_size) | ||
208 | { | ||
209 | // remember that if the blocknumber is > 0 then the number is appended to the name | ||
210 | char *namep = (char *)blockname; | ||
211 | LLMsgBlkData* block_data = mMemberBlocks[namep]; | ||
212 | if (block_data->mBlockNumber) | ||
213 | { | ||
214 | namep += block_data->mBlockNumber; | ||
215 | block_data->addData(varname, data, size, type, data_size); | ||
216 | } | ||
217 | else | ||
218 | { | ||
219 | block_data->addData(varname, data, size, type, data_size); | ||
220 | } | ||
221 | } | ||
222 | |||
223 | // LLMessage* classes store the template of messages | ||
224 | |||
225 | |||
226 | class LLMessageVariable | ||
227 | { | ||
228 | public: | ||
229 | LLMessageVariable() : mName(NULL), mType(MVT_NULL), mSize(-1) | ||
230 | { | ||
231 | } | ||
232 | |||
233 | LLMessageVariable(char *name) : mType(MVT_NULL), mSize(-1) | ||
234 | { | ||
235 | mName = name; | ||
236 | } | ||
237 | |||
238 | LLMessageVariable(char *name, const EMsgVariableType type, const S32 size) : mType(type), mSize(size) | ||
239 | { | ||
240 | mName = gMessageStringTable.getString(name); | ||
241 | } | ||
242 | |||
243 | ~LLMessageVariable() {} | ||
244 | |||
245 | friend std::ostream& operator<<(std::ostream& s, LLMessageVariable &msg); | ||
246 | |||
247 | EMsgVariableType getType() const { return mType; } | ||
248 | S32 getSize() const { return mSize; } | ||
249 | char *getName() const { return mName; } | ||
250 | protected: | ||
251 | char *mName; | ||
252 | EMsgVariableType mType; | ||
253 | S32 mSize; | ||
254 | }; | ||
255 | |||
256 | |||
257 | typedef enum e_message_block_type | ||
258 | { | ||
259 | MBT_NULL, | ||
260 | MBT_SINGLE, | ||
261 | MBT_MULTIPLE, | ||
262 | MBT_VARIABLE, | ||
263 | MBT_EOF | ||
264 | } EMsgBlockType; | ||
265 | |||
266 | class LLMessageBlock | ||
267 | { | ||
268 | public: | ||
269 | LLMessageBlock(char *name, EMsgBlockType type, S32 number = 1) : mType(type), mNumber(number), mTotalSize(0) | ||
270 | { | ||
271 | mName = gMessageStringTable.getString(name); | ||
272 | } | ||
273 | |||
274 | ~LLMessageBlock() | ||
275 | { | ||
276 | for_each(mMemberVariables.begin(), mMemberVariables.end(), DeletePairedPointer()); | ||
277 | } | ||
278 | |||
279 | void addVariable(char *name, const EMsgVariableType type, const S32 size) | ||
280 | { | ||
281 | LLMessageVariable** varp = &mMemberVariables[name]; | ||
282 | if (*varp != NULL) | ||
283 | { | ||
284 | llerrs << name << " has already been used as a variable name!" << llendl; | ||
285 | } | ||
286 | *varp = new LLMessageVariable(name, type, size); | ||
287 | if (((*varp)->getType() != MVT_VARIABLE) | ||
288 | &&(mTotalSize != -1)) | ||
289 | { | ||
290 | mTotalSize += (*varp)->getSize(); | ||
291 | } | ||
292 | else | ||
293 | { | ||
294 | mTotalSize = -1; | ||
295 | } | ||
296 | } | ||
297 | |||
298 | EMsgVariableType getVariableType(char *name) | ||
299 | { | ||
300 | return (mMemberVariables[name])->getType(); | ||
301 | } | ||
302 | |||
303 | S32 getVariableSize(char *name) | ||
304 | { | ||
305 | return (mMemberVariables[name])->getSize(); | ||
306 | } | ||
307 | |||
308 | friend std::ostream& operator<<(std::ostream& s, LLMessageBlock &msg); | ||
309 | |||
310 | typedef std::map<const char *, LLMessageVariable*> message_variable_map_t; | ||
311 | message_variable_map_t mMemberVariables; | ||
312 | char *mName; | ||
313 | EMsgBlockType mType; | ||
314 | S32 mNumber; | ||
315 | S32 mTotalSize; | ||
316 | }; | ||
317 | |||
318 | |||
319 | enum EMsgFrequency | ||
320 | { | ||
321 | MFT_NULL = 0, // value is size of message number in bytes | ||
322 | MFT_HIGH = 1, | ||
323 | MFT_MEDIUM = 2, | ||
324 | MFT_LOW = 4 | ||
325 | }; | ||
326 | |||
327 | typedef enum e_message_trust | ||
328 | { | ||
329 | MT_TRUST, | ||
330 | MT_NOTRUST | ||
331 | } EMsgTrust; | ||
332 | |||
333 | enum EMsgEncoding | ||
334 | { | ||
335 | ME_UNENCODED, | ||
336 | ME_ZEROCODED | ||
337 | }; | ||
338 | |||
339 | class LLMessageTemplate | ||
340 | { | ||
341 | public: | ||
342 | LLMessageTemplate(const char *name, U32 message_number, EMsgFrequency freq) | ||
343 | : | ||
344 | //mMemberBlocks(), | ||
345 | mName(NULL), | ||
346 | mFrequency(freq), | ||
347 | mTrust(MT_NOTRUST), | ||
348 | mEncoding(ME_ZEROCODED), | ||
349 | mMessageNumber(message_number), | ||
350 | mTotalSize(0), | ||
351 | mReceiveCount(0), | ||
352 | mReceiveBytes(0), | ||
353 | mReceiveInvalid(0), | ||
354 | mDecodeTimeThisFrame(0.f), | ||
355 | mTotalDecoded(0), | ||
356 | mTotalDecodeTime(0.f), | ||
357 | mMaxDecodeTimePerMsg(0.f), | ||
358 | mBanFromTrusted(false), | ||
359 | mBanFromUntrusted(false), | ||
360 | mHandlerFunc(NULL), | ||
361 | mUserData(NULL) | ||
362 | { | ||
363 | mName = gMessageStringTable.getString(name); | ||
364 | } | ||
365 | |||
366 | ~LLMessageTemplate() | ||
367 | { | ||
368 | for_each(mMemberBlocks.begin(), mMemberBlocks.end(), DeletePairedPointer()); | ||
369 | } | ||
370 | |||
371 | void addBlock(LLMessageBlock *blockp) | ||
372 | { | ||
373 | LLMessageBlock** member_blockp = &mMemberBlocks[blockp->mName]; | ||
374 | if (*member_blockp != NULL) | ||
375 | { | ||
376 | llerrs << "Block " << blockp->mName | ||
377 | << "has already been used as a block name!" << llendl; | ||
378 | } | ||
379 | *member_blockp = blockp; | ||
380 | if ( (mTotalSize != -1) | ||
381 | &&(blockp->mTotalSize != -1) | ||
382 | &&( (blockp->mType == MBT_SINGLE) | ||
383 | ||(blockp->mType == MBT_MULTIPLE))) | ||
384 | { | ||
385 | mTotalSize += blockp->mNumber*blockp->mTotalSize; | ||
386 | } | ||
387 | else | ||
388 | { | ||
389 | mTotalSize = -1; | ||
390 | } | ||
391 | } | ||
392 | |||
393 | LLMessageBlock *getBlock(char *name) | ||
394 | { | ||
395 | return mMemberBlocks[name]; | ||
396 | } | ||
397 | |||
398 | // Trusted messages can only be recieved on trusted circuits. | ||
399 | void setTrust(EMsgTrust t) | ||
400 | { | ||
401 | mTrust = t; | ||
402 | } | ||
403 | |||
404 | EMsgTrust getTrust(void) | ||
405 | { | ||
406 | return mTrust; | ||
407 | } | ||
408 | |||
409 | // controls for how the message should be encoded | ||
410 | void setEncoding(EMsgEncoding e) | ||
411 | { | ||
412 | mEncoding = e; | ||
413 | } | ||
414 | EMsgEncoding getEncoding() | ||
415 | { | ||
416 | return mEncoding; | ||
417 | } | ||
418 | |||
419 | void setHandlerFunc(void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data) | ||
420 | { | ||
421 | mHandlerFunc = handler_func; | ||
422 | mUserData = user_data; | ||
423 | } | ||
424 | |||
425 | BOOL callHandlerFunc(LLMessageSystem *msgsystem) | ||
426 | { | ||
427 | if (mHandlerFunc) | ||
428 | { | ||
429 | mHandlerFunc(msgsystem, mUserData); | ||
430 | return TRUE; | ||
431 | } | ||
432 | return FALSE; | ||
433 | } | ||
434 | |||
435 | bool isBanned(bool trustedSource) | ||
436 | { | ||
437 | return trustedSource ? mBanFromTrusted : mBanFromUntrusted; | ||
438 | } | ||
439 | |||
440 | friend std::ostream& operator<<(std::ostream& s, LLMessageTemplate &msg); | ||
441 | |||
442 | public: | ||
443 | typedef std::map<char*, LLMessageBlock*> message_block_map_t; | ||
444 | message_block_map_t mMemberBlocks; | ||
445 | char *mName; | ||
446 | EMsgFrequency mFrequency; | ||
447 | EMsgTrust mTrust; | ||
448 | EMsgEncoding mEncoding; | ||
449 | U32 mMessageNumber; | ||
450 | S32 mTotalSize; | ||
451 | U32 mReceiveCount; // how many of this template have been received since last reset | ||
452 | U32 mReceiveBytes; // How many bytes received | ||
453 | U32 mReceiveInvalid; // How many "invalid" packets | ||
454 | F32 mDecodeTimeThisFrame; // Total seconds spent decoding this frame | ||
455 | U32 mTotalDecoded; // Total messages successfully decoded | ||
456 | F32 mTotalDecodeTime; // Total time successfully decoding messages | ||
457 | F32 mMaxDecodeTimePerMsg; | ||
458 | |||
459 | bool mBanFromTrusted; | ||
460 | bool mBanFromUntrusted; | ||
461 | |||
462 | private: | ||
463 | // message handler function (this is set by each application) | ||
464 | void (*mHandlerFunc)(LLMessageSystem *msgsystem, void **user_data); | ||
465 | void **mUserData; | ||
466 | }; | ||
467 | |||
468 | |||
469 | |||
470 | // static | ||
471 | BOOL LLMessageSystem::mTimeDecodes = FALSE; | ||
472 | |||
473 | // static, 50ms per message decode | ||
474 | F32 LLMessageSystem::mTimeDecodesSpamThreshold = 0.05f; | ||
475 | |||
476 | // *NOTE: This needs to be moved into a seperate file so that it never gets | ||
477 | // included in the viewer. 30 Sep 2002 mark | ||
478 | // *NOTE: I don't think it's important that the messgage system tracks | ||
479 | // this since it must get set externally. 2004.08.25 Phoenix. | ||
480 | static std::string g_shared_secret; | ||
481 | std::string get_shared_secret(); | ||
482 | |||
483 | class LLMessagePollInfo | ||
484 | { | ||
485 | public: | ||
486 | apr_socket_t *mAPRSocketp; | ||
487 | apr_pollfd_t mPollFD; | ||
488 | }; | ||
489 | |||
490 | |||
491 | // LLMessageVariable functions and friends | ||
492 | |||
493 | std::ostream& operator<<(std::ostream& s, LLMessageVariable &msg) | ||
494 | { | ||
495 | s << "\t\t" << msg.mName << " ("; | ||
496 | switch (msg.mType) | ||
497 | { | ||
498 | case MVT_FIXED: | ||
499 | s << "Fixed, " << msg.mSize << " bytes total)\n"; | ||
500 | break; | ||
501 | case MVT_VARIABLE: | ||
502 | s << "Variable, " << msg.mSize << " bytes of size info)\n"; | ||
503 | break; | ||
504 | default: | ||
505 | s << "Unknown\n"; | ||
506 | break; | ||
507 | } | ||
508 | return s; | ||
509 | } | ||
510 | |||
511 | // LLMessageBlock functions and friends | ||
512 | |||
513 | std::ostream& operator<<(std::ostream& s, LLMessageBlock &msg) | ||
514 | { | ||
515 | s << "\t" << msg.mName << " ("; | ||
516 | switch (msg.mType) | ||
517 | { | ||
518 | case MBT_SINGLE: | ||
519 | s << "Fixed"; | ||
520 | break; | ||
521 | case MBT_MULTIPLE: | ||
522 | s << "Multiple - " << msg.mNumber << " copies"; | ||
523 | break; | ||
524 | case MBT_VARIABLE: | ||
525 | s << "Variable"; | ||
526 | break; | ||
527 | default: | ||
528 | s << "Unknown"; | ||
529 | break; | ||
530 | } | ||
531 | if (msg.mTotalSize != -1) | ||
532 | { | ||
533 | s << ", " << msg.mTotalSize << " bytes each, " << msg.mNumber*msg.mTotalSize << " bytes total)\n"; | ||
534 | } | ||
535 | else | ||
536 | { | ||
537 | s << ")\n"; | ||
538 | } | ||
539 | |||
540 | |||
541 | for (LLMessageBlock::message_variable_map_t::iterator iter = msg.mMemberVariables.begin(); | ||
542 | iter != msg.mMemberVariables.end(); iter++) | ||
543 | { | ||
544 | LLMessageVariable& ci = *(iter->second); | ||
545 | s << ci; | ||
546 | } | ||
547 | |||
548 | return s; | ||
549 | } | ||
550 | |||
551 | // LLMessageTemplate functions and friends | ||
552 | |||
553 | std::ostream& operator<<(std::ostream& s, LLMessageTemplate &msg) | ||
554 | { | ||
555 | switch (msg.mFrequency) | ||
556 | { | ||
557 | case MFT_HIGH: | ||
558 | s << "========================================\n" << "Message #" << msg.mMessageNumber << "\n" << msg.mName << " ("; | ||
559 | s << "High"; | ||
560 | break; | ||
561 | case MFT_MEDIUM: | ||
562 | s << "========================================\n" << "Message #"; | ||
563 | s << (msg.mMessageNumber & 0xFF) << "\n" << msg.mName << " ("; | ||
564 | s << "Medium"; | ||
565 | break; | ||
566 | case MFT_LOW: | ||
567 | s << "========================================\n" << "Message #"; | ||
568 | s << (msg.mMessageNumber & 0xFFFF) << "\n" << msg.mName << " ("; | ||
569 | s << "Low"; | ||
570 | break; | ||
571 | default: | ||
572 | s << "Unknown"; | ||
573 | break; | ||
574 | } | ||
575 | |||
576 | if (msg.mTotalSize != -1) | ||
577 | { | ||
578 | s << ", " << msg.mTotalSize << " bytes total)\n"; | ||
579 | } | ||
580 | else | ||
581 | { | ||
582 | s << ")\n"; | ||
583 | } | ||
584 | |||
585 | for (LLMessageTemplate::message_block_map_t::iterator iter = msg.mMemberBlocks.begin(); | ||
586 | iter != msg.mMemberBlocks.end(); iter++) | ||
587 | { | ||
588 | LLMessageBlock* ci = iter->second; | ||
589 | s << *ci; | ||
590 | } | ||
591 | |||
592 | return s; | ||
593 | } | ||
594 | |||
595 | // LLMessageList functions and friends | ||
596 | |||
597 | // Lets support a small subset of regular expressions here | ||
598 | // Syntax is a string made up of: | ||
599 | // a - checks against alphanumeric ([A-Za-z0-9]) | ||
600 | // c - checks against character ([A-Za-z]) | ||
601 | // f - checks against first variable character ([A-Za-z_]) | ||
602 | // v - checks against variable ([A-Za-z0-9_]) | ||
603 | // s - checks against sign of integer ([-0-9]) | ||
604 | // d - checks against integer digit ([0-9]) | ||
605 | // * - repeat last check | ||
606 | |||
607 | // checks 'a' | ||
608 | BOOL b_return_alphanumeric_ok(char c) | ||
609 | { | ||
610 | if ( ( (c < 'A') | ||
611 | ||(c > 'Z')) | ||
612 | &&( (c < 'a') | ||
613 | ||(c > 'z')) | ||
614 | &&( (c < '0') | ||
615 | ||(c > '9'))) | ||
616 | { | ||
617 | return FALSE; | ||
618 | } | ||
619 | return TRUE; | ||
620 | } | ||
621 | |||
622 | // checks 'c' | ||
623 | BOOL b_return_character_ok(char c) | ||
624 | { | ||
625 | if ( ( (c < 'A') | ||
626 | ||(c > 'Z')) | ||
627 | &&( (c < 'a') | ||
628 | ||(c > 'z'))) | ||
629 | { | ||
630 | return FALSE; | ||
631 | } | ||
632 | return TRUE; | ||
633 | } | ||
634 | |||
635 | // checks 'f' | ||
636 | BOOL b_return_first_variable_ok(char c) | ||
637 | { | ||
638 | if ( ( (c < 'A') | ||
639 | ||(c > 'Z')) | ||
640 | &&( (c < 'a') | ||
641 | ||(c > 'z')) | ||
642 | &&(c != '_')) | ||
643 | { | ||
644 | return FALSE; | ||
645 | } | ||
646 | return TRUE; | ||
647 | } | ||
648 | |||
649 | // checks 'v' | ||
650 | BOOL b_return_variable_ok(char c) | ||
651 | { | ||
652 | if ( ( (c < 'A') | ||
653 | ||(c > 'Z')) | ||
654 | &&( (c < 'a') | ||
655 | ||(c > 'z')) | ||
656 | &&( (c < '0') | ||
657 | ||(c > '9')) | ||
658 | &&(c != '_')) | ||
659 | { | ||
660 | return FALSE; | ||
661 | } | ||
662 | return TRUE; | ||
663 | } | ||
664 | |||
665 | // checks 's' | ||
666 | BOOL b_return_signed_integer_ok(char c) | ||
667 | { | ||
668 | if ( ( (c < '0') | ||
669 | ||(c > '9')) | ||
670 | &&(c != '-')) | ||
671 | { | ||
672 | return FALSE; | ||
673 | } | ||
674 | return TRUE; | ||
675 | } | ||
676 | |||
677 | // checks 'd' | ||
678 | BOOL b_return_integer_ok(char c) | ||
679 | { | ||
680 | if ( (c < '0') | ||
681 | ||(c > '9')) | ||
682 | { | ||
683 | return FALSE; | ||
684 | } | ||
685 | return TRUE; | ||
686 | } | ||
687 | |||
688 | BOOL (*gParseCheckCharacters[])(char c) = | ||
689 | { | ||
690 | b_return_alphanumeric_ok, | ||
691 | b_return_character_ok, | ||
692 | b_return_first_variable_ok, | ||
693 | b_return_variable_ok, | ||
694 | b_return_signed_integer_ok, | ||
695 | b_return_integer_ok | ||
696 | }; | ||
697 | |||
698 | S32 get_checker_number(char checker) | ||
699 | { | ||
700 | switch(checker) | ||
701 | { | ||
702 | case 'a': | ||
703 | return 0; | ||
704 | case 'c': | ||
705 | return 1; | ||
706 | case 'f': | ||
707 | return 2; | ||
708 | case 'v': | ||
709 | return 3; | ||
710 | case 's': | ||
711 | return 4; | ||
712 | case 'd': | ||
713 | return 5; | ||
714 | case '*': | ||
715 | return 9999; | ||
716 | default: | ||
717 | return -1; | ||
718 | } | ||
719 | } | ||
720 | |||
721 | // check token based on passed simplified regular expression | ||
722 | BOOL b_check_token(char *token, char *regexp) | ||
723 | { | ||
724 | S32 tptr, rptr = 0; | ||
725 | S32 current_checker, next_checker = 0; | ||
726 | |||
727 | current_checker = get_checker_number(regexp[rptr++]); | ||
728 | |||
729 | if (current_checker == -1) | ||
730 | { | ||
731 | llerrs << "Invalid regular expression value!" << llendl; | ||
732 | return FALSE; | ||
733 | } | ||
734 | |||
735 | if (current_checker == 9999) | ||
736 | { | ||
737 | llerrs << "Regular expression can't start with *!" << llendl; | ||
738 | return FALSE; | ||
739 | } | ||
740 | |||
741 | for (tptr = 0; token[tptr]; tptr++) | ||
742 | { | ||
743 | if (current_checker == -1) | ||
744 | { | ||
745 | llerrs << "Input exceeds regular expression!\nDid you forget a *?" << llendl; | ||
746 | return FALSE; | ||
747 | } | ||
748 | |||
749 | if (!gParseCheckCharacters[current_checker](token[tptr])) | ||
750 | { | ||
751 | return FALSE; | ||
752 | } | ||
753 | if (next_checker != 9999) | ||
754 | { | ||
755 | next_checker = get_checker_number(regexp[rptr++]); | ||
756 | if (next_checker != 9999) | ||
757 | { | ||
758 | current_checker = next_checker; | ||
759 | } | ||
760 | } | ||
761 | } | ||
762 | return TRUE; | ||
763 | } | ||
764 | |||
765 | // C variable can be made up of upper or lower case letters, underscores, or numbers, but can't start with a number | ||
766 | BOOL b_variable_ok(char *token) | ||
767 | { | ||
768 | if (!b_check_token(token, "fv*")) | ||
769 | { | ||
770 | llerrs << "Token '" << token << "' isn't a variable!" << llendl; | ||
771 | return FALSE; | ||
772 | } | ||
773 | return TRUE; | ||
774 | } | ||
775 | |||
776 | // An integer is made up of the digits 0-9 and may be preceded by a '-' | ||
777 | BOOL b_integer_ok(char *token) | ||
778 | { | ||
779 | if (!b_check_token(token, "sd*")) | ||
780 | { | ||
781 | llerrs << "Token isn't an integer!" << llendl; | ||
782 | return FALSE; | ||
783 | } | ||
784 | return TRUE; | ||
785 | } | ||
786 | |||
787 | // An integer is made up of the digits 0-9 | ||
788 | BOOL b_positive_integer_ok(char *token) | ||
789 | { | ||
790 | if (!b_check_token(token, "d*")) | ||
791 | { | ||
792 | llerrs << "Token isn't an integer!" << llendl; | ||
793 | return FALSE; | ||
794 | } | ||
795 | return TRUE; | ||
796 | } | ||
797 | |||
798 | void LLMessageSystem::init() | ||
799 | { | ||
800 | // initialize member variables | ||
801 | mVerboseLog = FALSE; | ||
802 | |||
803 | mbError = FALSE; | ||
804 | mErrorCode = 0; | ||
805 | mIncomingCompressedSize = 0; | ||
806 | mSendReliable = FALSE; | ||
807 | |||
808 | mbSBuilt = FALSE; | ||
809 | mbSClear = TRUE; | ||
810 | |||
811 | mUnackedListDepth = 0; | ||
812 | mUnackedListSize = 0; | ||
813 | mDSMaxListDepth = 0; | ||
814 | |||
815 | mCurrentRMessageData = NULL; | ||
816 | mCurrentRMessageTemplate = NULL; | ||
817 | |||
818 | mCurrentSMessageData = NULL; | ||
819 | mCurrentSMessageTemplate = NULL; | ||
820 | mCurrentSMessageName = NULL; | ||
821 | |||
822 | mCurrentRecvPacketID = 0; | ||
823 | |||
824 | mNumberHighFreqMessages = 0; | ||
825 | mNumberMediumFreqMessages = 0; | ||
826 | mNumberLowFreqMessages = 0; | ||
827 | mPacketsIn = mPacketsOut = 0; | ||
828 | mBytesIn = mBytesOut = 0; | ||
829 | mCompressedPacketsIn = mCompressedPacketsOut = 0; | ||
830 | mReliablePacketsIn = mReliablePacketsOut = 0; | ||
831 | |||
832 | mCompressedBytesIn = 0; | ||
833 | mCompressedBytesOut = 0; | ||
834 | mUncompressedBytesIn = 0; | ||
835 | mUncompressedBytesOut = 0; | ||
836 | mTotalBytesIn = 0; | ||
837 | mTotalBytesOut = 0; | ||
838 | |||
839 | mDroppedPackets = 0; // total dropped packets in | ||
840 | mResentPackets = 0; // total resent packets out | ||
841 | mFailedResendPackets = 0; // total resend failure packets out | ||
842 | mOffCircuitPackets = 0; // total # of off-circuit packets rejected | ||
843 | mInvalidOnCircuitPackets = 0; // total # of on-circuit packets rejected | ||
844 | |||
845 | mOurCircuitCode = 0; | ||
846 | |||
847 | mMessageFileChecksum = 0; | ||
848 | mMessageFileVersionNumber = 0.f; | ||
849 | } | ||
850 | |||
851 | LLMessageSystem::LLMessageSystem() | ||
852 | { | ||
853 | init(); | ||
854 | |||
855 | mSystemVersionMajor = 0; | ||
856 | mSystemVersionMinor = 0; | ||
857 | mSystemVersionPatch = 0; | ||
858 | mSystemVersionServer = 0; | ||
859 | mVersionFlags = 0x0; | ||
860 | |||
861 | // default to not accepting packets from not alive circuits | ||
862 | mbProtected = TRUE; | ||
863 | |||
864 | mSendPacketFailureCount = 0; | ||
865 | mCircuitPrintFreq = 0.f; // seconds | ||
866 | |||
867 | // initialize various bits of net info | ||
868 | mSocket = 0; | ||
869 | mPort = 0; | ||
870 | |||
871 | mPollInfop = NULL; | ||
872 | |||
873 | mResendDumpTime = 0; | ||
874 | mMessageCountTime = 0; | ||
875 | mCircuitPrintTime = 0; | ||
876 | mCurrentMessageTimeSeconds = 0; | ||
877 | |||
878 | // Constants for dumping output based on message processing time/count | ||
879 | mNumMessageCounts = 0; | ||
880 | mMaxMessageCounts = 0; // >= 0 means dump warnings | ||
881 | mMaxMessageTime = 0.f; | ||
882 | |||
883 | mTrueReceiveSize = 0; | ||
884 | |||
885 | // Error if checking this state, subclass methods which aren't implemented are delegated | ||
886 | // to properly constructed message system. | ||
887 | mbError = TRUE; | ||
888 | } | ||
889 | |||
890 | // Read file and build message templates | ||
891 | LLMessageSystem::LLMessageSystem(const char *filename, U32 port, | ||
892 | S32 version_major, | ||
893 | S32 version_minor, | ||
894 | S32 version_patch) | ||
895 | { | ||
896 | init(); | ||
897 | |||
898 | mSystemVersionMajor = version_major; | ||
899 | mSystemVersionMinor = version_minor; | ||
900 | mSystemVersionPatch = version_patch; | ||
901 | mSystemVersionServer = 0; | ||
902 | mVersionFlags = 0x0; | ||
903 | |||
904 | // default to not accepting packets from not alive circuits | ||
905 | mbProtected = TRUE; | ||
906 | |||
907 | mSendPacketFailureCount = 0; | ||
908 | |||
909 | mCircuitPrintFreq = 60.f; // seconds | ||
910 | |||
911 | loadTemplateFile(filename); | ||
912 | |||
913 | // initialize various bits of net info | ||
914 | mSocket = 0; | ||
915 | mPort = port; | ||
916 | |||
917 | S32 error = start_net(mSocket, mPort); | ||
918 | if (error != 0) | ||
919 | { | ||
920 | mbError = TRUE; | ||
921 | mErrorCode = error; | ||
922 | } | ||
923 | //llinfos << << "*** port: " << mPort << llendl; | ||
924 | |||
925 | // | ||
926 | // Create the data structure that we can poll on | ||
927 | // | ||
928 | if (!gAPRPoolp) | ||
929 | { | ||
930 | llerrs << "No APR pool before message system initialization!" << llendl; | ||
931 | ll_init_apr(); | ||
932 | } | ||
933 | apr_socket_t *aprSocketp = NULL; | ||
934 | apr_os_sock_put(&aprSocketp, (apr_os_sock_t*)&mSocket, gAPRPoolp); | ||
935 | |||
936 | mPollInfop = new LLMessagePollInfo; | ||
937 | mPollInfop->mAPRSocketp = aprSocketp; | ||
938 | mPollInfop->mPollFD.p = gAPRPoolp; | ||
939 | mPollInfop->mPollFD.desc_type = APR_POLL_SOCKET; | ||
940 | mPollInfop->mPollFD.reqevents = APR_POLLIN; | ||
941 | mPollInfop->mPollFD.rtnevents = 0; | ||
942 | mPollInfop->mPollFD.desc.s = aprSocketp; | ||
943 | mPollInfop->mPollFD.client_data = NULL; | ||
944 | |||
945 | F64 mt_sec = getMessageTimeSeconds(); | ||
946 | mResendDumpTime = mt_sec; | ||
947 | mMessageCountTime = mt_sec; | ||
948 | mCircuitPrintTime = mt_sec; | ||
949 | mCurrentMessageTimeSeconds = mt_sec; | ||
950 | |||
951 | // Constants for dumping output based on message processing time/count | ||
952 | mNumMessageCounts = 0; | ||
953 | mMaxMessageCounts = 200; // >= 0 means dump warnings | ||
954 | mMaxMessageTime = 1.f; | ||
955 | |||
956 | mTrueReceiveSize = 0; | ||
957 | } | ||
958 | |||
959 | // Read file and build message templates | ||
960 | void LLMessageSystem::loadTemplateFile(const char* filename) | ||
961 | { | ||
962 | if(!filename) | ||
963 | { | ||
964 | llerrs << "No template filename specified" << llendl; | ||
965 | } | ||
966 | |||
967 | char token[MAX_MESSAGE_INTERNAL_NAME_SIZE]; /* Flawfinder: ignore */ | ||
968 | |||
969 | // state variables | ||
970 | BOOL b_template_start = TRUE; | ||
971 | BOOL b_template_end = FALSE; | ||
972 | BOOL b_template = FALSE; | ||
973 | BOOL b_block_start = FALSE; | ||
974 | BOOL b_block_end = FALSE; | ||
975 | BOOL b_block = FALSE; | ||
976 | BOOL b_variable_start = FALSE; | ||
977 | BOOL b_variable_end = FALSE; | ||
978 | BOOL b_variable = FALSE; | ||
979 | //BOOL b_in_comment_block = FALSE; // not yet used | ||
980 | |||
981 | // working temp variables | ||
982 | LLMessageTemplate *templatep = NULL; | ||
983 | char template_name[MAX_MESSAGE_INTERNAL_NAME_SIZE]; /* Flawfinder: ignore */ | ||
984 | |||
985 | LLMessageBlock *blockp = NULL; | ||
986 | char block_name[MAX_MESSAGE_INTERNAL_NAME_SIZE]; /* Flawfinder: ignore */ | ||
987 | |||
988 | LLMessageVariable var; | ||
989 | char var_name[MAX_MESSAGE_INTERNAL_NAME_SIZE]; /* Flawfinder: ignore */ | ||
990 | char formatString[MAX_MESSAGE_INTERNAL_NAME_SIZE]; | ||
991 | |||
992 | FILE* messagefilep = NULL; | ||
993 | mMessageFileChecksum = 0; | ||
994 | mMessageFileVersionNumber = 0.f; | ||
995 | S32 checksum_offset = 0; | ||
996 | char* checkp = NULL; | ||
997 | |||
998 | snprintf(formatString, sizeof(formatString), "%%%ds", MAX_MESSAGE_INTERNAL_NAME_SIZE); | ||
999 | messagefilep = LLFile::fopen(filename, "r"); | ||
1000 | if (messagefilep) | ||
1001 | { | ||
1002 | // mName = gMessageStringTable.getString(filename); | ||
1003 | |||
1004 | fseek(messagefilep, 0L, SEEK_SET ); | ||
1005 | while(fscanf(messagefilep, formatString, token) != EOF) | ||
1006 | { | ||
1007 | // skip comments | ||
1008 | if (token[0] == '/') | ||
1009 | { | ||
1010 | // skip to end of line | ||
1011 | while (token[0] != 10) | ||
1012 | fscanf(messagefilep, "%c", token); | ||
1013 | continue; | ||
1014 | } | ||
1015 | |||
1016 | checkp = token; | ||
1017 | |||
1018 | while (*checkp) | ||
1019 | { | ||
1020 | mMessageFileChecksum += ((U32)*checkp++) << checksum_offset; | ||
1021 | checksum_offset = (checksum_offset + 8) % 32; | ||
1022 | } | ||
1023 | |||
1024 | // what are we looking for | ||
1025 | if (!strcmp(token, "{")) | ||
1026 | { | ||
1027 | // is that a legit option? | ||
1028 | if (b_template_start) | ||
1029 | { | ||
1030 | // yup! | ||
1031 | b_template_start = FALSE; | ||
1032 | |||
1033 | // remember that it could be only a signal message, so name is all that it contains | ||
1034 | b_template_end = TRUE; | ||
1035 | |||
1036 | // start working on it! | ||
1037 | b_template = TRUE; | ||
1038 | } | ||
1039 | else if (b_block_start) | ||
1040 | { | ||
1041 | // yup! | ||
1042 | b_block_start = FALSE; | ||
1043 | b_template_end = FALSE; | ||
1044 | |||
1045 | // start working on it! | ||
1046 | b_block = TRUE; | ||
1047 | } | ||
1048 | else if (b_variable_start) | ||
1049 | { | ||
1050 | // yup! | ||
1051 | b_variable_start = FALSE; | ||
1052 | b_block_end = FALSE; | ||
1053 | |||
1054 | // start working on it! | ||
1055 | b_variable = TRUE; | ||
1056 | } | ||
1057 | else | ||
1058 | { | ||
1059 | llerrs << "Detcted unexpected token '" << token | ||
1060 | << "' while parsing template." << llendl; | ||
1061 | mbError = TRUE; | ||
1062 | fclose(messagefilep); | ||
1063 | return; | ||
1064 | } | ||
1065 | } | ||
1066 | |||
1067 | if (!strcmp(token, "}")) | ||
1068 | { | ||
1069 | // is that a legit option? | ||
1070 | if (b_template_end) | ||
1071 | { | ||
1072 | // yup! | ||
1073 | b_template_end = FALSE; | ||
1074 | b_template = FALSE; | ||
1075 | b_block_start = FALSE; | ||
1076 | |||
1077 | // add data! | ||
1078 | // we've gotten a complete variable! hooray! | ||
1079 | // add it! | ||
1080 | addTemplate(templatep); | ||
1081 | |||
1082 | //llinfos << "Read template: "templatep->mNametemp_str | ||
1083 | // << llendl; | ||
1084 | |||
1085 | // look for next one! | ||
1086 | b_template_start = TRUE; | ||
1087 | } | ||
1088 | else if (b_block_end) | ||
1089 | { | ||
1090 | // yup! | ||
1091 | b_block_end = FALSE; | ||
1092 | b_variable_start = FALSE; | ||
1093 | |||
1094 | // add data! | ||
1095 | // we've gotten a complete variable! hooray! | ||
1096 | // add it to template | ||
1097 | |||
1098 | templatep->addBlock(blockp); | ||
1099 | |||
1100 | // start working on it! | ||
1101 | b_template_end = TRUE; | ||
1102 | b_block_start = TRUE; | ||
1103 | } | ||
1104 | else if (b_variable_end) | ||
1105 | { | ||
1106 | // yup! | ||
1107 | b_variable_end = FALSE; | ||
1108 | |||
1109 | // add data! | ||
1110 | // we've gotten a complete variable! hooray! | ||
1111 | // add it to block | ||
1112 | blockp->addVariable(var.getName(), var.getType(), var.getSize()); | ||
1113 | |||
1114 | // start working on it! | ||
1115 | b_variable_start = TRUE; | ||
1116 | b_block_end = TRUE; | ||
1117 | } | ||
1118 | else | ||
1119 | { | ||
1120 | llerrs << "Detcted unexpected token '" << token | ||
1121 | << "' while parsing template." << llendl; | ||
1122 | mbError = TRUE; | ||
1123 | fclose(messagefilep); | ||
1124 | return; | ||
1125 | } | ||
1126 | } | ||
1127 | |||
1128 | // now, are we looking to start a template? | ||
1129 | if (b_template) | ||
1130 | { | ||
1131 | |||
1132 | b_template = FALSE; | ||
1133 | |||
1134 | // name first | ||
1135 | if (fscanf(messagefilep, formatString, template_name) == EOF) | ||
1136 | { | ||
1137 | // oops, file ended | ||
1138 | llerrs << "Expected message template name, but file ended" | ||
1139 | << llendl; | ||
1140 | mbError = TRUE; | ||
1141 | fclose(messagefilep); | ||
1142 | return; | ||
1143 | } | ||
1144 | |||
1145 | // debugging to help figure out busted templates | ||
1146 | //llinfos << template_name << llendl; | ||
1147 | |||
1148 | // is name a legit C variable name | ||
1149 | if (!b_variable_ok(template_name)) | ||
1150 | { | ||
1151 | // nope! | ||
1152 | llerrs << "Not legal message template name: " | ||
1153 | << template_name << llendl; | ||
1154 | mbError = TRUE; | ||
1155 | fclose(messagefilep); | ||
1156 | return; | ||
1157 | } | ||
1158 | |||
1159 | checkp = template_name; | ||
1160 | while (*checkp) | ||
1161 | { | ||
1162 | mMessageFileChecksum += ((U32)*checkp++) << checksum_offset; | ||
1163 | checksum_offset = (checksum_offset + 8) % 32; | ||
1164 | } | ||
1165 | |||
1166 | // ok, now get Frequency ("High", "Medium", or "Low") | ||
1167 | if (fscanf(messagefilep, formatString, token) == EOF) | ||
1168 | { | ||
1169 | // oops, file ended | ||
1170 | llerrs << "Expected message template frequency, found EOF." | ||
1171 | << llendl; | ||
1172 | mbError = TRUE; | ||
1173 | fclose(messagefilep); | ||
1174 | return; | ||
1175 | } | ||
1176 | |||
1177 | checkp = token; | ||
1178 | while (*checkp) | ||
1179 | { | ||
1180 | mMessageFileChecksum += ((U32)*checkp++) << checksum_offset; | ||
1181 | checksum_offset = (checksum_offset + 8) % 32; | ||
1182 | } | ||
1183 | |||
1184 | // which one is it? | ||
1185 | if (!strcmp(token, "High")) | ||
1186 | { | ||
1187 | if (++mNumberHighFreqMessages == 255) | ||
1188 | { | ||
1189 | // oops, too many High Frequency messages!! | ||
1190 | llerrs << "Message " << template_name | ||
1191 | << " exceeded 254 High frequency messages!" | ||
1192 | << llendl; | ||
1193 | mbError = TRUE; | ||
1194 | fclose(messagefilep); | ||
1195 | return; | ||
1196 | } | ||
1197 | // ok, we can create a template! | ||
1198 | // message number is just mNumberHighFreqMessages | ||
1199 | templatep = new LLMessageTemplate(template_name, mNumberHighFreqMessages, MFT_HIGH); | ||
1200 | //lldebugs << "Template " << template_name << " # " | ||
1201 | // << std::hex << mNumberHighFreqMessages | ||
1202 | // << std::dec << " high" | ||
1203 | // << llendl; | ||
1204 | } | ||
1205 | else if (!strcmp(token, "Medium")) | ||
1206 | { | ||
1207 | if (++mNumberMediumFreqMessages == 255) | ||
1208 | { | ||
1209 | // oops, too many Medium Frequency messages!! | ||
1210 | llerrs << "Message " << template_name | ||
1211 | << " exceeded 254 Medium frequency messages!" | ||
1212 | << llendl; | ||
1213 | mbError = TRUE; | ||
1214 | fclose(messagefilep); | ||
1215 | return; | ||
1216 | } | ||
1217 | // ok, we can create a template! | ||
1218 | // message number is ((255 << 8) | mNumberMediumFreqMessages) | ||
1219 | templatep = new LLMessageTemplate(template_name, (255 << 8) | mNumberMediumFreqMessages, MFT_MEDIUM); | ||
1220 | //lldebugs << "Template " << template_name << " # " | ||
1221 | // << std::hex << mNumberMediumFreqMessages | ||
1222 | // << std::dec << " medium" | ||
1223 | // << llendl; | ||
1224 | } | ||
1225 | else if (!strcmp(token, "Low")) | ||
1226 | { | ||
1227 | if (++mNumberLowFreqMessages == 65535) | ||
1228 | { | ||
1229 | // oops, too many High Frequency messages!! | ||
1230 | llerrs << "Message " << template_name | ||
1231 | << " exceeded 65534 Low frequency messages!" | ||
1232 | << llendl; | ||
1233 | mbError = TRUE; | ||
1234 | fclose(messagefilep); | ||
1235 | return; | ||
1236 | } | ||
1237 | // ok, we can create a template! | ||
1238 | // message number is ((255 << 24) | (255 << 16) | mNumberLowFreqMessages) | ||
1239 | templatep = new LLMessageTemplate(template_name, (255 << 24) | (255 << 16) | mNumberLowFreqMessages, MFT_LOW); | ||
1240 | //lldebugs << "Template " << template_name << " # " | ||
1241 | // << std::hex << mNumberLowFreqMessages | ||
1242 | // << std::dec << " low" | ||
1243 | // << llendl; | ||
1244 | } | ||
1245 | else if (!strcmp(token, "Fixed")) | ||
1246 | { | ||
1247 | U32 message_num = 0; | ||
1248 | if (fscanf(messagefilep, formatString, token) == EOF) | ||
1249 | { | ||
1250 | // oops, file ended | ||
1251 | llerrs << "Expected message template number (fixed)," | ||
1252 | << " found EOF." << llendl; | ||
1253 | mbError = TRUE; | ||
1254 | fclose(messagefilep); | ||
1255 | return; | ||
1256 | } | ||
1257 | |||
1258 | checkp = token; | ||
1259 | while (*checkp) | ||
1260 | { | ||
1261 | mMessageFileChecksum += ((U32)*checkp++) << checksum_offset; | ||
1262 | checksum_offset = (checksum_offset + 8) % 32; | ||
1263 | } | ||
1264 | |||
1265 | message_num = strtoul(token,NULL,0); | ||
1266 | |||
1267 | // ok, we can create a template! | ||
1268 | // message number is ((255 << 24) | (255 << 16) | mNumberLowFreqMessages) | ||
1269 | templatep = new LLMessageTemplate(template_name, message_num, MFT_LOW); | ||
1270 | } | ||
1271 | else | ||
1272 | { | ||
1273 | // oops, bad frequency line | ||
1274 | llerrs << "Bad frequency! " << token | ||
1275 | << " isn't High, Medium, or Low" << llendl | ||
1276 | mbError = TRUE; | ||
1277 | fclose(messagefilep); | ||
1278 | return; | ||
1279 | } | ||
1280 | |||
1281 | // Now get trust ("Trusted", "NotTrusted") | ||
1282 | if (fscanf(messagefilep, formatString, token) == EOF) | ||
1283 | { | ||
1284 | // File ended | ||
1285 | llerrs << "Expected message template " | ||
1286 | "trust, but file ended." | ||
1287 | << llendl; | ||
1288 | mbError = TRUE; | ||
1289 | fclose(messagefilep); | ||
1290 | return; | ||
1291 | } | ||
1292 | checkp = token; | ||
1293 | while (*checkp) | ||
1294 | { | ||
1295 | mMessageFileChecksum += ((U32) *checkp++) << checksum_offset; | ||
1296 | checksum_offset = (checksum_offset + 8) % 32; | ||
1297 | } | ||
1298 | |||
1299 | if (strcmp(token, "Trusted") == 0) | ||
1300 | { | ||
1301 | templatep->setTrust(MT_TRUST); | ||
1302 | } | ||
1303 | else if (strcmp(token, "NotTrusted") == 0) | ||
1304 | { | ||
1305 | templatep->setTrust(MT_NOTRUST); | ||
1306 | } | ||
1307 | else | ||
1308 | { | ||
1309 | // bad trust token | ||
1310 | llerrs << "bad trust: " << token | ||
1311 | << " isn't Trusted or NotTrusted" | ||
1312 | << llendl; | ||
1313 | mbError = TRUE; | ||
1314 | fclose(messagefilep); | ||
1315 | return; | ||
1316 | } | ||
1317 | |||
1318 | // get encoding | ||
1319 | if (fscanf(messagefilep, formatString, token) == EOF) | ||
1320 | { | ||
1321 | // File ended | ||
1322 | llerrs << "Expected message encoding, but file ended." | ||
1323 | << llendl; | ||
1324 | mbError = TRUE; | ||
1325 | fclose(messagefilep); | ||
1326 | return; | ||
1327 | } | ||
1328 | checkp = token; | ||
1329 | while(*checkp) | ||
1330 | { | ||
1331 | mMessageFileChecksum += ((U32) *checkp++) << checksum_offset; | ||
1332 | checksum_offset = (checksum_offset + 8) % 32; | ||
1333 | } | ||
1334 | |||
1335 | if(0 == strcmp(token, "Unencoded")) | ||
1336 | { | ||
1337 | templatep->setEncoding(ME_UNENCODED); | ||
1338 | } | ||
1339 | else if(0 == strcmp(token, "Zerocoded")) | ||
1340 | { | ||
1341 | templatep->setEncoding(ME_ZEROCODED); | ||
1342 | } | ||
1343 | else | ||
1344 | { | ||
1345 | // bad trust token | ||
1346 | llerrs << "bad encoding: " << token | ||
1347 | << " isn't Unencoded or Zerocoded" << llendl; | ||
1348 | mbError = TRUE; | ||
1349 | fclose(messagefilep); | ||
1350 | return; | ||
1351 | } | ||
1352 | |||
1353 | // ok, now we need to look for a block | ||
1354 | b_block_start = TRUE; | ||
1355 | continue; | ||
1356 | } | ||
1357 | |||
1358 | // now, are we looking to start a template? | ||
1359 | if (b_block) | ||
1360 | { | ||
1361 | b_block = FALSE; | ||
1362 | // ok, need to pull header info | ||
1363 | |||
1364 | // name first | ||
1365 | if (fscanf(messagefilep, formatString, block_name) == EOF) | ||
1366 | { | ||
1367 | // oops, file ended | ||
1368 | llerrs << "Expected block name, but file ended" << llendl; | ||
1369 | mbError = TRUE; | ||
1370 | fclose(messagefilep); | ||
1371 | return; | ||
1372 | } | ||
1373 | |||
1374 | checkp = block_name; | ||
1375 | while (*checkp) | ||
1376 | { | ||
1377 | mMessageFileChecksum += ((U32)*checkp++) << checksum_offset; | ||
1378 | checksum_offset = (checksum_offset + 8) % 32; | ||
1379 | } | ||
1380 | |||
1381 | // is name a legit C variable name | ||
1382 | if (!b_variable_ok(block_name)) | ||
1383 | { | ||
1384 | // nope! | ||
1385 | llerrs << block_name << "is not a legal block name" | ||
1386 | << llendl; | ||
1387 | mbError = TRUE; | ||
1388 | fclose(messagefilep); | ||
1389 | return; | ||
1390 | } | ||
1391 | |||
1392 | // now, block type ("Single", "Multiple", or "Variable") | ||
1393 | if (fscanf(messagefilep, formatString, token) == EOF) | ||
1394 | { | ||
1395 | // oops, file ended | ||
1396 | llerrs << "Expected block type, but file ended." << llendl; | ||
1397 | mbError = TRUE; | ||
1398 | fclose(messagefilep); | ||
1399 | return; | ||
1400 | } | ||
1401 | |||
1402 | checkp = token; | ||
1403 | while (*checkp) | ||
1404 | { | ||
1405 | mMessageFileChecksum += ((U32)*checkp++) << checksum_offset; | ||
1406 | checksum_offset = (checksum_offset + 8) % 32; | ||
1407 | } | ||
1408 | |||
1409 | // which one is it? | ||
1410 | if (!strcmp(token, "Single")) | ||
1411 | { | ||
1412 | // ok, we can create a block | ||
1413 | blockp = new LLMessageBlock(block_name, MBT_SINGLE); | ||
1414 | } | ||
1415 | else if (!strcmp(token, "Multiple")) | ||
1416 | { | ||
1417 | // need to get the number of repeats | ||
1418 | if (fscanf(messagefilep, formatString, token) == EOF) | ||
1419 | { | ||
1420 | // oops, file ended | ||
1421 | llerrs << "Expected block multiple count," | ||
1422 | " but file ended." << llendl; | ||
1423 | mbError = TRUE; | ||
1424 | fclose(messagefilep); | ||
1425 | return; | ||
1426 | } | ||
1427 | |||
1428 | checkp = token; | ||
1429 | while (*checkp) | ||
1430 | { | ||
1431 | mMessageFileChecksum += ((U32)*checkp++) << checksum_offset; | ||
1432 | checksum_offset = (checksum_offset + 8) % 32; | ||
1433 | } | ||
1434 | |||
1435 | // is it a legal integer | ||
1436 | if (!b_positive_integer_ok(token)) | ||
1437 | { | ||
1438 | // nope! | ||
1439 | llerrs << token << "is not a legal integer for" | ||
1440 | " block multiple count" << llendl; | ||
1441 | mbError = TRUE; | ||
1442 | fclose(messagefilep); | ||
1443 | return; | ||
1444 | } | ||
1445 | // ok, we can create a block | ||
1446 | blockp = new LLMessageBlock(block_name, MBT_MULTIPLE, atoi(token)); | ||
1447 | } | ||
1448 | else if (!strcmp(token, "Variable")) | ||
1449 | { | ||
1450 | // ok, we can create a block | ||
1451 | blockp = new LLMessageBlock(block_name, MBT_VARIABLE); | ||
1452 | } | ||
1453 | else | ||
1454 | { | ||
1455 | // oops, bad block type | ||
1456 | llerrs << "Bad block type! " << token | ||
1457 | << " isn't Single, Multiple, or Variable" << llendl; | ||
1458 | mbError = TRUE; | ||
1459 | fclose(messagefilep); | ||
1460 | return; | ||
1461 | } | ||
1462 | // ok, now we need to look for a variable | ||
1463 | b_variable_start = TRUE; | ||
1464 | continue; | ||
1465 | } | ||
1466 | |||
1467 | // now, are we looking to start a template? | ||
1468 | if (b_variable) | ||
1469 | { | ||
1470 | b_variable = FALSE; | ||
1471 | // ok, need to pull header info | ||
1472 | |||
1473 | // name first | ||
1474 | if (fscanf(messagefilep, formatString, var_name) == EOF) | ||
1475 | { | ||
1476 | // oops, file ended | ||
1477 | llerrs << "Expected variable name, but file ended." | ||
1478 | << llendl; | ||
1479 | mbError = TRUE; | ||
1480 | fclose(messagefilep); | ||
1481 | return; | ||
1482 | } | ||
1483 | |||
1484 | checkp = var_name; | ||
1485 | while (*checkp) | ||
1486 | { | ||
1487 | mMessageFileChecksum += ((U32)*checkp++) << checksum_offset; | ||
1488 | checksum_offset = (checksum_offset + 8) % 32; | ||
1489 | } | ||
1490 | |||
1491 | // is name a legit C variable name | ||
1492 | if (!b_variable_ok(var_name)) | ||
1493 | { | ||
1494 | // nope! | ||
1495 | llerrs << var_name << " is not a legal variable name" | ||
1496 | << llendl; | ||
1497 | mbError = TRUE; | ||
1498 | fclose(messagefilep); | ||
1499 | return; | ||
1500 | } | ||
1501 | |||
1502 | // now, variable type ("Fixed" or "Variable") | ||
1503 | if (fscanf(messagefilep, formatString, token) == EOF) | ||
1504 | { | ||
1505 | // oops, file ended | ||
1506 | llerrs << "Expected variable type, but file ended" | ||
1507 | << llendl; | ||
1508 | mbError = TRUE; | ||
1509 | fclose(messagefilep); | ||
1510 | return; | ||
1511 | } | ||
1512 | |||
1513 | checkp = token; | ||
1514 | while (*checkp) | ||
1515 | { | ||
1516 | mMessageFileChecksum += ((U32)*checkp++) << checksum_offset; | ||
1517 | checksum_offset = (checksum_offset + 8) % 32; | ||
1518 | } | ||
1519 | |||
1520 | |||
1521 | // which one is it? | ||
1522 | if (!strcmp(token, "U8")) | ||
1523 | { | ||
1524 | var = LLMessageVariable(var_name, MVT_U8, 1); | ||
1525 | } | ||
1526 | else if (!strcmp(token, "U16")) | ||
1527 | { | ||
1528 | var = LLMessageVariable(var_name, MVT_U16, 2); | ||
1529 | } | ||
1530 | else if (!strcmp(token, "U32")) | ||
1531 | { | ||
1532 | var = LLMessageVariable(var_name, MVT_U32, 4); | ||
1533 | } | ||
1534 | else if (!strcmp(token, "U64")) | ||
1535 | { | ||
1536 | var = LLMessageVariable(var_name, MVT_U64, 8); | ||
1537 | } | ||
1538 | else if (!strcmp(token, "S8")) | ||
1539 | { | ||
1540 | var = LLMessageVariable(var_name, MVT_S8, 1); | ||
1541 | } | ||
1542 | else if (!strcmp(token, "S16")) | ||
1543 | { | ||
1544 | var = LLMessageVariable(var_name, MVT_S16, 2); | ||
1545 | } | ||
1546 | else if (!strcmp(token, "S32")) | ||
1547 | { | ||
1548 | var = LLMessageVariable(var_name, MVT_S32, 4); | ||
1549 | } | ||
1550 | else if (!strcmp(token, "S64")) | ||
1551 | { | ||
1552 | var = LLMessageVariable(var_name, MVT_S64, 8); | ||
1553 | } | ||
1554 | else if (!strcmp(token, "F32")) | ||
1555 | { | ||
1556 | var = LLMessageVariable(var_name, MVT_F32, 4); | ||
1557 | } | ||
1558 | else if (!strcmp(token, "F64")) | ||
1559 | { | ||
1560 | var = LLMessageVariable(var_name, MVT_F64, 8); | ||
1561 | } | ||
1562 | else if (!strcmp(token, "LLVector3")) | ||
1563 | { | ||
1564 | var = LLMessageVariable(var_name, MVT_LLVector3, 12); | ||
1565 | } | ||
1566 | else if (!strcmp(token, "LLVector3d")) | ||
1567 | { | ||
1568 | var = LLMessageVariable(var_name, MVT_LLVector3d, 24); | ||
1569 | } | ||
1570 | else if (!strcmp(token, "LLVector4")) | ||
1571 | { | ||
1572 | var = LLMessageVariable(var_name, MVT_LLVector4, 16); | ||
1573 | } | ||
1574 | else if (!strcmp(token, "LLQuaternion")) | ||
1575 | { | ||
1576 | var = LLMessageVariable(var_name, MVT_LLQuaternion, 12); | ||
1577 | } | ||
1578 | else if (!strcmp(token, "LLUUID")) | ||
1579 | { | ||
1580 | var = LLMessageVariable(var_name, MVT_LLUUID, 16); | ||
1581 | } | ||
1582 | else if (!strcmp(token, "BOOL")) | ||
1583 | { | ||
1584 | var = LLMessageVariable(var_name, MVT_BOOL, 1); | ||
1585 | } | ||
1586 | else if (!strcmp(token, "IPADDR")) | ||
1587 | { | ||
1588 | var = LLMessageVariable(var_name, MVT_IP_ADDR, 4); | ||
1589 | } | ||
1590 | else if (!strcmp(token, "IPPORT")) | ||
1591 | { | ||
1592 | var = LLMessageVariable(var_name, MVT_IP_PORT, 2); | ||
1593 | } | ||
1594 | else if (!strcmp(token, "Fixed")) | ||
1595 | { | ||
1596 | // need to get the variable size | ||
1597 | if (fscanf(messagefilep, formatString, token) == EOF) | ||
1598 | { | ||
1599 | // oops, file ended | ||
1600 | llerrs << "Expected variable size, but file ended" | ||
1601 | << llendl; | ||
1602 | mbError = TRUE; | ||
1603 | fclose(messagefilep); | ||
1604 | return; | ||
1605 | } | ||
1606 | |||
1607 | checkp = token; | ||
1608 | while (*checkp) | ||
1609 | { | ||
1610 | mMessageFileChecksum += ((U32)*checkp++) << checksum_offset; | ||
1611 | checksum_offset = (checksum_offset + 8) % 32; | ||
1612 | } | ||
1613 | |||
1614 | // is it a legal integer | ||
1615 | if (!b_positive_integer_ok(token)) | ||
1616 | { | ||
1617 | // nope! | ||
1618 | llerrs << token << " is not a legal integer for" | ||
1619 | " variable size" << llendl; | ||
1620 | mbError = TRUE; | ||
1621 | fclose(messagefilep); | ||
1622 | return; | ||
1623 | } | ||
1624 | // ok, we can create a block | ||
1625 | var = LLMessageVariable(var_name, MVT_FIXED, atoi(token)); | ||
1626 | } | ||
1627 | else if (!strcmp(token, "Variable")) | ||
1628 | { | ||
1629 | // need to get the variable size | ||
1630 | if (fscanf(messagefilep, formatString, token) == EOF) | ||
1631 | { | ||
1632 | // oops, file ended | ||
1633 | llerrs << "Expected variable size, but file ended" | ||
1634 | << llendl; | ||
1635 | mbError = TRUE; | ||
1636 | fclose(messagefilep); | ||
1637 | return; | ||
1638 | } | ||
1639 | |||
1640 | checkp = token; | ||
1641 | while (*checkp) | ||
1642 | { | ||
1643 | mMessageFileChecksum += ((U32)*checkp++) << checksum_offset; | ||
1644 | checksum_offset = (checksum_offset + 8) % 32; | ||
1645 | } | ||
1646 | |||
1647 | // is it a legal integer | ||
1648 | if (!b_positive_integer_ok(token)) | ||
1649 | { | ||
1650 | // nope! | ||
1651 | llerrs << token << "is not a legal integer" | ||
1652 | " for variable size" << llendl; | ||
1653 | mbError = TRUE; | ||
1654 | fclose(messagefilep); | ||
1655 | return; | ||
1656 | } | ||
1657 | // ok, we can create a block | ||
1658 | var = LLMessageVariable(var_name, MVT_VARIABLE, atoi(token)); | ||
1659 | } | ||
1660 | else | ||
1661 | { | ||
1662 | // oops, bad variable type | ||
1663 | llerrs << "Bad variable type! " << token | ||
1664 | << " isn't Fixed or Variable" << llendl; | ||
1665 | mbError = TRUE; | ||
1666 | fclose(messagefilep); | ||
1667 | return; | ||
1668 | } | ||
1669 | |||
1670 | // we got us a variable! | ||
1671 | b_variable_end = TRUE; | ||
1672 | continue; | ||
1673 | } | ||
1674 | |||
1675 | // do we have a version number stuck in the file? | ||
1676 | if (!strcmp(token, "version")) | ||
1677 | { | ||
1678 | // version number | ||
1679 | if (fscanf(messagefilep, formatString, token) == EOF) | ||
1680 | { | ||
1681 | // oops, file ended | ||
1682 | llerrs << "Expected version number, but file ended" | ||
1683 | << llendl; | ||
1684 | mbError = TRUE; | ||
1685 | fclose(messagefilep); | ||
1686 | return; | ||
1687 | } | ||
1688 | |||
1689 | checkp = token; | ||
1690 | while (*checkp) | ||
1691 | { | ||
1692 | mMessageFileChecksum += ((U32)*checkp++) << checksum_offset; | ||
1693 | checksum_offset = (checksum_offset + 8) % 32; | ||
1694 | } | ||
1695 | |||
1696 | mMessageFileVersionNumber = (F32)atof(token); | ||
1697 | |||
1698 | // llinfos << "### Message template version " << mMessageFileVersionNumber << " ###" << llendl; | ||
1699 | continue; | ||
1700 | } | ||
1701 | } | ||
1702 | |||
1703 | llinfos << "Message template checksum = " << std::hex << mMessageFileChecksum << std::dec << llendl; | ||
1704 | } | ||
1705 | else | ||
1706 | { | ||
1707 | llwarns << "Failed to open template: " << filename << llendl; | ||
1708 | mbError = TRUE; | ||
1709 | return; | ||
1710 | } | ||
1711 | fclose(messagefilep); | ||
1712 | } | ||
1713 | |||
1714 | |||
1715 | LLMessageSystem::~LLMessageSystem() | ||
1716 | { | ||
1717 | mMessageTemplates.clear(); // don't delete templates. | ||
1718 | for_each(mMessageNumbers.begin(), mMessageNumbers.end(), DeletePairedPointer()); | ||
1719 | mMessageNumbers.clear(); | ||
1720 | |||
1721 | if (!mbError) | ||
1722 | { | ||
1723 | end_net(); | ||
1724 | } | ||
1725 | |||
1726 | delete mCurrentRMessageData; | ||
1727 | mCurrentRMessageData = NULL; | ||
1728 | |||
1729 | delete mCurrentSMessageData; | ||
1730 | mCurrentSMessageData = NULL; | ||
1731 | |||
1732 | delete mPollInfop; | ||
1733 | mPollInfop = NULL; | ||
1734 | } | ||
1735 | |||
1736 | void LLMessageSystem::clearReceiveState() | ||
1737 | { | ||
1738 | mReceiveSize = -1; | ||
1739 | mCurrentRecvPacketID = 0; | ||
1740 | mCurrentRMessageTemplate = NULL; | ||
1741 | delete mCurrentRMessageData; | ||
1742 | mCurrentRMessageData = NULL; | ||
1743 | mIncomingCompressedSize = 0; | ||
1744 | mLastSender.invalidate(); | ||
1745 | } | ||
1746 | |||
1747 | |||
1748 | BOOL LLMessageSystem::poll(F32 seconds) | ||
1749 | { | ||
1750 | S32 num_socks; | ||
1751 | apr_status_t status; | ||
1752 | status = apr_poll(&(mPollInfop->mPollFD), 1, &num_socks,(U64)(seconds*1000000.f)); | ||
1753 | if (status != APR_TIMEUP) | ||
1754 | { | ||
1755 | ll_apr_warn_status(status); | ||
1756 | } | ||
1757 | if (num_socks) | ||
1758 | { | ||
1759 | return TRUE; | ||
1760 | } | ||
1761 | else | ||
1762 | { | ||
1763 | return FALSE; | ||
1764 | } | ||
1765 | } | ||
1766 | |||
1767 | |||
1768 | // Returns TRUE if a valid, on-circuit message has been received. | ||
1769 | BOOL LLMessageSystem::checkMessages( S64 frame_count ) | ||
1770 | { | ||
1771 | BOOL valid_packet = FALSE; | ||
1772 | |||
1773 | LLTransferTargetVFile::updateQueue(); | ||
1774 | |||
1775 | if (!mNumMessageCounts) | ||
1776 | { | ||
1777 | // This is the first message being handled after a resetReceiveCounts, we must be starting | ||
1778 | // the message processing loop. Reset the timers. | ||
1779 | mCurrentMessageTimeSeconds = totalTime() * SEC_PER_USEC; | ||
1780 | mMessageCountTime = getMessageTimeSeconds(); | ||
1781 | } | ||
1782 | |||
1783 | // loop until either no packets or a valid packet | ||
1784 | // i.e., burn through packets from unregistered circuits | ||
1785 | do | ||
1786 | { | ||
1787 | clearReceiveState(); | ||
1788 | |||
1789 | BOOL recv_reliable = FALSE; | ||
1790 | BOOL recv_resent = FALSE; | ||
1791 | S32 acks = 0; | ||
1792 | S32 true_rcv_size = 0; | ||
1793 | |||
1794 | U8* buffer = mTrueReceiveBuffer; | ||
1795 | |||
1796 | mTrueReceiveSize = mPacketRing.receivePacket(mSocket, (char *)mTrueReceiveBuffer); | ||
1797 | // If you want to dump all received packets into SecondLife.log, uncomment this | ||
1798 | //dumpPacketToLog(); | ||
1799 | |||
1800 | mReceiveSize = mTrueReceiveSize; | ||
1801 | mLastSender = mPacketRing.getLastSender(); | ||
1802 | |||
1803 | if (mReceiveSize < (S32) LL_MINIMUM_VALID_PACKET_SIZE) | ||
1804 | { | ||
1805 | // A receive size of zero is OK, that means that there are no more packets available. | ||
1806 | // Ones that are non-zero but below the minimum packet size are worrisome. | ||
1807 | if (mReceiveSize > 0) | ||
1808 | { | ||
1809 | llwarns << "Invalid (too short) packet discarded " << mReceiveSize << llendl; | ||
1810 | callExceptionFunc(MX_PACKET_TOO_SHORT); | ||
1811 | } | ||
1812 | // no data in packet receive buffer | ||
1813 | valid_packet = FALSE; | ||
1814 | } | ||
1815 | else | ||
1816 | { | ||
1817 | LLHost host; | ||
1818 | LLCircuitData *cdp; | ||
1819 | |||
1820 | // note if packet acks are appended. | ||
1821 | if(buffer[0] & LL_ACK_FLAG) | ||
1822 | { | ||
1823 | acks += buffer[--mReceiveSize]; | ||
1824 | true_rcv_size = mReceiveSize; | ||
1825 | mReceiveSize -= acks * sizeof(TPACKETID); | ||
1826 | } | ||
1827 | |||
1828 | // process the message as normal | ||
1829 | |||
1830 | mIncomingCompressedSize = zeroCodeExpand(&buffer,&mReceiveSize); | ||
1831 | mCurrentRecvPacketID = buffer[1] + ((buffer[0] & 0x0f ) * 256); | ||
1832 | if (sizeof(TPACKETID) == 4) | ||
1833 | { | ||
1834 | mCurrentRecvPacketID *= 256; | ||
1835 | mCurrentRecvPacketID += buffer[2]; | ||
1836 | mCurrentRecvPacketID *= 256; | ||
1837 | mCurrentRecvPacketID += buffer[3]; | ||
1838 | } | ||
1839 | |||
1840 | host = getSender(); | ||
1841 | //llinfos << host << ":" << mCurrentRecvPacketID << llendl; | ||
1842 | |||
1843 | // For testing the weird case we're having in the office where the first few packets | ||
1844 | // on a connection get dropped | ||
1845 | //if ((mCurrentRecvPacketID < 8) && !(buffer[0] & LL_RESENT_FLAG)) | ||
1846 | //{ | ||
1847 | // llinfos << "Evil! Dropping " << mCurrentRecvPacketID << " from " << host << " for fun!" << llendl; | ||
1848 | // continue; | ||
1849 | //} | ||
1850 | |||
1851 | cdp = mCircuitInfo.findCircuit(host); | ||
1852 | if (!cdp) | ||
1853 | { | ||
1854 | // This packet comes from a circuit we don't know about. | ||
1855 | |||
1856 | // Are we rejecting off-circuit packets? | ||
1857 | if (mbProtected) | ||
1858 | { | ||
1859 | // cdp is already NULL, so we don't need to unset it. | ||
1860 | } | ||
1861 | else | ||
1862 | { | ||
1863 | // nope, open the new circuit | ||
1864 | cdp = mCircuitInfo.addCircuitData(host, mCurrentRecvPacketID); | ||
1865 | |||
1866 | // I added this - I think it's correct - DJS | ||
1867 | // reset packet in ID | ||
1868 | cdp->setPacketInID(mCurrentRecvPacketID); | ||
1869 | |||
1870 | // And claim the packet is on the circuit we just added. | ||
1871 | } | ||
1872 | } | ||
1873 | else | ||
1874 | { | ||
1875 | // this is an old circuit. . . is it still alive? | ||
1876 | if (!cdp->isAlive()) | ||
1877 | { | ||
1878 | // nope. don't accept if we're protected | ||
1879 | if (mbProtected) | ||
1880 | { | ||
1881 | // don't accept packets from unexpected sources | ||
1882 | cdp = NULL; | ||
1883 | } | ||
1884 | else | ||
1885 | { | ||
1886 | // wake up the circuit | ||
1887 | cdp->setAlive(TRUE); | ||
1888 | |||
1889 | // reset packet in ID | ||
1890 | cdp->setPacketInID(mCurrentRecvPacketID); | ||
1891 | } | ||
1892 | } | ||
1893 | } | ||
1894 | |||
1895 | // At this point, cdp is now a pointer to the circuit that | ||
1896 | // this message came in on if it's valid, and NULL if the | ||
1897 | // circuit was bogus. | ||
1898 | |||
1899 | if(cdp && (acks > 0) && ((S32)(acks * sizeof(TPACKETID)) < (true_rcv_size))) | ||
1900 | { | ||
1901 | TPACKETID packet_id; | ||
1902 | U32 mem_id=0; | ||
1903 | for(S32 i = 0; i < acks; ++i) | ||
1904 | { | ||
1905 | true_rcv_size -= sizeof(TPACKETID); | ||
1906 | memcpy(&mem_id, &mTrueReceiveBuffer[true_rcv_size], /* Flawfinder: ignore*/ | ||
1907 | sizeof(TPACKETID)); | ||
1908 | packet_id = ntohl(mem_id); | ||
1909 | //llinfos << "got ack: " << packet_id << llendl; | ||
1910 | cdp->ackReliablePacket(packet_id); | ||
1911 | } | ||
1912 | if (!cdp->getUnackedPacketCount()) | ||
1913 | { | ||
1914 | // Remove this circuit from the list of circuits with unacked packets | ||
1915 | mCircuitInfo.mUnackedCircuitMap.erase(cdp->mHost); | ||
1916 | } | ||
1917 | } | ||
1918 | |||
1919 | if (buffer[0] & LL_RELIABLE_FLAG) | ||
1920 | { | ||
1921 | recv_reliable = TRUE; | ||
1922 | } | ||
1923 | if (buffer[0] & LL_RESENT_FLAG) | ||
1924 | { | ||
1925 | recv_resent = TRUE; | ||
1926 | if (cdp && cdp->isDuplicateResend(mCurrentRecvPacketID)) | ||
1927 | { | ||
1928 | // We need to ACK here to suppress | ||
1929 | // further resends of packets we've | ||
1930 | // already seen. | ||
1931 | if (recv_reliable) | ||
1932 | { | ||
1933 | //mAckList.addData(new LLPacketAck(host, mCurrentRecvPacketID)); | ||
1934 | // *************************************** | ||
1935 | // TESTING CODE | ||
1936 | //if(mCircuitInfo.mCurrentCircuit->mHost != host) | ||
1937 | //{ | ||
1938 | // llwarns << "DISCARDED PACKET HOST MISMATCH! HOST: " | ||
1939 | // << host << " CIRCUIT: " | ||
1940 | // << mCircuitInfo.mCurrentCircuit->mHost | ||
1941 | // << llendl; | ||
1942 | //} | ||
1943 | // *************************************** | ||
1944 | //mCircuitInfo.mCurrentCircuit->mAcks.put(mCurrentRecvPacketID); | ||
1945 | cdp->collectRAck(mCurrentRecvPacketID); | ||
1946 | } | ||
1947 | |||
1948 | //llinfos << "Discarding duplicate resend from " << host << llendl; | ||
1949 | if(mVerboseLog) | ||
1950 | { | ||
1951 | std::ostringstream str; | ||
1952 | str << "MSG: <- " << host; | ||
1953 | char buffer[MAX_STRING]; /* Flawfinder: ignore*/ | ||
1954 | snprintf(buffer, MAX_STRING, "\t%6d\t%6d\t%6d ", mReceiveSize, (mIncomingCompressedSize ? mIncomingCompressedSize : mReceiveSize), mCurrentRecvPacketID);/* Flawfinder: ignore*/ | ||
1955 | str << buffer << "(unknown)" | ||
1956 | << (recv_reliable ? " reliable" : "") | ||
1957 | << " resent " | ||
1958 | << ((acks > 0) ? "acks" : "") | ||
1959 | << " DISCARD DUPLICATE"; | ||
1960 | llinfos << str.str() << llendl; | ||
1961 | } | ||
1962 | mPacketsIn++; | ||
1963 | valid_packet = FALSE; | ||
1964 | continue; | ||
1965 | } | ||
1966 | } | ||
1967 | |||
1968 | // UseCircuitCode can be a valid, off-circuit packet. | ||
1969 | // But we don't want to acknowledge UseCircuitCode until the circuit is | ||
1970 | // available, which is why the acknowledgement test is done above. JC | ||
1971 | |||
1972 | valid_packet = decodeTemplate( buffer, mReceiveSize, &mCurrentRMessageTemplate ); | ||
1973 | if( valid_packet ) | ||
1974 | { | ||
1975 | mCurrentRMessageTemplate->mReceiveCount++; | ||
1976 | lldebugst(LLERR_MESSAGE) << "MessageRecvd:" << mCurrentRMessageTemplate->mName << " from " << host << llendl; | ||
1977 | } | ||
1978 | |||
1979 | // UseCircuitCode is allowed in even from an invalid circuit, so that | ||
1980 | // we can toss circuits around. | ||
1981 | if (valid_packet && !cdp && (mCurrentRMessageTemplate->mName != _PREHASH_UseCircuitCode) ) | ||
1982 | { | ||
1983 | logMsgFromInvalidCircuit( host, recv_reliable ); | ||
1984 | clearReceiveState(); | ||
1985 | valid_packet = FALSE; | ||
1986 | } | ||
1987 | |||
1988 | if (valid_packet && cdp && !cdp->getTrusted() && (mCurrentRMessageTemplate->getTrust() == MT_TRUST) ) | ||
1989 | { | ||
1990 | logTrustedMsgFromUntrustedCircuit( host ); | ||
1991 | clearReceiveState(); | ||
1992 | |||
1993 | sendDenyTrustedCircuit(host); | ||
1994 | valid_packet = FALSE; | ||
1995 | } | ||
1996 | |||
1997 | if (valid_packet | ||
1998 | && mCurrentRMessageTemplate->isBanned(cdp && cdp->getTrusted())) | ||
1999 | { | ||
2000 | llwarns << "LLMessageSystem::checkMessages " | ||
2001 | << "received banned message " | ||
2002 | << mCurrentRMessageTemplate->mName | ||
2003 | << " from " | ||
2004 | << ((cdp && cdp->getTrusted()) ? "trusted " : "untrusted ") | ||
2005 | << host << llendl; | ||
2006 | clearReceiveState(); | ||
2007 | valid_packet = FALSE; | ||
2008 | } | ||
2009 | |||
2010 | if( valid_packet ) | ||
2011 | { | ||
2012 | logValidMsg(cdp, host, recv_reliable, recv_resent, (BOOL)(acks>0) ); | ||
2013 | |||
2014 | valid_packet = decodeData( buffer, host ); | ||
2015 | } | ||
2016 | |||
2017 | // It's possible that the circuit went away, because ANY message can disable the circuit | ||
2018 | // (for example, UseCircuit, CloseCircuit, DisableSimulator). Find it again. | ||
2019 | cdp = mCircuitInfo.findCircuit(host); | ||
2020 | |||
2021 | if (valid_packet) | ||
2022 | { | ||
2023 | /* Code for dumping the complete contents of a message. Keep for future use in optimizing messages. | ||
2024 | if( 1 ) | ||
2025 | { | ||
2026 | static char* object_update = gMessageStringTable.getString("ObjectUpdate"); | ||
2027 | if(object_update == mCurrentRMessageTemplate->mName ) | ||
2028 | { | ||
2029 | llinfos << "ObjectUpdate:" << llendl; | ||
2030 | U32 i; | ||
2031 | llinfos << " Zero Encoded: " << zero_unexpanded_size << llendl; | ||
2032 | for( i = 0; i<zero_unexpanded_size; i++ ) | ||
2033 | { | ||
2034 | llinfos << " " << i << ": " << (U32) zero_unexpanded_buffer[i] << llendl; | ||
2035 | } | ||
2036 | llinfos << "" << llendl; | ||
2037 | |||
2038 | llinfos << " Zero Unencoded: " << mReceiveSize << llendl; | ||
2039 | for( i = 0; i<mReceiveSize; i++ ) | ||
2040 | { | ||
2041 | llinfos << " " << i << ": " << (U32) buffer[i] << llendl; | ||
2042 | } | ||
2043 | llinfos << "" << llendl; | ||
2044 | |||
2045 | llinfos << " Blocks and variables: " << llendl; | ||
2046 | S32 byte_count = 0; | ||
2047 | for (LLMessageTemplate::message_block_map_t::iterator | ||
2048 | iter = mCurrentRMessageTemplate->mMemberBlocks.begin(), | ||
2049 | end = mCurrentRMessageTemplate->mMemberBlocks.end(); | ||
2050 | iter != end; iter++) | ||
2051 | { | ||
2052 | LLMessageBlock* block = iter->second; | ||
2053 | const char* block_name = block->mName; | ||
2054 | for (LLMsgBlkData::msg_var_data_map_t::iterator | ||
2055 | iter = block->mMemberVariables.begin(), | ||
2056 | end = block->mMemberVariables.end(); | ||
2057 | iter != end; iter++) | ||
2058 | { | ||
2059 | const char* var_name = iter->first; | ||
2060 | |||
2061 | if( getNumberOfBlocksFast( block_name ) < 1 ) | ||
2062 | { | ||
2063 | llinfos << var_name << " has no blocks" << llendl; | ||
2064 | } | ||
2065 | for( S32 blocknum = 0; blocknum < getNumberOfBlocksFast( block_name ); blocknum++ ) | ||
2066 | { | ||
2067 | char *bnamep = (char *)block_name + blocknum; // this works because it's just a hash. The bnamep is never derefference | ||
2068 | char *vnamep = (char *)var_name; | ||
2069 | |||
2070 | LLMsgBlkData *msg_block_data = mCurrentRMessageData->mMemberBlocks[bnamep]; | ||
2071 | |||
2072 | char errmsg[1024]; | ||
2073 | if (!msg_block_data) | ||
2074 | { | ||
2075 | sprintf(errmsg, "Block %s #%d not in message %s", block_name, blocknum, mCurrentRMessageData->mName); | ||
2076 | llerrs << errmsg << llendl; | ||
2077 | } | ||
2078 | |||
2079 | LLMsgVarData vardata = msg_block_data->mMemberVarData[vnamep]; | ||
2080 | |||
2081 | if (!vardata.getName()) | ||
2082 | { | ||
2083 | sprintf(errmsg, "Variable %s not in message %s block %s", vnamep, mCurrentRMessageData->mName, bnamep); | ||
2084 | llerrs << errmsg << llendl; | ||
2085 | } | ||
2086 | |||
2087 | const S32 vardata_size = vardata.getSize(); | ||
2088 | if( vardata_size ) | ||
2089 | { | ||
2090 | for( i = 0; i < vardata_size; i++ ) | ||
2091 | { | ||
2092 | byte_count++; | ||
2093 | llinfos << block_name << " " << var_name << " [" << blocknum << "][" << i << "]= " << (U32)(((U8*)vardata.getData())[i]) << llendl; | ||
2094 | } | ||
2095 | } | ||
2096 | else | ||
2097 | { | ||
2098 | llinfos << block_name << " " << var_name << " [" << blocknum << "] 0 bytes" << llendl; | ||
2099 | } | ||
2100 | } | ||
2101 | } | ||
2102 | } | ||
2103 | llinfos << "Byte count =" << byte_count << llendl; | ||
2104 | } | ||
2105 | } | ||
2106 | */ | ||
2107 | |||
2108 | mPacketsIn++; | ||
2109 | mBytesIn += mTrueReceiveSize; | ||
2110 | |||
2111 | // ACK here for valid packets that we've seen | ||
2112 | // for the first time. | ||
2113 | if (cdp && recv_reliable) | ||
2114 | { | ||
2115 | // Add to the recently received list for duplicate suppression | ||
2116 | cdp->mRecentlyReceivedReliablePackets[mCurrentRecvPacketID] = getMessageTimeUsecs(); | ||
2117 | |||
2118 | // Put it onto the list of packets to be acked | ||
2119 | cdp->collectRAck(mCurrentRecvPacketID); | ||
2120 | mReliablePacketsIn++; | ||
2121 | } | ||
2122 | } | ||
2123 | else | ||
2124 | { | ||
2125 | if (mbProtected && (!cdp)) | ||
2126 | { | ||
2127 | llwarns << "Packet " | ||
2128 | << (mCurrentRMessageTemplate ? mCurrentRMessageTemplate->mName : "") | ||
2129 | << " from invalid circuit " << host << llendl; | ||
2130 | mOffCircuitPackets++; | ||
2131 | } | ||
2132 | else | ||
2133 | { | ||
2134 | mInvalidOnCircuitPackets++; | ||
2135 | } | ||
2136 | } | ||
2137 | |||
2138 | // Code for dumping the complete contents of a message | ||
2139 | // delete [] zero_unexpanded_buffer; | ||
2140 | } | ||
2141 | } while (!valid_packet && mReceiveSize > 0); | ||
2142 | |||
2143 | F64 mt_sec = getMessageTimeSeconds(); | ||
2144 | // Check to see if we need to print debug info | ||
2145 | if ((mt_sec - mCircuitPrintTime) > mCircuitPrintFreq) | ||
2146 | { | ||
2147 | dumpCircuitInfo(); | ||
2148 | mCircuitPrintTime = mt_sec; | ||
2149 | } | ||
2150 | |||
2151 | if( !valid_packet ) | ||
2152 | { | ||
2153 | clearReceiveState(); | ||
2154 | } | ||
2155 | |||
2156 | return valid_packet; | ||
2157 | } | ||
2158 | |||
2159 | S32 LLMessageSystem::getReceiveBytes() const | ||
2160 | { | ||
2161 | if (getReceiveCompressedSize()) | ||
2162 | { | ||
2163 | return getReceiveCompressedSize() * 8; | ||
2164 | } | ||
2165 | else | ||
2166 | { | ||
2167 | return getReceiveSize() * 8; | ||
2168 | } | ||
2169 | } | ||
2170 | |||
2171 | |||
2172 | void LLMessageSystem::processAcks() | ||
2173 | { | ||
2174 | F64 mt_sec = getMessageTimeSeconds(); | ||
2175 | { | ||
2176 | gTransferManager.updateTransfers(); | ||
2177 | |||
2178 | if (gXferManager) | ||
2179 | { | ||
2180 | gXferManager->retransmitUnackedPackets(); | ||
2181 | } | ||
2182 | |||
2183 | if (gAssetStorage) | ||
2184 | { | ||
2185 | gAssetStorage->checkForTimeouts(); | ||
2186 | } | ||
2187 | } | ||
2188 | |||
2189 | BOOL dump = FALSE; | ||
2190 | { | ||
2191 | // Check the status of circuits | ||
2192 | mCircuitInfo.updateWatchDogTimers(this); | ||
2193 | |||
2194 | //resend any necessary packets | ||
2195 | mCircuitInfo.resendUnackedPackets(mUnackedListDepth, mUnackedListSize); | ||
2196 | |||
2197 | //cycle through ack list for each host we need to send acks to | ||
2198 | mCircuitInfo.sendAcks(); | ||
2199 | |||
2200 | if (!mDenyTrustedCircuitSet.empty()) | ||
2201 | { | ||
2202 | llinfos << "Sending queued DenyTrustedCircuit messages." << llendl; | ||
2203 | for (host_set_t::iterator hostit = mDenyTrustedCircuitSet.begin(); hostit != mDenyTrustedCircuitSet.end(); ++hostit) | ||
2204 | { | ||
2205 | reallySendDenyTrustedCircuit(*hostit); | ||
2206 | } | ||
2207 | mDenyTrustedCircuitSet.clear(); | ||
2208 | } | ||
2209 | |||
2210 | if (mMaxMessageCounts >= 0) | ||
2211 | { | ||
2212 | if (mNumMessageCounts >= mMaxMessageCounts) | ||
2213 | { | ||
2214 | dump = TRUE; | ||
2215 | } | ||
2216 | } | ||
2217 | |||
2218 | if (mMaxMessageTime >= 0.f) | ||
2219 | { | ||
2220 | // This is one of the only places where we're required to get REAL message system time. | ||
2221 | mReceiveTime = (F32)(getMessageTimeSeconds(TRUE) - mMessageCountTime); | ||
2222 | if (mReceiveTime > mMaxMessageTime) | ||
2223 | { | ||
2224 | dump = TRUE; | ||
2225 | } | ||
2226 | } | ||
2227 | } | ||
2228 | |||
2229 | if (dump) | ||
2230 | { | ||
2231 | dumpReceiveCounts(); | ||
2232 | } | ||
2233 | resetReceiveCounts(); | ||
2234 | |||
2235 | if ((mt_sec - mResendDumpTime) > CIRCUIT_DUMP_TIMEOUT) | ||
2236 | { | ||
2237 | mResendDumpTime = mt_sec; | ||
2238 | mCircuitInfo.dumpResends(); | ||
2239 | } | ||
2240 | } | ||
2241 | |||
2242 | |||
2243 | void LLMessageSystem::newMessageFast(const char *name) | ||
2244 | { | ||
2245 | mbSBuilt = FALSE; | ||
2246 | mbSClear = FALSE; | ||
2247 | |||
2248 | mCurrentSendTotal = 0; | ||
2249 | mSendReliable = FALSE; | ||
2250 | |||
2251 | char *namep = (char *)name; | ||
2252 | |||
2253 | if (mMessageTemplates.count(namep) > 0) | ||
2254 | { | ||
2255 | mCurrentSMessageTemplate = mMessageTemplates[namep]; | ||
2256 | if (mCurrentSMessageData) | ||
2257 | { | ||
2258 | delete mCurrentSMessageData; | ||
2259 | } | ||
2260 | mCurrentSMessageData = new LLMsgData(namep); | ||
2261 | mCurrentSMessageName = namep; | ||
2262 | mCurrentSDataBlock = NULL; | ||
2263 | mCurrentSBlockName = NULL; | ||
2264 | |||
2265 | // add at one of each block | ||
2266 | LLMessageTemplate* msg_template = mMessageTemplates[namep]; | ||
2267 | for (LLMessageTemplate::message_block_map_t::iterator iter = msg_template->mMemberBlocks.begin(); | ||
2268 | iter != msg_template->mMemberBlocks.end(); iter++) | ||
2269 | { | ||
2270 | LLMessageBlock* ci = iter->second; | ||
2271 | LLMsgBlkData *tblockp; | ||
2272 | tblockp = new LLMsgBlkData(ci->mName, 0); | ||
2273 | mCurrentSMessageData->addBlock(tblockp); | ||
2274 | } | ||
2275 | } | ||
2276 | else | ||
2277 | { | ||
2278 | llerrs << "newMessage - Message " << name << " not registered" << llendl; | ||
2279 | } | ||
2280 | } | ||
2281 | |||
2282 | void LLMessageSystem::copyMessageRtoS() | ||
2283 | { | ||
2284 | if (!mCurrentRMessageTemplate) | ||
2285 | { | ||
2286 | return; | ||
2287 | } | ||
2288 | newMessageFast(mCurrentRMessageTemplate->mName); | ||
2289 | |||
2290 | // copy the blocks | ||
2291 | // counting variables used to encode multiple block info | ||
2292 | S32 block_count = 0; | ||
2293 | char *block_name = NULL; | ||
2294 | |||
2295 | // loop through msg blocks to loop through variables, totalling up size data and filling the new (send) message | ||
2296 | LLMsgData::msg_blk_data_map_t::iterator iter = mCurrentRMessageData->mMemberBlocks.begin(); | ||
2297 | LLMsgData::msg_blk_data_map_t::iterator end = mCurrentRMessageData->mMemberBlocks.end(); | ||
2298 | for(; iter != end; ++iter) | ||
2299 | { | ||
2300 | LLMsgBlkData* mbci = iter->second; | ||
2301 | if(!mbci) continue; | ||
2302 | |||
2303 | // do we need to encode a block code? | ||
2304 | if (block_count == 0) | ||
2305 | { | ||
2306 | block_count = mbci->mBlockNumber; | ||
2307 | block_name = (char *)mbci->mName; | ||
2308 | } | ||
2309 | |||
2310 | // counting down mutliple blocks | ||
2311 | block_count--; | ||
2312 | |||
2313 | nextBlockFast(block_name); | ||
2314 | |||
2315 | // now loop through the variables | ||
2316 | LLMsgBlkData::msg_var_data_map_t::iterator dit = mbci->mMemberVarData.begin(); | ||
2317 | LLMsgBlkData::msg_var_data_map_t::iterator dend = mbci->mMemberVarData.end(); | ||
2318 | |||
2319 | for(; dit != dend; ++dit) | ||
2320 | { | ||
2321 | LLMsgVarData& mvci = *dit; | ||
2322 | addDataFast(mvci.getName(), mvci.getData(), mvci.getType(), mvci.getSize()); | ||
2323 | } | ||
2324 | } | ||
2325 | } | ||
2326 | |||
2327 | void LLMessageSystem::clearMessage() | ||
2328 | { | ||
2329 | mbSBuilt = FALSE; | ||
2330 | mbSClear = TRUE; | ||
2331 | |||
2332 | mCurrentSendTotal = 0; | ||
2333 | mSendReliable = FALSE; | ||
2334 | |||
2335 | mCurrentSMessageTemplate = NULL; | ||
2336 | |||
2337 | delete mCurrentSMessageData; | ||
2338 | mCurrentSMessageData = NULL; | ||
2339 | |||
2340 | mCurrentSMessageName = NULL; | ||
2341 | mCurrentSDataBlock = NULL; | ||
2342 | mCurrentSBlockName = NULL; | ||
2343 | } | ||
2344 | |||
2345 | |||
2346 | // set block to add data to within current message | ||
2347 | void LLMessageSystem::nextBlockFast(const char *blockname) | ||
2348 | { | ||
2349 | char *bnamep = (char *)blockname; | ||
2350 | |||
2351 | if (!mCurrentSMessageTemplate) | ||
2352 | { | ||
2353 | llerrs << "newMessage not called prior to setBlock" << llendl; | ||
2354 | return; | ||
2355 | } | ||
2356 | |||
2357 | // now, does this block exist? | ||
2358 | LLMessageTemplate::message_block_map_t::iterator temp_iter = mCurrentSMessageTemplate->mMemberBlocks.find(bnamep); | ||
2359 | if (temp_iter == mCurrentSMessageTemplate->mMemberBlocks.end()) | ||
2360 | { | ||
2361 | llerrs << "LLMessageSystem::nextBlockFast " << bnamep | ||
2362 | << " not a block in " << mCurrentSMessageTemplate->mName << llendl; | ||
2363 | return; | ||
2364 | } | ||
2365 | |||
2366 | LLMessageBlock* template_data = temp_iter->second; | ||
2367 | |||
2368 | // ok, have we already set this block? | ||
2369 | LLMsgBlkData* block_data = mCurrentSMessageData->mMemberBlocks[bnamep]; | ||
2370 | if (block_data->mBlockNumber == 0) | ||
2371 | { | ||
2372 | // nope! set this as the current block | ||
2373 | block_data->mBlockNumber = 1; | ||
2374 | mCurrentSDataBlock = block_data; | ||
2375 | mCurrentSBlockName = bnamep; | ||
2376 | |||
2377 | // add placeholders for each of the variables | ||
2378 | for (LLMessageBlock::message_variable_map_t::iterator iter = template_data->mMemberVariables.begin(); | ||
2379 | iter != template_data->mMemberVariables.end(); iter++) | ||
2380 | { | ||
2381 | LLMessageVariable& ci = *(iter->second); | ||
2382 | mCurrentSDataBlock->addVariable(ci.getName(), ci.getType()); | ||
2383 | } | ||
2384 | return; | ||
2385 | } | ||
2386 | else | ||
2387 | { | ||
2388 | // already have this block. . . | ||
2389 | // are we supposed to have a new one? | ||
2390 | |||
2391 | // if the block is type MBT_SINGLE this is bad! | ||
2392 | if (template_data->mType == MBT_SINGLE) | ||
2393 | { | ||
2394 | llerrs << "LLMessageSystem::nextBlockFast called multiple times" | ||
2395 | << " for " << bnamep << " but is type MBT_SINGLE" << llendl; | ||
2396 | return; | ||
2397 | } | ||
2398 | |||
2399 | |||
2400 | // if the block is type MBT_MULTIPLE then we need a known number, make sure that we're not exceeding it | ||
2401 | if ( (template_data->mType == MBT_MULTIPLE) | ||
2402 | &&(mCurrentSDataBlock->mBlockNumber == template_data->mNumber)) | ||
2403 | { | ||
2404 | llerrs << "LLMessageSystem::nextBlockFast called " | ||
2405 | << mCurrentSDataBlock->mBlockNumber << " times for " << bnamep | ||
2406 | << " exceeding " << template_data->mNumber | ||
2407 | << " specified in type MBT_MULTIPLE." << llendl; | ||
2408 | return; | ||
2409 | } | ||
2410 | |||
2411 | // ok, we can make a new one | ||
2412 | // modify the name to avoid name collision by adding number to end | ||
2413 | S32 count = block_data->mBlockNumber; | ||
2414 | |||
2415 | // incrememt base name's count | ||
2416 | block_data->mBlockNumber++; | ||
2417 | |||
2418 | if (block_data->mBlockNumber > MAX_BLOCKS) | ||
2419 | { | ||
2420 | llerrs << "Trying to pack too many blocks into MBT_VARIABLE type (limited to " << MAX_BLOCKS << ")" << llendl; | ||
2421 | } | ||
2422 | |||
2423 | // create new name | ||
2424 | // Nota Bene: if things are working correctly, mCurrentMessageData->mMemberBlocks[blockname]->mBlockNumber == mCurrentDataBlock->mBlockNumber + 1 | ||
2425 | |||
2426 | char *nbnamep = bnamep + count; | ||
2427 | |||
2428 | mCurrentSDataBlock = new LLMsgBlkData(bnamep, count); | ||
2429 | mCurrentSDataBlock->mName = nbnamep; | ||
2430 | mCurrentSMessageData->mMemberBlocks[nbnamep] = mCurrentSDataBlock; | ||
2431 | |||
2432 | // add placeholders for each of the variables | ||
2433 | for (LLMessageBlock::message_variable_map_t::iterator | ||
2434 | iter = template_data->mMemberVariables.begin(), | ||
2435 | end = template_data->mMemberVariables.end(); | ||
2436 | iter != end; iter++) | ||
2437 | { | ||
2438 | LLMessageVariable& ci = *(iter->second); | ||
2439 | mCurrentSDataBlock->addVariable(ci.getName(), ci.getType()); | ||
2440 | } | ||
2441 | return; | ||
2442 | } | ||
2443 | } | ||
2444 | |||
2445 | // add data to variable in current block | ||
2446 | void LLMessageSystem::addDataFast(const char *varname, const void *data, EMsgVariableType type, S32 size) | ||
2447 | { | ||
2448 | char *vnamep = (char *)varname; | ||
2449 | |||
2450 | // do we have a current message? | ||
2451 | if (!mCurrentSMessageTemplate) | ||
2452 | { | ||
2453 | llerrs << "newMessage not called prior to addData" << llendl; | ||
2454 | return; | ||
2455 | } | ||
2456 | |||
2457 | // do we have a current block? | ||
2458 | if (!mCurrentSDataBlock) | ||
2459 | { | ||
2460 | llerrs << "setBlock not called prior to addData" << llendl; | ||
2461 | return; | ||
2462 | } | ||
2463 | |||
2464 | // kewl, add the data if it exists | ||
2465 | LLMessageVariable* var_data = mCurrentSMessageTemplate->mMemberBlocks[mCurrentSBlockName]->mMemberVariables[vnamep]; | ||
2466 | if (!var_data || !var_data->getName()) | ||
2467 | { | ||
2468 | llerrs << vnamep << " not a variable in block " << mCurrentSBlockName << " of " << mCurrentSMessageTemplate->mName << llendl; | ||
2469 | return; | ||
2470 | } | ||
2471 | |||
2472 | // ok, it seems ok. . . are we the correct size? | ||
2473 | if (var_data->getType() == MVT_VARIABLE) | ||
2474 | { | ||
2475 | // Variable 1 can only store 255 bytes, make sure our data is smaller | ||
2476 | if ((var_data->getSize() == 1) && | ||
2477 | (size > 255)) | ||
2478 | { | ||
2479 | llwarns << "Field " << varname << " is a Variable 1 but program " | ||
2480 | << "attempted to stuff more than 255 bytes in " | ||
2481 | << "(" << size << "). Clamping size and truncating data." << llendl; | ||
2482 | size = 255; | ||
2483 | char *truncate = (char *)data; | ||
2484 | truncate[255] = 0; | ||
2485 | } | ||
2486 | |||
2487 | // no correct size for MVT_VARIABLE, instead we need to tell how many bytes the size will be encoded as | ||
2488 | mCurrentSDataBlock->addData(vnamep, data, size, type, var_data->getSize()); | ||
2489 | mCurrentSendTotal += size; | ||
2490 | } | ||
2491 | else | ||
2492 | { | ||
2493 | if (size != var_data->getSize()) | ||
2494 | { | ||
2495 | llerrs << varname << " is type MVT_FIXED but request size " << size << " doesn't match template size " | ||
2496 | << var_data->getSize() << llendl; | ||
2497 | return; | ||
2498 | } | ||
2499 | // alright, smash it in | ||
2500 | mCurrentSDataBlock->addData(vnamep, data, size, type); | ||
2501 | mCurrentSendTotal += size; | ||
2502 | } | ||
2503 | } | ||
2504 | |||
2505 | // add data to variable in current block - fails if variable isn't MVT_FIXED | ||
2506 | void LLMessageSystem::addDataFast(const char *varname, const void *data, EMsgVariableType type) | ||
2507 | { | ||
2508 | char *vnamep = (char *)varname; | ||
2509 | |||
2510 | // do we have a current message? | ||
2511 | if (!mCurrentSMessageTemplate) | ||
2512 | { | ||
2513 | llerrs << "newMessage not called prior to addData" << llendl; | ||
2514 | return; | ||
2515 | } | ||
2516 | |||
2517 | // do we have a current block? | ||
2518 | if (!mCurrentSDataBlock) | ||
2519 | { | ||
2520 | llerrs << "setBlock not called prior to addData" << llendl; | ||
2521 | return; | ||
2522 | } | ||
2523 | |||
2524 | // kewl, add the data if it exists | ||
2525 | LLMessageVariable* var_data = mCurrentSMessageTemplate->mMemberBlocks[mCurrentSBlockName]->mMemberVariables[vnamep]; | ||
2526 | if (!var_data->getName()) | ||
2527 | { | ||
2528 | llerrs << vnamep << " not a variable in block " << mCurrentSBlockName << " of " << mCurrentSMessageTemplate->mName << llendl; | ||
2529 | return; | ||
2530 | } | ||
2531 | |||
2532 | // ok, it seems ok. . . are we MVT_VARIABLE? | ||
2533 | if (var_data->getType() == MVT_VARIABLE) | ||
2534 | { | ||
2535 | // nope | ||
2536 | llerrs << vnamep << " is type MVT_VARIABLE. Call using addData(name, data, size)" << llendl; | ||
2537 | return; | ||
2538 | } | ||
2539 | else | ||
2540 | { | ||
2541 | mCurrentSDataBlock->addData(vnamep, data, var_data->getSize(), type); | ||
2542 | mCurrentSendTotal += var_data->getSize(); | ||
2543 | } | ||
2544 | } | ||
2545 | |||
2546 | BOOL LLMessageSystem::isSendFull(const char* blockname) | ||
2547 | { | ||
2548 | if(!blockname) | ||
2549 | { | ||
2550 | return (mCurrentSendTotal > MTUBYTES); | ||
2551 | } | ||
2552 | return isSendFullFast(gMessageStringTable.getString(blockname)); | ||
2553 | } | ||
2554 | |||
2555 | BOOL LLMessageSystem::isSendFullFast(const char* blockname) | ||
2556 | { | ||
2557 | if(mCurrentSendTotal > MTUBYTES) | ||
2558 | { | ||
2559 | return TRUE; | ||
2560 | } | ||
2561 | if(!blockname) | ||
2562 | { | ||
2563 | return FALSE; | ||
2564 | } | ||
2565 | char* bnamep = (char*)blockname; | ||
2566 | S32 max; | ||
2567 | |||
2568 | LLMessageBlock* template_data = mCurrentSMessageTemplate->mMemberBlocks[bnamep]; | ||
2569 | |||
2570 | switch(template_data->mType) | ||
2571 | { | ||
2572 | case MBT_SINGLE: | ||
2573 | max = 1; | ||
2574 | break; | ||
2575 | case MBT_MULTIPLE: | ||
2576 | max = template_data->mNumber; | ||
2577 | break; | ||
2578 | case MBT_VARIABLE: | ||
2579 | default: | ||
2580 | max = MAX_BLOCKS; | ||
2581 | break; | ||
2582 | } | ||
2583 | if(mCurrentSMessageData->mMemberBlocks[bnamep]->mBlockNumber >= max) | ||
2584 | { | ||
2585 | return TRUE; | ||
2586 | } | ||
2587 | return FALSE; | ||
2588 | } | ||
2589 | |||
2590 | |||
2591 | // blow away the last block of a message, return FALSE if that leaves no blocks or there wasn't a block to remove | ||
2592 | BOOL LLMessageSystem::removeLastBlock() | ||
2593 | { | ||
2594 | if (mCurrentSBlockName) | ||
2595 | { | ||
2596 | if ( (mCurrentSMessageData) | ||
2597 | &&(mCurrentSMessageTemplate)) | ||
2598 | { | ||
2599 | if (mCurrentSMessageData->mMemberBlocks[mCurrentSBlockName]->mBlockNumber >= 1) | ||
2600 | { | ||
2601 | // At least one block for the current block name. | ||
2602 | |||
2603 | // Store the current block name for future reference. | ||
2604 | char *block_name = mCurrentSBlockName; | ||
2605 | |||
2606 | // Decrement the sent total by the size of the | ||
2607 | // data in the message block that we're currently building. | ||
2608 | |||
2609 | LLMessageBlock* template_data = mCurrentSMessageTemplate->mMemberBlocks[mCurrentSBlockName]; | ||
2610 | |||
2611 | for (LLMessageBlock::message_variable_map_t::iterator iter = template_data->mMemberVariables.begin(); | ||
2612 | iter != template_data->mMemberVariables.end(); iter++) | ||
2613 | { | ||
2614 | LLMessageVariable& ci = *(iter->second); | ||
2615 | mCurrentSendTotal -= ci.getSize(); | ||
2616 | } | ||
2617 | |||
2618 | |||
2619 | // Now we want to find the block that we're blowing away. | ||
2620 | |||
2621 | // Get the number of blocks. | ||
2622 | LLMsgBlkData* block_data = mCurrentSMessageData->mMemberBlocks[block_name]; | ||
2623 | S32 num_blocks = block_data->mBlockNumber; | ||
2624 | |||
2625 | // Use the same (suspect?) algorithm that's used to generate | ||
2626 | // the names in the nextBlock method to find it. | ||
2627 | char *block_getting_whacked = block_name + num_blocks - 1; | ||
2628 | LLMsgBlkData* whacked_data = mCurrentSMessageData->mMemberBlocks[block_getting_whacked]; | ||
2629 | delete whacked_data; | ||
2630 | mCurrentSMessageData->mMemberBlocks.erase(block_getting_whacked); | ||
2631 | |||
2632 | if (num_blocks <= 1) | ||
2633 | { | ||
2634 | // we just blew away the last one, so return FALSE | ||
2635 | return FALSE; | ||
2636 | } | ||
2637 | else | ||
2638 | { | ||
2639 | // Decrement the counter. | ||
2640 | block_data->mBlockNumber--; | ||
2641 | return TRUE; | ||
2642 | } | ||
2643 | } | ||
2644 | } | ||
2645 | } | ||
2646 | return FALSE; | ||
2647 | } | ||
2648 | |||
2649 | // make sure that all the desired data is in place and then copy the data into mSendBuffer | ||
2650 | void LLMessageSystem::buildMessage() | ||
2651 | { | ||
2652 | // basic algorithm is to loop through the various pieces, building | ||
2653 | // size and offset info if we encounter a -1 for mSize at any | ||
2654 | // point that variable wasn't given data | ||
2655 | |||
2656 | // do we have a current message? | ||
2657 | if (!mCurrentSMessageTemplate) | ||
2658 | { | ||
2659 | llerrs << "newMessage not called prior to buildMessage" << llendl; | ||
2660 | return; | ||
2661 | } | ||
2662 | |||
2663 | // zero out some useful values | ||
2664 | |||
2665 | // leave room for circuit counter | ||
2666 | mSendSize = LL_PACKET_ID_SIZE; | ||
2667 | |||
2668 | // encode message number and adjust total_offset | ||
2669 | if (mCurrentSMessageTemplate->mFrequency == MFT_HIGH) | ||
2670 | { | ||
2671 | // old, endian-dependant way | ||
2672 | // memcpy(&mSendBuffer[mSendSize], &mCurrentMessageTemplate->mMessageNumber, sizeof(U8)); | ||
2673 | |||
2674 | // new, independant way | ||
2675 | mSendBuffer[mSendSize] = (U8)mCurrentSMessageTemplate->mMessageNumber; | ||
2676 | mSendSize += sizeof(U8); | ||
2677 | } | ||
2678 | else if (mCurrentSMessageTemplate->mFrequency == MFT_MEDIUM) | ||
2679 | { | ||
2680 | U8 temp = 255; | ||
2681 | memcpy(&mSendBuffer[mSendSize], &temp, sizeof(U8)); /*Flawfinder: ignore*/ | ||
2682 | mSendSize += sizeof(U8); | ||
2683 | |||
2684 | // mask off unsightly bits | ||
2685 | temp = mCurrentSMessageTemplate->mMessageNumber & 255; | ||
2686 | memcpy(&mSendBuffer[mSendSize], &temp, sizeof(U8)); /*Flawfinder: ignore*/ | ||
2687 | mSendSize += sizeof(U8); | ||
2688 | } | ||
2689 | else if (mCurrentSMessageTemplate->mFrequency == MFT_LOW) | ||
2690 | { | ||
2691 | U8 temp = 255; | ||
2692 | U16 message_num; | ||
2693 | memcpy(&mSendBuffer[mSendSize], &temp, sizeof(U8)); /*Flawfinder: ignore*/ | ||
2694 | mSendSize += sizeof(U8); | ||
2695 | memcpy(&mSendBuffer[mSendSize], &temp, sizeof(U8)); /*Flawfinder: ignore*/ | ||
2696 | mSendSize += sizeof(U8); | ||
2697 | |||
2698 | // mask off unsightly bits | ||
2699 | message_num = mCurrentSMessageTemplate->mMessageNumber & 0xFFFF; | ||
2700 | |||
2701 | // convert to network byte order | ||
2702 | message_num = htons(message_num); | ||
2703 | memcpy(&mSendBuffer[mSendSize], &message_num, sizeof(U16)); /*Flawfinder: ignore*/ | ||
2704 | mSendSize += sizeof(U16); | ||
2705 | } | ||
2706 | else | ||
2707 | { | ||
2708 | llerrs << "unexpected message frequency in buildMessage" << llendl; | ||
2709 | return; | ||
2710 | } | ||
2711 | |||
2712 | // counting variables used to encode multiple block info | ||
2713 | S32 block_count = 0; | ||
2714 | U8 temp_block_number; | ||
2715 | |||
2716 | // loop through msg blocks to loop through variables, totalling up size data and copying into mSendBuffer | ||
2717 | for (LLMsgData::msg_blk_data_map_t::iterator | ||
2718 | iter = mCurrentSMessageData->mMemberBlocks.begin(), | ||
2719 | end = mCurrentSMessageData->mMemberBlocks.end(); | ||
2720 | iter != end; iter++) | ||
2721 | { | ||
2722 | LLMsgBlkData* mbci = iter->second; | ||
2723 | // do we need to encode a block code? | ||
2724 | if (block_count == 0) | ||
2725 | { | ||
2726 | block_count = mbci->mBlockNumber; | ||
2727 | |||
2728 | LLMessageBlock* template_data = mCurrentSMessageTemplate->mMemberBlocks[mbci->mName]; | ||
2729 | |||
2730 | // ok, if this is the first block of a repeating pack, set block_count and, if it's type MBT_VARIABLE encode a byte for how many there are | ||
2731 | if (template_data->mType == MBT_VARIABLE) | ||
2732 | { | ||
2733 | // remember that mBlockNumber is a S32 | ||
2734 | temp_block_number = (U8)mbci->mBlockNumber; | ||
2735 | if ((S32)(mSendSize + sizeof(U8)) < MAX_BUFFER_SIZE) | ||
2736 | { | ||
2737 | memcpy(&mSendBuffer[mSendSize], &temp_block_number, sizeof(U8)); | ||
2738 | mSendSize += sizeof(U8); | ||
2739 | } | ||
2740 | else | ||
2741 | { | ||
2742 | // Just reporting error is likely not enough. Need | ||
2743 | // to check how to abort or error out gracefully | ||
2744 | // from this function. XXXTBD | ||
2745 | llerrs << "buildMessage failed. Message excedding" | ||
2746 | " sendBuffersize." << llendl; | ||
2747 | } | ||
2748 | } | ||
2749 | else if (template_data->mType == MBT_MULTIPLE) | ||
2750 | { | ||
2751 | if (block_count != template_data->mNumber) | ||
2752 | { | ||
2753 | // nope! need to fill it in all the way! | ||
2754 | llerrs << "Block " << mbci->mName | ||
2755 | << " is type MBT_MULTIPLE but only has data for " | ||
2756 | << block_count << " out of its " | ||
2757 | << template_data->mNumber << " blocks" << llendl; | ||
2758 | } | ||
2759 | } | ||
2760 | } | ||
2761 | |||
2762 | // counting down multiple blocks | ||
2763 | block_count--; | ||
2764 | |||
2765 | // now loop through the variables | ||
2766 | for (LLMsgBlkData::msg_var_data_map_t::iterator iter = mbci->mMemberVarData.begin(); | ||
2767 | iter != mbci->mMemberVarData.end(); iter++) | ||
2768 | { | ||
2769 | LLMsgVarData& mvci = *iter; | ||
2770 | if (mvci.getSize() == -1) | ||
2771 | { | ||
2772 | // oops, this variable wasn't ever set! | ||
2773 | llerrs << "The variable " << mvci.getName() << " in block " | ||
2774 | << mbci->mName << " of message " | ||
2775 | << mCurrentSMessageData->mName | ||
2776 | << " wasn't set prior to buildMessage call" << llendl; | ||
2777 | } | ||
2778 | else | ||
2779 | { | ||
2780 | S32 data_size = mvci.getDataSize(); | ||
2781 | if(data_size > 0) | ||
2782 | { | ||
2783 | // The type is MVT_VARIABLE, which means that we | ||
2784 | // need to encode a size argument. Otherwise, | ||
2785 | // there is no need. | ||
2786 | S32 size = mvci.getSize(); | ||
2787 | U8 sizeb; | ||
2788 | U16 sizeh; | ||
2789 | switch(data_size) | ||
2790 | { | ||
2791 | case 1: | ||
2792 | sizeb = size; | ||
2793 | htonmemcpy(&mSendBuffer[mSendSize], &sizeb, MVT_U8, 1); | ||
2794 | break; | ||
2795 | case 2: | ||
2796 | sizeh = size; | ||
2797 | htonmemcpy(&mSendBuffer[mSendSize], &sizeh, MVT_U16, 2); | ||
2798 | break; | ||
2799 | case 4: | ||
2800 | htonmemcpy(&mSendBuffer[mSendSize], &size, MVT_S32, 4); | ||
2801 | break; | ||
2802 | default: | ||
2803 | llerrs << "Attempting to build variable field with unknown size of " << size << llendl; | ||
2804 | break; | ||
2805 | } | ||
2806 | mSendSize += mvci.getDataSize(); | ||
2807 | } | ||
2808 | |||
2809 | // if there is any data to pack, pack it | ||
2810 | if((mvci.getData() != NULL) && mvci.getSize()) | ||
2811 | { | ||
2812 | if(mSendSize + mvci.getSize() < (S32)sizeof(mSendBuffer)) | ||
2813 | { | ||
2814 | memcpy( | ||
2815 | &mSendBuffer[mSendSize], | ||
2816 | mvci.getData(), | ||
2817 | mvci.getSize()); | ||
2818 | mSendSize += mvci.getSize(); | ||
2819 | } | ||
2820 | else | ||
2821 | { | ||
2822 | // Just reporting error is likely not | ||
2823 | // enough. Need to check how to abort or error | ||
2824 | // out gracefully from this function. XXXTBD | ||
2825 | llerrs << "LLMessageSystem::buildMessage failed. " | ||
2826 | << "Attempted to pack " | ||
2827 | << mSendSize + mvci.getSize() | ||
2828 | << " bytes into a buffer with size " | ||
2829 | << mSendBuffer << "." << llendl | ||
2830 | } | ||
2831 | } | ||
2832 | } | ||
2833 | } | ||
2834 | } | ||
2835 | mbSBuilt = TRUE; | ||
2836 | } | ||
2837 | |||
2838 | S32 LLMessageSystem::sendReliable(const LLHost &host) | ||
2839 | { | ||
2840 | return sendReliable(host, LL_DEFAULT_RELIABLE_RETRIES, TRUE, LL_PING_BASED_TIMEOUT_DUMMY, NULL, NULL); | ||
2841 | } | ||
2842 | |||
2843 | |||
2844 | S32 LLMessageSystem::sendSemiReliable(const LLHost &host, void (*callback)(void **,S32), void ** callback_data) | ||
2845 | { | ||
2846 | F32 timeout; | ||
2847 | |||
2848 | LLCircuitData *cdp = mCircuitInfo.findCircuit(host); | ||
2849 | if (cdp) | ||
2850 | { | ||
2851 | timeout = llmax(LL_MINIMUM_SEMIRELIABLE_TIMEOUT_SECONDS, | ||
2852 | LL_SEMIRELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged()); | ||
2853 | } | ||
2854 | else | ||
2855 | { | ||
2856 | timeout = LL_SEMIRELIABLE_TIMEOUT_FACTOR * LL_AVERAGED_PING_MAX; | ||
2857 | } | ||
2858 | |||
2859 | return sendReliable(host, 0, FALSE, timeout, callback, callback_data); | ||
2860 | } | ||
2861 | |||
2862 | // send the message via a UDP packet | ||
2863 | S32 LLMessageSystem::sendReliable( const LLHost &host, | ||
2864 | S32 retries, | ||
2865 | BOOL ping_based_timeout, | ||
2866 | F32 timeout, | ||
2867 | void (*callback)(void **,S32), | ||
2868 | void ** callback_data) | ||
2869 | { | ||
2870 | if (ping_based_timeout) | ||
2871 | { | ||
2872 | LLCircuitData *cdp = mCircuitInfo.findCircuit(host); | ||
2873 | if (cdp) | ||
2874 | { | ||
2875 | timeout = llmax(LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS, LL_RELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged()); | ||
2876 | } | ||
2877 | else | ||
2878 | { | ||
2879 | timeout = llmax(LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS, LL_RELIABLE_TIMEOUT_FACTOR * LL_AVERAGED_PING_MAX); | ||
2880 | } | ||
2881 | } | ||
2882 | |||
2883 | mSendReliable = TRUE; | ||
2884 | mReliablePacketParams.set(host, retries, ping_based_timeout, timeout, | ||
2885 | callback, callback_data, mCurrentSMessageName); | ||
2886 | return sendMessage(host); | ||
2887 | } | ||
2888 | |||
2889 | void LLMessageSystem::forwardMessage(const LLHost &host) | ||
2890 | { | ||
2891 | copyMessageRtoS(); | ||
2892 | sendMessage(host); | ||
2893 | } | ||
2894 | |||
2895 | void LLMessageSystem::forwardReliable(const LLHost &host) | ||
2896 | { | ||
2897 | copyMessageRtoS(); | ||
2898 | sendReliable(host); | ||
2899 | } | ||
2900 | |||
2901 | void LLMessageSystem::forwardReliable(const U32 circuit_code) | ||
2902 | { | ||
2903 | copyMessageRtoS(); | ||
2904 | sendReliable(findHost(circuit_code)); | ||
2905 | } | ||
2906 | |||
2907 | S32 LLMessageSystem::flushSemiReliable(const LLHost &host, void (*callback)(void **,S32), void ** callback_data) | ||
2908 | { | ||
2909 | F32 timeout; | ||
2910 | |||
2911 | LLCircuitData *cdp = mCircuitInfo.findCircuit(host); | ||
2912 | if (cdp) | ||
2913 | { | ||
2914 | timeout = llmax(LL_MINIMUM_SEMIRELIABLE_TIMEOUT_SECONDS, | ||
2915 | LL_SEMIRELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged()); | ||
2916 | } | ||
2917 | else | ||
2918 | { | ||
2919 | timeout = LL_SEMIRELIABLE_TIMEOUT_FACTOR * LL_AVERAGED_PING_MAX; | ||
2920 | } | ||
2921 | |||
2922 | S32 send_bytes = 0; | ||
2923 | if (mCurrentSendTotal) | ||
2924 | { | ||
2925 | mSendReliable = TRUE; | ||
2926 | // No need for ping-based retry as not going to retry | ||
2927 | mReliablePacketParams.set(host, 0, FALSE, timeout, callback, callback_data, mCurrentSMessageName); | ||
2928 | send_bytes = sendMessage(host); | ||
2929 | clearMessage(); | ||
2930 | } | ||
2931 | else | ||
2932 | { | ||
2933 | delete callback_data; | ||
2934 | } | ||
2935 | return send_bytes; | ||
2936 | } | ||
2937 | |||
2938 | S32 LLMessageSystem::flushReliable(const LLHost &host) | ||
2939 | { | ||
2940 | S32 send_bytes = 0; | ||
2941 | if (mCurrentSendTotal) | ||
2942 | { | ||
2943 | send_bytes = sendReliable(host); | ||
2944 | } | ||
2945 | clearMessage(); | ||
2946 | return send_bytes; | ||
2947 | } | ||
2948 | |||
2949 | |||
2950 | // This can be called from signal handlers, | ||
2951 | // so should should not use llinfos. | ||
2952 | S32 LLMessageSystem::sendMessage(const LLHost &host) | ||
2953 | { | ||
2954 | if (!mbSBuilt) | ||
2955 | { | ||
2956 | buildMessage(); | ||
2957 | } | ||
2958 | |||
2959 | mCurrentSendTotal = 0; | ||
2960 | |||
2961 | if (!(host.isOk())) // if port and ip are zero, don't bother trying to send the message | ||
2962 | { | ||
2963 | return 0; | ||
2964 | } | ||
2965 | |||
2966 | LLCircuitData *cdp = mCircuitInfo.findCircuit(host); | ||
2967 | if (!cdp) | ||
2968 | { | ||
2969 | // this is a new circuit! | ||
2970 | // are we protected? | ||
2971 | if (mbProtected) | ||
2972 | { | ||
2973 | // yup! don't send packets to an unknown circuit | ||
2974 | if(mVerboseLog) | ||
2975 | { | ||
2976 | llinfos << "MSG: -> " << host << "\tUNKNOWN CIRCUIT:\t" | ||
2977 | << mCurrentSMessageName << llendl; | ||
2978 | } | ||
2979 | llwarns << "sendMessage - Trying to send " | ||
2980 | << mCurrentSMessageName << " on unknown circuit " | ||
2981 | << host << llendl; | ||
2982 | return 0; | ||
2983 | } | ||
2984 | else | ||
2985 | { | ||
2986 | // nope, open the new circuit | ||
2987 | cdp = mCircuitInfo.addCircuitData(host, 0); | ||
2988 | } | ||
2989 | } | ||
2990 | else | ||
2991 | { | ||
2992 | // this is an old circuit. . . is it still alive? | ||
2993 | if (!cdp->isAlive()) | ||
2994 | { | ||
2995 | // nope. don't send to dead circuits | ||
2996 | if(mVerboseLog) | ||
2997 | { | ||
2998 | llinfos << "MSG: -> " << host << "\tDEAD CIRCUIT\t\t" | ||
2999 | << mCurrentSMessageName << llendl; | ||
3000 | } | ||
3001 | llwarns << "sendMessage - Trying to send message " | ||
3002 | << mCurrentSMessageName << " to dead circuit " | ||
3003 | << host << llendl; | ||
3004 | return 0; | ||
3005 | } | ||
3006 | } | ||
3007 | |||
3008 | memset(mSendBuffer,0,LL_PACKET_ID_SIZE); // zero out the packet ID field | ||
3009 | |||
3010 | // add the send id to the front of the message | ||
3011 | cdp->nextPacketOutID(); | ||
3012 | |||
3013 | // Packet ID size is always 4 | ||
3014 | *((S32*)&mSendBuffer[0]) = htonl(cdp->getPacketOutID()); | ||
3015 | |||
3016 | // Compress the message, which will usually reduce its size. | ||
3017 | U8 * buf_ptr = (U8 *)mSendBuffer; | ||
3018 | S32 buffer_length = mSendSize; | ||
3019 | if(ME_ZEROCODED == mCurrentSMessageTemplate->getEncoding()) | ||
3020 | { | ||
3021 | zeroCode(&buf_ptr, &buffer_length); | ||
3022 | } | ||
3023 | |||
3024 | if (buffer_length > 1500) | ||
3025 | { | ||
3026 | if((mCurrentSMessageName != _PREHASH_ChildAgentUpdate) | ||
3027 | && (mCurrentSMessageName != _PREHASH_SendXferPacket)) | ||
3028 | { | ||
3029 | llwarns << "sendMessage - Trying to send " | ||
3030 | << ((buffer_length > 4000) ? "EXTRA " : "") | ||
3031 | << "BIG message " << mCurrentSMessageName << " - " | ||
3032 | << buffer_length << llendl; | ||
3033 | } | ||
3034 | } | ||
3035 | if (mSendReliable) | ||
3036 | { | ||
3037 | buf_ptr[0] |= LL_RELIABLE_FLAG; | ||
3038 | |||
3039 | if (!cdp->getUnackedPacketCount()) | ||
3040 | { | ||
3041 | // We are adding the first packed onto the unacked packet list(s) | ||
3042 | // Add this circuit to the list of circuits with unacked packets | ||
3043 | mCircuitInfo.mUnackedCircuitMap[cdp->mHost] = cdp; | ||
3044 | } | ||
3045 | |||
3046 | cdp->addReliablePacket(mSocket,buf_ptr,buffer_length, &mReliablePacketParams); | ||
3047 | mReliablePacketsOut++; | ||
3048 | } | ||
3049 | |||
3050 | // tack packet acks onto the end of this message | ||
3051 | S32 space_left = (MTUBYTES - buffer_length) / sizeof(TPACKETID); // space left for packet ids | ||
3052 | S32 ack_count = (S32)cdp->mAcks.size(); | ||
3053 | BOOL is_ack_appended = FALSE; | ||
3054 | std::vector<TPACKETID> acks; | ||
3055 | if((space_left > 0) && (ack_count > 0) && | ||
3056 | (mCurrentSMessageName != _PREHASH_PacketAck)) | ||
3057 | { | ||
3058 | buf_ptr[0] |= LL_ACK_FLAG; | ||
3059 | S32 append_ack_count = llmin(space_left, ack_count); | ||
3060 | const S32 MAX_ACKS = 250; | ||
3061 | append_ack_count = llmin(append_ack_count, MAX_ACKS); | ||
3062 | std::vector<TPACKETID>::iterator iter = cdp->mAcks.begin(); | ||
3063 | std::vector<TPACKETID>::iterator last = cdp->mAcks.begin(); | ||
3064 | last += append_ack_count; | ||
3065 | TPACKETID packet_id; | ||
3066 | for( ; iter != last ; ++iter) | ||
3067 | { | ||
3068 | // grab the next packet id. | ||
3069 | packet_id = (*iter); | ||
3070 | if(mVerboseLog) | ||
3071 | { | ||
3072 | acks.push_back(packet_id); | ||
3073 | } | ||
3074 | |||
3075 | // put it on the end of the buffer | ||
3076 | packet_id = htonl(packet_id); | ||
3077 | |||
3078 | if((S32)(buffer_length + sizeof(TPACKETID)) < MAX_BUFFER_SIZE) | ||
3079 | { | ||
3080 | memcpy(&buf_ptr[buffer_length], &packet_id, sizeof(TPACKETID)); | ||
3081 | // Do the accounting | ||
3082 | buffer_length += sizeof(TPACKETID); | ||
3083 | } | ||
3084 | else | ||
3085 | { | ||
3086 | // Just reporting error is likely not enough. Need to | ||
3087 | // check how to abort or error out gracefully from | ||
3088 | // this function. XXXTBD | ||
3089 | // *NOTE: Actually hitting this error would indicate | ||
3090 | // the calculation above for space_left, ack_count, | ||
3091 | // append_acout_count is incorrect or that | ||
3092 | // MAX_BUFFER_SIZE has fallen below MTU which is bad | ||
3093 | // and probably programmer error. | ||
3094 | llerrs << "Buffer packing failed due to size.." << llendl; | ||
3095 | } | ||
3096 | } | ||
3097 | |||
3098 | // clean up the source | ||
3099 | cdp->mAcks.erase(cdp->mAcks.begin(), last); | ||
3100 | |||
3101 | // tack the count in the final byte | ||
3102 | U8 count = (U8)append_ack_count; | ||
3103 | buf_ptr[buffer_length++] = count; | ||
3104 | is_ack_appended = TRUE; | ||
3105 | } | ||
3106 | |||
3107 | BOOL success; | ||
3108 | success = mPacketRing.sendPacket(mSocket, (char *)buf_ptr, buffer_length, host); | ||
3109 | |||
3110 | if (!success) | ||
3111 | { | ||
3112 | mSendPacketFailureCount++; | ||
3113 | } | ||
3114 | else | ||
3115 | { | ||
3116 | // mCircuitInfo already points to the correct circuit data | ||
3117 | cdp->addBytesOut( buffer_length ); | ||
3118 | } | ||
3119 | |||
3120 | if(mVerboseLog) | ||
3121 | { | ||
3122 | std::ostringstream str; | ||
3123 | str << "MSG: -> " << host; | ||
3124 | char buffer[MAX_STRING]; /* Flawfinder: ignore */ | ||
3125 | snprintf(buffer, MAX_STRING, "\t%6d\t%6d\t%6d ", mSendSize, buffer_length, cdp->getPacketOutID()); /* Flawfinder: ignore */ | ||
3126 | str << buffer | ||
3127 | << mCurrentSMessageTemplate->mName | ||
3128 | << (mSendReliable ? " reliable " : ""); | ||
3129 | if(is_ack_appended) | ||
3130 | { | ||
3131 | str << "\tACKS:\t"; | ||
3132 | std::ostream_iterator<TPACKETID> append(str, " "); | ||
3133 | std::copy(acks.begin(), acks.end(), append); | ||
3134 | } | ||
3135 | llinfos << str.str() << llendl; | ||
3136 | } | ||
3137 | |||
3138 | lldebugst(LLERR_MESSAGE) << "MessageSent at: " << (S32)totalTime() | ||
3139 | << ", " << mCurrentSMessageTemplate->mName | ||
3140 | << " to " << host | ||
3141 | << llendl; | ||
3142 | |||
3143 | // ok, clean up temp data | ||
3144 | delete mCurrentSMessageData; | ||
3145 | mCurrentSMessageData = NULL; | ||
3146 | |||
3147 | mPacketsOut++; | ||
3148 | mBytesOut += buffer_length; | ||
3149 | |||
3150 | return buffer_length; | ||
3151 | } | ||
3152 | |||
3153 | |||
3154 | // Returns template for the message contained in buffer | ||
3155 | BOOL LLMessageSystem::decodeTemplate( | ||
3156 | const U8* buffer, S32 buffer_size, // inputs | ||
3157 | LLMessageTemplate** msg_template ) // outputs | ||
3158 | { | ||
3159 | const U8* header = buffer + LL_PACKET_ID_SIZE; | ||
3160 | |||
3161 | // is there a message ready to go? | ||
3162 | if (buffer_size <= 0) | ||
3163 | { | ||
3164 | llwarns << "No message waiting for decode!" << llendl; | ||
3165 | return(FALSE); | ||
3166 | } | ||
3167 | |||
3168 | U32 num = 0; | ||
3169 | |||
3170 | if (header[0] != 255) | ||
3171 | { | ||
3172 | // high frequency message | ||
3173 | num = header[0]; | ||
3174 | } | ||
3175 | else if ((buffer_size >= ((S32) LL_MINIMUM_VALID_PACKET_SIZE + 1)) && (header[1] != 255)) | ||
3176 | { | ||
3177 | // medium frequency message | ||
3178 | num = (255 << 8) | header[1]; | ||
3179 | } | ||
3180 | else if ((buffer_size >= ((S32) LL_MINIMUM_VALID_PACKET_SIZE + 3)) && (header[1] == 255)) | ||
3181 | { | ||
3182 | // low frequency message | ||
3183 | U16 message_id_U16 = 0; | ||
3184 | // I think this check busts the message system. | ||
3185 | // it appears that if there is a NULL in the message #, it won't copy it.... | ||
3186 | // what was the goal? | ||
3187 | //if(header[2]) | ||
3188 | memcpy(&message_id_U16, &header[2], 2); | ||
3189 | |||
3190 | // dependant on endian-ness: | ||
3191 | // U32 temp = (255 << 24) | (255 << 16) | header[2]; | ||
3192 | |||
3193 | // independant of endian-ness: | ||
3194 | message_id_U16 = ntohs(message_id_U16); | ||
3195 | num = 0xFFFF0000 | message_id_U16; | ||
3196 | } | ||
3197 | else // bogus packet received (too short) | ||
3198 | { | ||
3199 | llwarns << "Packet with unusable length received (too short): " | ||
3200 | << buffer_size << llendl; | ||
3201 | return(FALSE); | ||
3202 | } | ||
3203 | |||
3204 | LLMessageTemplate* temp = get_ptr_in_map(mMessageNumbers,num); | ||
3205 | if (temp) | ||
3206 | { | ||
3207 | *msg_template = temp; | ||
3208 | } | ||
3209 | else | ||
3210 | { | ||
3211 | llwarns << "Message #" << std::hex << num << std::dec | ||
3212 | << " received but not registered!" << llendl; | ||
3213 | callExceptionFunc(MX_UNREGISTERED_MESSAGE); | ||
3214 | return(FALSE); | ||
3215 | } | ||
3216 | |||
3217 | return(TRUE); | ||
3218 | } | ||
3219 | |||
3220 | |||
3221 | void LLMessageSystem::logMsgFromInvalidCircuit( const LLHost& host, BOOL recv_reliable ) | ||
3222 | { | ||
3223 | if(mVerboseLog) | ||
3224 | { | ||
3225 | std::ostringstream str; | ||
3226 | str << "MSG: <- " << host; | ||
3227 | char buffer[MAX_STRING]; /* Flawfinder: ignore */ | ||
3228 | snprintf(buffer, MAX_STRING, "\t%6d\t%6d\t%6d ", mReceiveSize, (mIncomingCompressedSize ? mIncomingCompressedSize: mReceiveSize), mCurrentRecvPacketID); /* Flawfinder: ignore */ | ||
3229 | str << buffer | ||
3230 | << mCurrentRMessageTemplate->mName | ||
3231 | << (recv_reliable ? " reliable" : "") | ||
3232 | << " REJECTED"; | ||
3233 | llinfos << str.str() << llendl; | ||
3234 | } | ||
3235 | // nope! | ||
3236 | // cout << "Rejecting unexpected message " << mCurrentMessageTemplate->mName << " from " << hex << ip << " , " << dec << port << endl; | ||
3237 | |||
3238 | // Keep track of rejected messages as well | ||
3239 | if (mNumMessageCounts >= MAX_MESSAGE_COUNT_NUM) | ||
3240 | { | ||
3241 | llwarns << "Got more than " << MAX_MESSAGE_COUNT_NUM << " packets without clearing counts" << llendl; | ||
3242 | } | ||
3243 | else | ||
3244 | { | ||
3245 | mMessageCountList[mNumMessageCounts].mMessageNum = mCurrentRMessageTemplate->mMessageNumber; | ||
3246 | mMessageCountList[mNumMessageCounts].mMessageBytes = mReceiveSize; | ||
3247 | mMessageCountList[mNumMessageCounts].mInvalid = TRUE; | ||
3248 | mNumMessageCounts++; | ||
3249 | } | ||
3250 | } | ||
3251 | |||
3252 | void LLMessageSystem::logTrustedMsgFromUntrustedCircuit( const LLHost& host ) | ||
3253 | { | ||
3254 | // RequestTrustedCircuit is how we establish trust, so don't spam | ||
3255 | // if it's received on a trusted circuit. JC | ||
3256 | if (strcmp(mCurrentRMessageTemplate->mName, "RequestTrustedCircuit")) | ||
3257 | { | ||
3258 | llwarns << "Received trusted message on untrusted circuit. " | ||
3259 | << "Will reply with deny. " | ||
3260 | << "Message: " << mCurrentRMessageTemplate->mName | ||
3261 | << " Host: " << host << llendl; | ||
3262 | } | ||
3263 | |||
3264 | if (mNumMessageCounts >= MAX_MESSAGE_COUNT_NUM) | ||
3265 | { | ||
3266 | llwarns << "got more than " << MAX_MESSAGE_COUNT_NUM | ||
3267 | << " packets without clearing counts" | ||
3268 | << llendl; | ||
3269 | } | ||
3270 | else | ||
3271 | { | ||
3272 | mMessageCountList[mNumMessageCounts].mMessageNum | ||
3273 | = mCurrentRMessageTemplate->mMessageNumber; | ||
3274 | mMessageCountList[mNumMessageCounts].mMessageBytes | ||
3275 | = mReceiveSize; | ||
3276 | mMessageCountList[mNumMessageCounts].mInvalid = TRUE; | ||
3277 | mNumMessageCounts++; | ||
3278 | } | ||
3279 | } | ||
3280 | |||
3281 | void LLMessageSystem::logValidMsg(LLCircuitData *cdp, const LLHost& host, BOOL recv_reliable, BOOL recv_resent, BOOL recv_acks ) | ||
3282 | { | ||
3283 | if (mNumMessageCounts >= MAX_MESSAGE_COUNT_NUM) | ||
3284 | { | ||
3285 | llwarns << "Got more than " << MAX_MESSAGE_COUNT_NUM << " packets without clearing counts" << llendl; | ||
3286 | } | ||
3287 | else | ||
3288 | { | ||
3289 | mMessageCountList[mNumMessageCounts].mMessageNum = mCurrentRMessageTemplate->mMessageNumber; | ||
3290 | mMessageCountList[mNumMessageCounts].mMessageBytes = mReceiveSize; | ||
3291 | mMessageCountList[mNumMessageCounts].mInvalid = FALSE; | ||
3292 | mNumMessageCounts++; | ||
3293 | } | ||
3294 | |||
3295 | if (cdp) | ||
3296 | { | ||
3297 | // update circuit packet ID tracking (missing/out of order packets) | ||
3298 | cdp->checkPacketInID( mCurrentRecvPacketID, recv_resent ); | ||
3299 | cdp->addBytesIn( mTrueReceiveSize ); | ||
3300 | } | ||
3301 | |||
3302 | if(mVerboseLog) | ||
3303 | { | ||
3304 | std::ostringstream str; | ||
3305 | str << "MSG: <- " << host; | ||
3306 | char buffer[MAX_STRING]; /* Flawfinder: ignore */ | ||
3307 | snprintf(buffer, MAX_STRING, "\t%6d\t%6d\t%6d ", mReceiveSize, (mIncomingCompressedSize ? mIncomingCompressedSize : mReceiveSize), mCurrentRecvPacketID); /* Flawfinder: ignore */ | ||
3308 | str << buffer | ||
3309 | << mCurrentRMessageTemplate->mName | ||
3310 | << (recv_reliable ? " reliable" : "") | ||
3311 | << (recv_resent ? " resent" : "") | ||
3312 | << (recv_acks ? " acks" : ""); | ||
3313 | llinfos << str.str() << llendl; | ||
3314 | } | ||
3315 | } | ||
3316 | |||
3317 | |||
3318 | void LLMessageSystem::logRanOffEndOfPacket( const LLHost& host ) | ||
3319 | { | ||
3320 | // we've run off the end of the packet! | ||
3321 | llwarns << "Ran off end of packet " << mCurrentRMessageTemplate->mName | ||
3322 | << " with id " << mCurrentRecvPacketID << " from " << host | ||
3323 | << llendl; | ||
3324 | if(mVerboseLog) | ||
3325 | { | ||
3326 | llinfos << "MSG: -> " << host << "\tREAD PAST END:\t" | ||
3327 | << mCurrentRecvPacketID << " " | ||
3328 | << mCurrentSMessageTemplate->mName << llendl; | ||
3329 | } | ||
3330 | callExceptionFunc(MX_RAN_OFF_END_OF_PACKET); | ||
3331 | } | ||
3332 | |||
3333 | |||
3334 | // decode a given message | ||
3335 | BOOL LLMessageSystem::decodeData(const U8* buffer, const LLHost& sender ) | ||
3336 | { | ||
3337 | llassert( mReceiveSize >= 0 ); | ||
3338 | llassert( mCurrentRMessageTemplate); | ||
3339 | llassert( !mCurrentRMessageData ); | ||
3340 | delete mCurrentRMessageData; // just to make sure | ||
3341 | |||
3342 | S32 decode_pos = LL_PACKET_ID_SIZE + (S32)(mCurrentRMessageTemplate->mFrequency); | ||
3343 | |||
3344 | // create base working data set | ||
3345 | mCurrentRMessageData = new LLMsgData(mCurrentRMessageTemplate->mName); | ||
3346 | |||
3347 | // loop through the template building the data structure as we go | ||
3348 | for (LLMessageTemplate::message_block_map_t::iterator iter = mCurrentRMessageTemplate->mMemberBlocks.begin(); | ||
3349 | iter != mCurrentRMessageTemplate->mMemberBlocks.end(); iter++) | ||
3350 | { | ||
3351 | LLMessageBlock* mbci = iter->second; | ||
3352 | U8 repeat_number; | ||
3353 | S32 i; | ||
3354 | |||
3355 | // how many of this block? | ||
3356 | |||
3357 | if (mbci->mType == MBT_SINGLE) | ||
3358 | { | ||
3359 | // just one | ||
3360 | repeat_number = 1; | ||
3361 | } | ||
3362 | else if (mbci->mType == MBT_MULTIPLE) | ||
3363 | { | ||
3364 | // a known number | ||
3365 | repeat_number = mbci->mNumber; | ||
3366 | } | ||
3367 | else if (mbci->mType == MBT_VARIABLE) | ||
3368 | { | ||
3369 | // need to read the number from the message | ||
3370 | // repeat number is a single byte | ||
3371 | if (decode_pos >= mReceiveSize) | ||
3372 | { | ||
3373 | logRanOffEndOfPacket( sender ); | ||
3374 | return FALSE; | ||
3375 | } | ||
3376 | repeat_number = buffer[decode_pos]; | ||
3377 | decode_pos++; | ||
3378 | } | ||
3379 | else | ||
3380 | { | ||
3381 | llerrs << "Unknown block type" << llendl; | ||
3382 | return FALSE; | ||
3383 | } | ||
3384 | |||
3385 | LLMsgBlkData* cur_data_block = NULL; | ||
3386 | |||
3387 | // now loop through the block | ||
3388 | for (i = 0; i < repeat_number; i++) | ||
3389 | { | ||
3390 | if (i) | ||
3391 | { | ||
3392 | // build new name to prevent collisions | ||
3393 | // TODO: This should really change to a vector | ||
3394 | cur_data_block = new LLMsgBlkData(mbci->mName, repeat_number); | ||
3395 | cur_data_block->mName = mbci->mName + i; | ||
3396 | } | ||
3397 | else | ||
3398 | { | ||
3399 | cur_data_block = new LLMsgBlkData(mbci->mName, repeat_number); | ||
3400 | } | ||
3401 | |||
3402 | // add the block to the message | ||
3403 | mCurrentRMessageData->addBlock(cur_data_block); | ||
3404 | |||
3405 | // now read the variables | ||
3406 | for (LLMessageBlock::message_variable_map_t::iterator iter = mbci->mMemberVariables.begin(); | ||
3407 | iter != mbci->mMemberVariables.end(); iter++) | ||
3408 | { | ||
3409 | LLMessageVariable& mvci = *(iter->second); | ||
3410 | // ok, build out the variables | ||
3411 | // add variable block | ||
3412 | cur_data_block->addVariable(mvci.getName(), mvci.getType()); | ||
3413 | |||
3414 | // what type of variable? | ||
3415 | if (mvci.getType() == MVT_VARIABLE) | ||
3416 | { | ||
3417 | // variable, get the number of bytes to read from the template | ||
3418 | S32 data_size = mvci.getSize(); | ||
3419 | U8 tsizeb = 0; | ||
3420 | U16 tsizeh = 0; | ||
3421 | U32 tsize = 0; | ||
3422 | |||
3423 | if ((decode_pos + data_size) > mReceiveSize) | ||
3424 | { | ||
3425 | logRanOffEndOfPacket( sender ); | ||
3426 | return FALSE; | ||
3427 | } | ||
3428 | switch(data_size) | ||
3429 | { | ||
3430 | case 1: | ||
3431 | htonmemcpy(&tsizeb, &buffer[decode_pos], MVT_U8, 1); | ||
3432 | tsize = tsizeb; | ||
3433 | break; | ||
3434 | case 2: | ||
3435 | htonmemcpy(&tsizeh, &buffer[decode_pos], MVT_U16, 2); | ||
3436 | tsize = tsizeh; | ||
3437 | break; | ||
3438 | case 4: | ||
3439 | htonmemcpy(&tsizeb, &buffer[decode_pos], MVT_U32, 4); | ||
3440 | break; | ||
3441 | default: | ||
3442 | llerrs << "Attempting to read variable field with unknown size of " << data_size << llendl; | ||
3443 | break; | ||
3444 | |||
3445 | } | ||
3446 | decode_pos += data_size; | ||
3447 | |||
3448 | if ((decode_pos + (S32)tsize) > mReceiveSize) | ||
3449 | { | ||
3450 | logRanOffEndOfPacket( sender ); | ||
3451 | return FALSE; | ||
3452 | } | ||
3453 | cur_data_block->addData(mvci.getName(), &buffer[decode_pos], tsize, mvci.getType()); | ||
3454 | decode_pos += tsize; | ||
3455 | } | ||
3456 | else | ||
3457 | { | ||
3458 | // fixed! | ||
3459 | // so, copy data pointer and set data size to fixed size | ||
3460 | |||
3461 | if ((decode_pos + mvci.getSize()) > mReceiveSize) | ||
3462 | { | ||
3463 | logRanOffEndOfPacket( sender ); | ||
3464 | return FALSE; | ||
3465 | } | ||
3466 | |||
3467 | cur_data_block->addData(mvci.getName(), &buffer[decode_pos], mvci.getSize(), mvci.getType()); | ||
3468 | decode_pos += mvci.getSize(); | ||
3469 | } | ||
3470 | } | ||
3471 | } | ||
3472 | } | ||
3473 | |||
3474 | if (mCurrentRMessageData->mMemberBlocks.empty() | ||
3475 | && !mCurrentRMessageTemplate->mMemberBlocks.empty()) | ||
3476 | { | ||
3477 | lldebugs << "Empty message '" << mCurrentRMessageTemplate->mName << "' (no blocks)" << llendl; | ||
3478 | return FALSE; | ||
3479 | } | ||
3480 | |||
3481 | { | ||
3482 | static LLTimer decode_timer; | ||
3483 | |||
3484 | if( mTimeDecodes ) | ||
3485 | { | ||
3486 | decode_timer.reset(); | ||
3487 | } | ||
3488 | |||
3489 | // if( mCurrentRMessageTemplate->mName == _PREHASH_AgentToNewRegion ) | ||
3490 | // { | ||
3491 | // VTResume(); // VTune | ||
3492 | // } | ||
3493 | |||
3494 | { | ||
3495 | LLFastTimer t(LLFastTimer::FTM_PROCESS_MESSAGES); | ||
3496 | if( !mCurrentRMessageTemplate->callHandlerFunc(this) ) | ||
3497 | { | ||
3498 | llwarns << "Message from " << sender << " with no handler function received: " << mCurrentRMessageTemplate->mName << llendl; | ||
3499 | } | ||
3500 | } | ||
3501 | |||
3502 | // if( mCurrentRMessageTemplate->mName == _PREHASH_AgentToNewRegion ) | ||
3503 | // { | ||
3504 | // VTPause(); // VTune | ||
3505 | // } | ||
3506 | |||
3507 | if( mTimeDecodes ) | ||
3508 | { | ||
3509 | F32 decode_time = decode_timer.getElapsedTimeF32(); | ||
3510 | mCurrentRMessageTemplate->mDecodeTimeThisFrame += decode_time; | ||
3511 | |||
3512 | mCurrentRMessageTemplate->mTotalDecoded++; | ||
3513 | mCurrentRMessageTemplate->mTotalDecodeTime += decode_time; | ||
3514 | |||
3515 | if( mCurrentRMessageTemplate->mMaxDecodeTimePerMsg < decode_time ) | ||
3516 | { | ||
3517 | mCurrentRMessageTemplate->mMaxDecodeTimePerMsg = decode_time; | ||
3518 | } | ||
3519 | |||
3520 | |||
3521 | if( decode_time > mTimeDecodesSpamThreshold ) | ||
3522 | { | ||
3523 | lldebugs << "--------- Message " << mCurrentRMessageTemplate->mName << " decode took " << decode_time << " seconds. (" << | ||
3524 | mCurrentRMessageTemplate->mMaxDecodeTimePerMsg << " max, " << | ||
3525 | (mCurrentRMessageTemplate->mTotalDecodeTime / mCurrentRMessageTemplate->mTotalDecoded) << " avg)" << llendl; | ||
3526 | } | ||
3527 | } | ||
3528 | } | ||
3529 | return TRUE; | ||
3530 | } | ||
3531 | |||
3532 | void LLMessageSystem::getDataFast(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum, S32 max_size) | ||
3533 | { | ||
3534 | // is there a message ready to go? | ||
3535 | if (mReceiveSize == -1) | ||
3536 | { | ||
3537 | llerrs << "No message waiting for decode 2!" << llendl; | ||
3538 | return; | ||
3539 | } | ||
3540 | |||
3541 | if (!mCurrentRMessageData) | ||
3542 | { | ||
3543 | llerrs << "Invalid mCurrentMessageData in getData!" << llendl; | ||
3544 | return; | ||
3545 | } | ||
3546 | |||
3547 | char *bnamep = (char *)blockname + blocknum; // this works because it's just a hash. The bnamep is never derefference | ||
3548 | char *vnamep = (char *)varname; | ||
3549 | |||
3550 | LLMsgData::msg_blk_data_map_t::iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep); | ||
3551 | |||
3552 | if (iter == mCurrentRMessageData->mMemberBlocks.end()) | ||
3553 | { | ||
3554 | llerrs << "Block " << blockname << " #" << blocknum | ||
3555 | << " not in message " << mCurrentRMessageData->mName << llendl; | ||
3556 | return; | ||
3557 | } | ||
3558 | |||
3559 | LLMsgBlkData *msg_block_data = iter->second; | ||
3560 | LLMsgVarData& vardata = msg_block_data->mMemberVarData[vnamep]; | ||
3561 | |||
3562 | if (!vardata.getName()) | ||
3563 | { | ||
3564 | llerrs << "Variable "<< vnamep << " not in message " | ||
3565 | << mCurrentRMessageData->mName<< " block " << bnamep << llendl; | ||
3566 | return; | ||
3567 | } | ||
3568 | |||
3569 | if (size && size != vardata.getSize()) | ||
3570 | { | ||
3571 | llerrs << "Msg " << mCurrentRMessageData->mName | ||
3572 | << " variable " << vnamep | ||
3573 | << " is size " << vardata.getSize() | ||
3574 | << " but copying into buffer of size " << size | ||
3575 | << llendl; | ||
3576 | return; | ||
3577 | } | ||
3578 | |||
3579 | |||
3580 | const S32 vardata_size = vardata.getSize(); | ||
3581 | if( max_size >= vardata_size ) | ||
3582 | { | ||
3583 | switch( vardata_size ) | ||
3584 | { | ||
3585 | case 1: | ||
3586 | *((U8*)datap) = *((U8*)vardata.getData()); | ||
3587 | break; | ||
3588 | case 2: | ||
3589 | *((U16*)datap) = *((U16*)vardata.getData()); | ||
3590 | break; | ||
3591 | case 4: | ||
3592 | *((U32*)datap) = *((U32*)vardata.getData()); | ||
3593 | break; | ||
3594 | case 8: | ||
3595 | ((U32*)datap)[0] = ((U32*)vardata.getData())[0]; | ||
3596 | ((U32*)datap)[1] = ((U32*)vardata.getData())[1]; | ||
3597 | break; | ||
3598 | default: | ||
3599 | memcpy(datap, vardata.getData(), vardata_size); | ||
3600 | break; | ||
3601 | } | ||
3602 | } | ||
3603 | else | ||
3604 | { | ||
3605 | llwarns << "Msg " << mCurrentRMessageData->mName | ||
3606 | << " variable " << vnamep | ||
3607 | << " is size " << vardata.getSize() | ||
3608 | << " but truncated to max size of " << max_size | ||
3609 | << llendl; | ||
3610 | |||
3611 | memcpy(datap, vardata.getData(), max_size); | ||
3612 | } | ||
3613 | } | ||
3614 | |||
3615 | S32 LLMessageSystem::getNumberOfBlocksFast(const char *blockname) | ||
3616 | { | ||
3617 | // is there a message ready to go? | ||
3618 | if (mReceiveSize == -1) | ||
3619 | { | ||
3620 | llerrs << "No message waiting for decode 3!" << llendl; | ||
3621 | return -1; | ||
3622 | } | ||
3623 | |||
3624 | if (!mCurrentRMessageData) | ||
3625 | { | ||
3626 | llerrs << "Invalid mCurrentRMessageData in getData!" << llendl; | ||
3627 | return -1; | ||
3628 | } | ||
3629 | |||
3630 | char *bnamep = (char *)blockname; | ||
3631 | |||
3632 | LLMsgData::msg_blk_data_map_t::iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep); | ||
3633 | |||
3634 | if (iter == mCurrentRMessageData->mMemberBlocks.end()) | ||
3635 | { | ||
3636 | // sprintf(errmsg, "Block %s not in message %s", bnamep, mCurrentRMessageData->mName); | ||
3637 | // llerrs << errmsg << llendl; | ||
3638 | // return -1; | ||
3639 | return 0; | ||
3640 | } | ||
3641 | |||
3642 | return (iter->second)->mBlockNumber; | ||
3643 | } | ||
3644 | |||
3645 | S32 LLMessageSystem::getSizeFast(const char *blockname, const char *varname) | ||
3646 | { | ||
3647 | // is there a message ready to go? | ||
3648 | if (mReceiveSize == -1) | ||
3649 | { | ||
3650 | llerrs << "No message waiting for decode 4!" << llendl; | ||
3651 | return -1; | ||
3652 | } | ||
3653 | |||
3654 | if (!mCurrentRMessageData) | ||
3655 | { | ||
3656 | llerrs << "Invalid mCurrentRMessageData in getData!" << llendl; | ||
3657 | return -1; | ||
3658 | } | ||
3659 | |||
3660 | char *bnamep = (char *)blockname; | ||
3661 | |||
3662 | LLMsgData::msg_blk_data_map_t::iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep); | ||
3663 | |||
3664 | if (iter == mCurrentRMessageData->mMemberBlocks.end()) | ||
3665 | { | ||
3666 | llerrs << "Block " << bnamep << " not in message " | ||
3667 | << mCurrentRMessageData->mName << llendl; | ||
3668 | return -1; | ||
3669 | } | ||
3670 | |||
3671 | char *vnamep = (char *)varname; | ||
3672 | |||
3673 | LLMsgBlkData* msg_data = iter->second; | ||
3674 | LLMsgVarData& vardata = msg_data->mMemberVarData[vnamep]; | ||
3675 | |||
3676 | if (!vardata.getName()) | ||
3677 | { | ||
3678 | llerrs << "Variable " << varname << " not in message " | ||
3679 | << mCurrentRMessageData->mName << " block " << bnamep << llendl; | ||
3680 | return -1; | ||
3681 | } | ||
3682 | |||
3683 | if (mCurrentRMessageTemplate->mMemberBlocks[bnamep]->mType != MBT_SINGLE) | ||
3684 | { | ||
3685 | llerrs << "Block " << bnamep << " isn't type MBT_SINGLE," | ||
3686 | " use getSize with blocknum argument!" << llendl; | ||
3687 | return -1; | ||
3688 | } | ||
3689 | |||
3690 | return vardata.getSize(); | ||
3691 | } | ||
3692 | |||
3693 | |||
3694 | S32 LLMessageSystem::getSizeFast(const char *blockname, S32 blocknum, const char *varname) | ||
3695 | { | ||
3696 | // is there a message ready to go? | ||
3697 | if (mReceiveSize == -1) | ||
3698 | { | ||
3699 | llerrs << "No message waiting for decode 5!" << llendl; | ||
3700 | return -1; | ||
3701 | } | ||
3702 | |||
3703 | if (!mCurrentRMessageData) | ||
3704 | { | ||
3705 | llerrs << "Invalid mCurrentRMessageData in getData!" << llendl; | ||
3706 | return -1; | ||
3707 | } | ||
3708 | |||
3709 | char *bnamep = (char *)blockname + blocknum; | ||
3710 | char *vnamep = (char *)varname; | ||
3711 | |||
3712 | LLMsgData::msg_blk_data_map_t::iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep); | ||
3713 | |||
3714 | if (iter == mCurrentRMessageData->mMemberBlocks.end()) | ||
3715 | { | ||
3716 | llerrs << "Block " << bnamep << " not in message " | ||
3717 | << mCurrentRMessageData->mName << llendl; | ||
3718 | return -1; | ||
3719 | } | ||
3720 | |||
3721 | LLMsgBlkData* msg_data = iter->second; | ||
3722 | LLMsgVarData& vardata = msg_data->mMemberVarData[vnamep]; | ||
3723 | |||
3724 | if (!vardata.getName()) | ||
3725 | { | ||
3726 | llerrs << "Variable " << vnamep << " not in message " | ||
3727 | << mCurrentRMessageData->mName << " block " << bnamep << llendl; | ||
3728 | return -1; | ||
3729 | } | ||
3730 | |||
3731 | return vardata.getSize(); | ||
3732 | } | ||
3733 | |||
3734 | |||
3735 | void LLMessageSystem::sanityCheck() | ||
3736 | { | ||
3737 | if (!mCurrentRMessageData) | ||
3738 | { | ||
3739 | llerrs << "mCurrentRMessageData is NULL" << llendl; | ||
3740 | } | ||
3741 | |||
3742 | if (!mCurrentRMessageTemplate) | ||
3743 | { | ||
3744 | llerrs << "mCurrentRMessageTemplate is NULL" << llendl; | ||
3745 | } | ||
3746 | |||
3747 | // if (!mCurrentRTemplateBlock) | ||
3748 | // { | ||
3749 | // llerrs << "mCurrentRTemplateBlock is NULL" << llendl; | ||
3750 | // } | ||
3751 | |||
3752 | // if (!mCurrentRDataBlock) | ||
3753 | // { | ||
3754 | // llerrs << "mCurrentRDataBlock is NULL" << llendl; | ||
3755 | // } | ||
3756 | |||
3757 | if (!mCurrentSMessageData) | ||
3758 | { | ||
3759 | llerrs << "mCurrentSMessageData is NULL" << llendl; | ||
3760 | } | ||
3761 | |||
3762 | if (!mCurrentSMessageTemplate) | ||
3763 | { | ||
3764 | llerrs << "mCurrentSMessageTemplate is NULL" << llendl; | ||
3765 | } | ||
3766 | |||
3767 | // if (!mCurrentSTemplateBlock) | ||
3768 | // { | ||
3769 | // llerrs << "mCurrentSTemplateBlock is NULL" << llendl; | ||
3770 | // } | ||
3771 | |||
3772 | if (!mCurrentSDataBlock) | ||
3773 | { | ||
3774 | llerrs << "mCurrentSDataBlock is NULL" << llendl; | ||
3775 | } | ||
3776 | } | ||
3777 | |||
3778 | void LLMessageSystem::showCircuitInfo() | ||
3779 | { | ||
3780 | llinfos << mCircuitInfo << llendl; | ||
3781 | } | ||
3782 | |||
3783 | |||
3784 | void LLMessageSystem::dumpCircuitInfo() | ||
3785 | { | ||
3786 | lldebugst(LLERR_CIRCUIT_INFO) << mCircuitInfo << llendl; | ||
3787 | } | ||
3788 | |||
3789 | /* virtual */ | ||
3790 | U32 LLMessageSystem::getOurCircuitCode() | ||
3791 | { | ||
3792 | return mOurCircuitCode; | ||
3793 | } | ||
3794 | |||
3795 | LLString LLMessageSystem::getCircuitInfoString() | ||
3796 | { | ||
3797 | LLString info_string; | ||
3798 | |||
3799 | info_string += mCircuitInfo.getInfoString(); | ||
3800 | return info_string; | ||
3801 | } | ||
3802 | |||
3803 | // returns whether the given host is on a trusted circuit | ||
3804 | BOOL LLMessageSystem::getCircuitTrust(const LLHost &host) | ||
3805 | { | ||
3806 | LLCircuitData *cdp = mCircuitInfo.findCircuit(host); | ||
3807 | if (cdp) | ||
3808 | { | ||
3809 | return cdp->getTrusted(); | ||
3810 | } | ||
3811 | |||
3812 | return FALSE; | ||
3813 | } | ||
3814 | |||
3815 | // Activate a circuit, and set its trust level (TRUE if trusted, | ||
3816 | // FALSE if not). | ||
3817 | void LLMessageSystem::enableCircuit(const LLHost &host, BOOL trusted) | ||
3818 | { | ||
3819 | LLCircuitData *cdp = mCircuitInfo.findCircuit(host); | ||
3820 | if (!cdp) | ||
3821 | { | ||
3822 | cdp = mCircuitInfo.addCircuitData(host, 0); | ||
3823 | } | ||
3824 | else | ||
3825 | { | ||
3826 | cdp->setAlive(TRUE); | ||
3827 | } | ||
3828 | cdp->setTrusted(trusted); | ||
3829 | } | ||
3830 | |||
3831 | void LLMessageSystem::disableCircuit(const LLHost &host) | ||
3832 | { | ||
3833 | llinfos << "LLMessageSystem::disableCircuit for " << host << llendl; | ||
3834 | U32 code = gMessageSystem->findCircuitCode( host ); | ||
3835 | |||
3836 | // Don't need to do this, as we're removing the circuit info anyway - djs 01/28/03 | ||
3837 | |||
3838 | // don't clean up 0 circuit code entries | ||
3839 | // because many hosts (neighbor sims, etc) can have the 0 circuit | ||
3840 | if (code) | ||
3841 | { | ||
3842 | //if (mCircuitCodes.checkKey(code)) | ||
3843 | code_session_map_t::iterator it = mCircuitCodes.find(code); | ||
3844 | if(it != mCircuitCodes.end()) | ||
3845 | { | ||
3846 | llinfos << "Circuit " << code << " removed from list" << llendl; | ||
3847 | //mCircuitCodes.removeData(code); | ||
3848 | mCircuitCodes.erase(it); | ||
3849 | } | ||
3850 | |||
3851 | U64 ip_port = 0; | ||
3852 | std::map<U32, U64>::iterator iter = gMessageSystem->mCircuitCodeToIPPort.find(code); | ||
3853 | if (iter != gMessageSystem->mCircuitCodeToIPPort.end()) | ||
3854 | { | ||
3855 | ip_port = iter->second; | ||
3856 | |||
3857 | gMessageSystem->mCircuitCodeToIPPort.erase(iter); | ||
3858 | |||
3859 | U32 old_port = (U32)(ip_port & (U64)0xFFFFFFFF); | ||
3860 | U32 old_ip = (U32)(ip_port >> 32); | ||
3861 | |||
3862 | llinfos << "Host " << LLHost(old_ip, old_port) << " circuit " << code << " removed from lookup table" << llendl; | ||
3863 | gMessageSystem->mIPPortToCircuitCode.erase(ip_port); | ||
3864 | } | ||
3865 | } | ||
3866 | else | ||
3867 | { | ||
3868 | // Sigh, since we can open circuits which don't have circuit | ||
3869 | // codes, it's possible for this to happen... | ||
3870 | |||
3871 | //llwarns << "Couldn't find circuit code for " << host << llendl; | ||
3872 | } | ||
3873 | |||
3874 | mCircuitInfo.removeCircuitData(host); | ||
3875 | } | ||
3876 | |||
3877 | |||
3878 | void LLMessageSystem::setCircuitAllowTimeout(const LLHost &host, BOOL allow) | ||
3879 | { | ||
3880 | LLCircuitData *cdp = mCircuitInfo.findCircuit(host); | ||
3881 | if (cdp) | ||
3882 | { | ||
3883 | cdp->setAllowTimeout(allow); | ||
3884 | } | ||
3885 | } | ||
3886 | |||
3887 | void LLMessageSystem::setCircuitTimeoutCallback(const LLHost &host, void (*callback_func)(const LLHost & host, void *user_data), void *user_data) | ||
3888 | { | ||
3889 | LLCircuitData *cdp = mCircuitInfo.findCircuit(host); | ||
3890 | if (cdp) | ||
3891 | { | ||
3892 | cdp->setTimeoutCallback(callback_func, user_data); | ||
3893 | } | ||
3894 | } | ||
3895 | |||
3896 | |||
3897 | BOOL LLMessageSystem::checkCircuitBlocked(const U32 circuit) | ||
3898 | { | ||
3899 | LLHost host = findHost(circuit); | ||
3900 | |||
3901 | if (!host.isOk()) | ||
3902 | { | ||
3903 | //llinfos << "checkCircuitBlocked: Unknown circuit " << circuit << llendl; | ||
3904 | return TRUE; | ||
3905 | } | ||
3906 | |||
3907 | LLCircuitData *cdp = mCircuitInfo.findCircuit(host); | ||
3908 | if (cdp) | ||
3909 | { | ||
3910 | return cdp->isBlocked(); | ||
3911 | } | ||
3912 | else | ||
3913 | { | ||
3914 | llinfos << "checkCircuitBlocked(circuit): Unknown host - " << host << llendl; | ||
3915 | return FALSE; | ||
3916 | } | ||
3917 | } | ||
3918 | |||
3919 | BOOL LLMessageSystem::checkCircuitAlive(const U32 circuit) | ||
3920 | { | ||
3921 | LLHost host = findHost(circuit); | ||
3922 | |||
3923 | if (!host.isOk()) | ||
3924 | { | ||
3925 | //llinfos << "checkCircuitAlive: Unknown circuit " << circuit << llendl; | ||
3926 | return FALSE; | ||
3927 | } | ||
3928 | |||
3929 | LLCircuitData *cdp = mCircuitInfo.findCircuit(host); | ||
3930 | if (cdp) | ||
3931 | { | ||
3932 | return cdp->isAlive(); | ||
3933 | } | ||
3934 | else | ||
3935 | { | ||
3936 | llinfos << "checkCircuitAlive(circuit): Unknown host - " << host << llendl; | ||
3937 | return FALSE; | ||
3938 | } | ||
3939 | } | ||
3940 | |||
3941 | BOOL LLMessageSystem::checkCircuitAlive(const LLHost &host) | ||
3942 | { | ||
3943 | LLCircuitData *cdp = mCircuitInfo.findCircuit(host); | ||
3944 | if (cdp) | ||
3945 | { | ||
3946 | return cdp->isAlive(); | ||
3947 | } | ||
3948 | else | ||
3949 | { | ||
3950 | //llinfos << "checkCircuitAlive(host): Unknown host - " << host << llendl; | ||
3951 | return FALSE; | ||
3952 | } | ||
3953 | } | ||
3954 | |||
3955 | |||
3956 | void LLMessageSystem::setCircuitProtection(BOOL b_protect) | ||
3957 | { | ||
3958 | mbProtected = b_protect; | ||
3959 | } | ||
3960 | |||
3961 | |||
3962 | U32 LLMessageSystem::findCircuitCode(const LLHost &host) | ||
3963 | { | ||
3964 | U64 ip64 = (U64) host.getAddress(); | ||
3965 | U64 port64 = (U64) host.getPort(); | ||
3966 | U64 ip_port = (ip64 << 32) | port64; | ||
3967 | |||
3968 | return get_if_there(mIPPortToCircuitCode, ip_port, U32(0)); | ||
3969 | } | ||
3970 | |||
3971 | LLHost LLMessageSystem::findHost(const U32 circuit_code) | ||
3972 | { | ||
3973 | if (mCircuitCodeToIPPort.count(circuit_code) > 0) | ||
3974 | { | ||
3975 | return LLHost(mCircuitCodeToIPPort[circuit_code]); | ||
3976 | } | ||
3977 | else | ||
3978 | { | ||
3979 | return LLHost::invalid; | ||
3980 | } | ||
3981 | } | ||
3982 | |||
3983 | void LLMessageSystem::setMaxMessageTime(const F32 seconds) | ||
3984 | { | ||
3985 | mMaxMessageTime = seconds; | ||
3986 | } | ||
3987 | |||
3988 | void LLMessageSystem::setMaxMessageCounts(const S32 num) | ||
3989 | { | ||
3990 | mMaxMessageCounts = num; | ||
3991 | } | ||
3992 | |||
3993 | |||
3994 | std::ostream& operator<<(std::ostream& s, LLMessageSystem &msg) | ||
3995 | { | ||
3996 | U32 i; | ||
3997 | if (msg.mbError) | ||
3998 | { | ||
3999 | s << "Message system not correctly initialized"; | ||
4000 | } | ||
4001 | else | ||
4002 | { | ||
4003 | s << "Message system open on port " << msg.mPort << " and socket " << msg.mSocket << "\n"; | ||
4004 | // s << "Message template file " << msg.mName << " loaded\n"; | ||
4005 | |||
4006 | s << "\nHigh frequency messages:\n"; | ||
4007 | |||
4008 | for (i = 1; msg.mMessageNumbers[i] && (i < 255); i++) | ||
4009 | { | ||
4010 | s << *(msg.mMessageNumbers[i]); | ||
4011 | } | ||
4012 | |||
4013 | s << "\nMedium frequency messages:\n"; | ||
4014 | |||
4015 | for (i = (255 << 8) + 1; msg.mMessageNumbers[i] && (i < (255 << 8) + 255); i++) | ||
4016 | { | ||
4017 | s << *msg.mMessageNumbers[i]; | ||
4018 | } | ||
4019 | |||
4020 | s << "\nLow frequency messages:\n"; | ||
4021 | |||
4022 | for (i = (0xFFFF0000) + 1; msg.mMessageNumbers[i] && (i < 0xFFFFFFFF); i++) | ||
4023 | { | ||
4024 | s << *msg.mMessageNumbers[i]; | ||
4025 | } | ||
4026 | } | ||
4027 | return s; | ||
4028 | } | ||
4029 | |||
4030 | LLMessageSystem *gMessageSystem = NULL; | ||
4031 | |||
4032 | // update appropriate ping info | ||
4033 | void process_complete_ping_check(LLMessageSystem *msgsystem, void** /*user_data*/) | ||
4034 | { | ||
4035 | U8 ping_id; | ||
4036 | msgsystem->getU8Fast(_PREHASH_PingID, _PREHASH_PingID, ping_id); | ||
4037 | |||
4038 | LLCircuitData *cdp; | ||
4039 | cdp = msgsystem->mCircuitInfo.findCircuit(msgsystem->getSender()); | ||
4040 | |||
4041 | // stop the appropriate timer | ||
4042 | if (cdp) | ||
4043 | { | ||
4044 | cdp->pingTimerStop(ping_id); | ||
4045 | } | ||
4046 | } | ||
4047 | |||
4048 | void process_start_ping_check(LLMessageSystem *msgsystem, void** /*user_data*/) | ||
4049 | { | ||
4050 | U8 ping_id; | ||
4051 | msgsystem->getU8Fast(_PREHASH_PingID, _PREHASH_PingID, ping_id); | ||
4052 | |||
4053 | LLCircuitData *cdp; | ||
4054 | cdp = msgsystem->mCircuitInfo.findCircuit(msgsystem->getSender()); | ||
4055 | if (cdp) | ||
4056 | { | ||
4057 | // Grab the packet id of the oldest unacked packet | ||
4058 | U32 packet_id; | ||
4059 | msgsystem->getU32Fast(_PREHASH_PingID, _PREHASH_OldestUnacked, packet_id); | ||
4060 | cdp->clearDuplicateList(packet_id); | ||
4061 | } | ||
4062 | |||
4063 | // Send off the response | ||
4064 | msgsystem->newMessageFast(_PREHASH_CompletePingCheck); | ||
4065 | msgsystem->nextBlockFast(_PREHASH_PingID); | ||
4066 | msgsystem->addU8(_PREHASH_PingID, ping_id); | ||
4067 | msgsystem->sendMessage(msgsystem->getSender()); | ||
4068 | } | ||
4069 | |||
4070 | |||
4071 | |||
4072 | // Note: this is currently unused. --mark | ||
4073 | void open_circuit(LLMessageSystem *msgsystem, void** /*user_data*/) | ||
4074 | { | ||
4075 | U32 ip; | ||
4076 | U16 port; | ||
4077 | |||
4078 | msgsystem->getIPAddrFast(_PREHASH_CircuitInfo, _PREHASH_IP, ip); | ||
4079 | msgsystem->getIPPortFast(_PREHASH_CircuitInfo, _PREHASH_Port, port); | ||
4080 | |||
4081 | // By default, OpenCircuit's are untrusted | ||
4082 | msgsystem->enableCircuit(LLHost(ip, port), FALSE); | ||
4083 | } | ||
4084 | |||
4085 | void close_circuit(LLMessageSystem *msgsystem, void** /*user_data*/) | ||
4086 | { | ||
4087 | msgsystem->disableCircuit(msgsystem->getSender()); | ||
4088 | } | ||
4089 | |||
4090 | // static | ||
4091 | /* | ||
4092 | void LLMessageSystem::processAssignCircuitCode(LLMessageSystem* msg, void**) | ||
4093 | { | ||
4094 | // if we already have a circuit code, we can bail | ||
4095 | if(msg->mOurCircuitCode) return; | ||
4096 | LLUUID session_id; | ||
4097 | msg->getUUIDFast(_PREHASH_CircuitCode, _PREHASH_SessionID, session_id); | ||
4098 | if(session_id != msg->getMySessionID()) | ||
4099 | { | ||
4100 | llwarns << "AssignCircuitCode, bad session id. Expecting " | ||
4101 | << msg->getMySessionID() << " but got " << session_id | ||
4102 | << llendl; | ||
4103 | return; | ||
4104 | } | ||
4105 | U32 code; | ||
4106 | msg->getU32Fast(_PREHASH_CircuitCode, _PREHASH_Code, code); | ||
4107 | if (!code) | ||
4108 | { | ||
4109 | llerrs << "Assigning circuit code of zero!" << llendl; | ||
4110 | } | ||
4111 | |||
4112 | msg->mOurCircuitCode = code; | ||
4113 | llinfos << "Circuit code " << code << " assigned." << llendl; | ||
4114 | } | ||
4115 | */ | ||
4116 | |||
4117 | // static | ||
4118 | void LLMessageSystem::processAddCircuitCode(LLMessageSystem* msg, void**) | ||
4119 | { | ||
4120 | U32 code; | ||
4121 | msg->getU32Fast(_PREHASH_CircuitCode, _PREHASH_Code, code); | ||
4122 | LLUUID session_id; | ||
4123 | msg->getUUIDFast(_PREHASH_CircuitCode, _PREHASH_SessionID, session_id); | ||
4124 | (void)msg->addCircuitCode(code, session_id); | ||
4125 | |||
4126 | // Send the ack back | ||
4127 | //msg->newMessageFast(_PREHASH_AckAddCircuitCode); | ||
4128 | //msg->nextBlockFast(_PREHASH_CircuitCode); | ||
4129 | //msg->addU32Fast(_PREHASH_Code, code); | ||
4130 | //msg->sendMessage(msg->getSender()); | ||
4131 | } | ||
4132 | |||
4133 | bool LLMessageSystem::addCircuitCode(U32 code, const LLUUID& session_id) | ||
4134 | { | ||
4135 | if(!code) | ||
4136 | { | ||
4137 | llwarns << "addCircuitCode: zero circuit code" << llendl; | ||
4138 | return false; | ||
4139 | } | ||
4140 | code_session_map_t::iterator it = mCircuitCodes.find(code); | ||
4141 | if(it == mCircuitCodes.end()) | ||
4142 | { | ||
4143 | llinfos << "New circuit code " << code << " added" << llendl; | ||
4144 | //msg->mCircuitCodes[circuit_code] = circuit_code; | ||
4145 | |||
4146 | mCircuitCodes.insert(code_session_map_t::value_type(code, session_id)); | ||
4147 | } | ||
4148 | else | ||
4149 | { | ||
4150 | llinfos << "Duplicate circuit code " << code << " added" << llendl; | ||
4151 | } | ||
4152 | return true; | ||
4153 | } | ||
4154 | |||
4155 | //void ack_add_circuit_code(LLMessageSystem *msgsystem, void** /*user_data*/) | ||
4156 | //{ | ||
4157 | // By default, we do nothing. This particular message is only handled by the spaceserver | ||
4158 | //} | ||
4159 | |||
4160 | // static | ||
4161 | void LLMessageSystem::processUseCircuitCode(LLMessageSystem* msg, void**) | ||
4162 | { | ||
4163 | U32 circuit_code_in; | ||
4164 | msg->getU32Fast(_PREHASH_CircuitCode, _PREHASH_Code, circuit_code_in); | ||
4165 | |||
4166 | U32 ip = msg->getSenderIP(); | ||
4167 | U32 port = msg->getSenderPort(); | ||
4168 | |||
4169 | U64 ip64 = ip; | ||
4170 | U64 port64 = port; | ||
4171 | U64 ip_port_in = (ip64 << 32) | port64; | ||
4172 | |||
4173 | if (circuit_code_in) | ||
4174 | { | ||
4175 | //if (!msg->mCircuitCodes.checkKey(circuit_code_in)) | ||
4176 | code_session_map_t::iterator it; | ||
4177 | it = msg->mCircuitCodes.find(circuit_code_in); | ||
4178 | if(it == msg->mCircuitCodes.end()) | ||
4179 | { | ||
4180 | // Whoah, abort! We don't know anything about this circuit code. | ||
4181 | llwarns << "UseCircuitCode for " << circuit_code_in | ||
4182 | << " received without AddCircuitCode message - aborting" | ||
4183 | << llendl; | ||
4184 | return; | ||
4185 | } | ||
4186 | |||
4187 | LLUUID id; | ||
4188 | msg->getUUIDFast(_PREHASH_CircuitCode, _PREHASH_ID, id); | ||
4189 | LLUUID session_id; | ||
4190 | msg->getUUIDFast(_PREHASH_CircuitCode, _PREHASH_SessionID, session_id); | ||
4191 | if(session_id != (*it).second) | ||
4192 | { | ||
4193 | llwarns << "UseCircuitCode unmatched session id. Got " | ||
4194 | << session_id << " but expected " << (*it).second | ||
4195 | << llendl; | ||
4196 | return; | ||
4197 | } | ||
4198 | |||
4199 | // Clean up previous references to this ip/port or circuit | ||
4200 | U64 ip_port_old = get_if_there(msg->mCircuitCodeToIPPort, circuit_code_in, U64(0)); | ||
4201 | U32 circuit_code_old = get_if_there(msg->mIPPortToCircuitCode, ip_port_in, U32(0)); | ||
4202 | |||
4203 | if (ip_port_old) | ||
4204 | { | ||
4205 | if ((ip_port_old == ip_port_in) && (circuit_code_old == circuit_code_in)) | ||
4206 | { | ||
4207 | // Current information is the same as incoming info, ignore | ||
4208 | llinfos << "Got duplicate UseCircuitCode for circuit " << circuit_code_in << " to " << msg->getSender() << llendl; | ||
4209 | return; | ||
4210 | } | ||
4211 | |||
4212 | // Hmm, got a different IP and port for the same circuit code. | ||
4213 | U32 circut_code_old_ip_port = get_if_there(msg->mIPPortToCircuitCode, ip_port_old, U32(0)); | ||
4214 | msg->mCircuitCodeToIPPort.erase(circut_code_old_ip_port); | ||
4215 | msg->mIPPortToCircuitCode.erase(ip_port_old); | ||
4216 | U32 old_port = (U32)(ip_port_old & (U64)0xFFFFFFFF); | ||
4217 | U32 old_ip = (U32)(ip_port_old >> 32); | ||
4218 | llinfos << "Removing derelict lookup entry for circuit " << circuit_code_old << " to " << LLHost(old_ip, old_port) << llendl; | ||
4219 | } | ||
4220 | |||
4221 | if (circuit_code_old) | ||
4222 | { | ||
4223 | LLHost cur_host(ip, port); | ||
4224 | |||
4225 | llwarns << "Disabling existing circuit for " << cur_host << llendl; | ||
4226 | msg->disableCircuit(cur_host); | ||
4227 | if (circuit_code_old == circuit_code_in) | ||
4228 | { | ||
4229 | llwarns << "Asymmetrical circuit to ip/port lookup!" << llendl; | ||
4230 | llwarns << "Multiple circuit codes for " << cur_host << " probably!" << llendl; | ||
4231 | llwarns << "Permanently disabling circuit" << llendl; | ||
4232 | return; | ||
4233 | } | ||
4234 | else | ||
4235 | { | ||
4236 | llwarns << "Circuit code changed for " << msg->getSender() | ||
4237 | << " from " << circuit_code_old << " to " | ||
4238 | << circuit_code_in << llendl; | ||
4239 | } | ||
4240 | } | ||
4241 | |||
4242 | // Since this comes from the viewer, it's untrusted, but it | ||
4243 | // passed the circuit code and session id check, so we will go | ||
4244 | // ahead and persist the ID associated. | ||
4245 | LLCircuitData *cdp = msg->mCircuitInfo.findCircuit(msg->getSender()); | ||
4246 | BOOL had_circuit_already = cdp ? TRUE : FALSE; | ||
4247 | |||
4248 | msg->enableCircuit(msg->getSender(), FALSE); | ||
4249 | cdp = msg->mCircuitInfo.findCircuit(msg->getSender()); | ||
4250 | if(cdp) | ||
4251 | { | ||
4252 | cdp->setRemoteID(id); | ||
4253 | cdp->setRemoteSessionID(session_id); | ||
4254 | } | ||
4255 | |||
4256 | if (!had_circuit_already) | ||
4257 | { | ||
4258 | // | ||
4259 | // HACK HACK HACK HACK HACK! | ||
4260 | // | ||
4261 | // This would NORMALLY happen inside logValidMsg, but at the point that this happens | ||
4262 | // inside logValidMsg, there's no circuit for this message yet. So the awful thing that | ||
4263 | // we do here is do it inside this message handler immediately AFTER the message is | ||
4264 | // handled. | ||
4265 | // | ||
4266 | // We COULD not do this, but then what happens is that some of the circuit bookkeeping | ||
4267 | // gets broken, especially the packets in count. That causes some later packets to flush | ||
4268 | // the RecentlyReceivedReliable list, resulting in an error in which UseCircuitCode | ||
4269 | // doesn't get properly duplicate suppressed. Not a BIG deal, but it's somewhat confusing | ||
4270 | // (and bad from a state point of view). DJS 9/23/04 | ||
4271 | // | ||
4272 | cdp->checkPacketInID(gMessageSystem->mCurrentRecvPacketID, FALSE ); // Since this is the first message on the circuit, by definition it's not resent. | ||
4273 | } | ||
4274 | |||
4275 | msg->mIPPortToCircuitCode[ip_port_in] = circuit_code_in; | ||
4276 | msg->mCircuitCodeToIPPort[circuit_code_in] = ip_port_in; | ||
4277 | |||
4278 | llinfos << "Circuit code " << circuit_code_in << " from " | ||
4279 | << msg->getSender() << " for agent " << id << " in session " | ||
4280 | << session_id << llendl; | ||
4281 | } | ||
4282 | else | ||
4283 | { | ||
4284 | llwarns << "Got zero circuit code in use_circuit_code" << llendl; | ||
4285 | } | ||
4286 | } | ||
4287 | |||
4288 | |||
4289 | |||
4290 | static void check_for_unrecognized_messages( | ||
4291 | const char* type, | ||
4292 | const LLSD& map, | ||
4293 | LLMessageSystem::message_template_name_map_t& templates) | ||
4294 | { | ||
4295 | for (LLSD::map_const_iterator iter = map.beginMap(), | ||
4296 | end = map.endMap(); | ||
4297 | iter != end; ++iter) | ||
4298 | { | ||
4299 | const char* name = gMessageStringTable.getString(iter->first.c_str()); | ||
4300 | |||
4301 | if (templates.find(name) == templates.end()) | ||
4302 | { | ||
4303 | llinfos << " " << type | ||
4304 | << " ban list contains unrecognized message " | ||
4305 | << name << llendl; | ||
4306 | } | ||
4307 | } | ||
4308 | } | ||
4309 | |||
4310 | void LLMessageSystem::setMessageBans( | ||
4311 | const LLSD& trusted, const LLSD& untrusted) | ||
4312 | { | ||
4313 | llinfos << "LLMessageSystem::setMessageBans:" << llendl; | ||
4314 | bool any_set = false; | ||
4315 | |||
4316 | for (message_template_name_map_t::iterator iter = mMessageTemplates.begin(), | ||
4317 | end = mMessageTemplates.end(); | ||
4318 | iter != end; ++iter) | ||
4319 | { | ||
4320 | LLMessageTemplate* mt = iter->second; | ||
4321 | |||
4322 | std::string name(mt->mName); | ||
4323 | bool ban_from_trusted | ||
4324 | = trusted.has(name) && trusted.get(name).asBoolean(); | ||
4325 | bool ban_from_untrusted | ||
4326 | = untrusted.has(name) && untrusted.get(name).asBoolean(); | ||
4327 | |||
4328 | mt->mBanFromTrusted = ban_from_trusted; | ||
4329 | mt->mBanFromUntrusted = ban_from_untrusted; | ||
4330 | |||
4331 | if (ban_from_trusted || ban_from_untrusted) | ||
4332 | { | ||
4333 | llinfos << " " << name << " banned from " | ||
4334 | << (ban_from_trusted ? "TRUSTED " : " ") | ||
4335 | << (ban_from_untrusted ? "UNTRUSTED " : " ") | ||
4336 | << llendl; | ||
4337 | any_set = true; | ||
4338 | } | ||
4339 | } | ||
4340 | |||
4341 | if (!any_set) | ||
4342 | { | ||
4343 | llinfos << " no messages banned" << llendl; | ||
4344 | } | ||
4345 | |||
4346 | check_for_unrecognized_messages("trusted", trusted, mMessageTemplates); | ||
4347 | check_for_unrecognized_messages("untrusted", untrusted, mMessageTemplates); | ||
4348 | } | ||
4349 | |||
4350 | void process_packet_ack(LLMessageSystem *msgsystem, void** /*user_data*/) | ||
4351 | { | ||
4352 | TPACKETID packet_id; | ||
4353 | |||
4354 | LLHost host = msgsystem->getSender(); | ||
4355 | LLCircuitData *cdp = msgsystem->mCircuitInfo.findCircuit(host); | ||
4356 | if (cdp) | ||
4357 | { | ||
4358 | |||
4359 | S32 ack_count = msgsystem->getNumberOfBlocksFast(_PREHASH_Packets); | ||
4360 | |||
4361 | for (S32 i = 0; i < ack_count; i++) | ||
4362 | { | ||
4363 | msgsystem->getU32Fast(_PREHASH_Packets, _PREHASH_ID, packet_id, i); | ||
4364 | // llinfos << "ack recvd' from " << host << " for packet " << (TPACKETID)packet_id << llendl; | ||
4365 | cdp->ackReliablePacket(packet_id); | ||
4366 | } | ||
4367 | if (!cdp->getUnackedPacketCount()) | ||
4368 | { | ||
4369 | // Remove this circuit from the list of circuits with unacked packets | ||
4370 | gMessageSystem->mCircuitInfo.mUnackedCircuitMap.erase(host); | ||
4371 | } | ||
4372 | } | ||
4373 | } | ||
4374 | |||
4375 | void send_template_reply(LLMessageSystem* msg, const LLUUID& token) | ||
4376 | { | ||
4377 | msg->newMessageFast(_PREHASH_TemplateChecksumReply); | ||
4378 | msg->nextBlockFast(_PREHASH_DataBlock); | ||
4379 | msg->addU32Fast(_PREHASH_Checksum, msg->mMessageFileChecksum); | ||
4380 | msg->addU8Fast(_PREHASH_MajorVersion, U8(msg->mSystemVersionMajor) ); | ||
4381 | msg->addU8Fast(_PREHASH_MinorVersion, U8(msg->mSystemVersionMinor) ); | ||
4382 | msg->addU8Fast(_PREHASH_PatchVersion, U8(msg->mSystemVersionPatch) ); | ||
4383 | msg->addU8Fast(_PREHASH_ServerVersion, U8(msg->mSystemVersionServer) ); | ||
4384 | msg->addU32Fast(_PREHASH_Flags, msg->mVersionFlags); | ||
4385 | msg->nextBlockFast(_PREHASH_TokenBlock); | ||
4386 | msg->addUUIDFast(_PREHASH_Token, token); | ||
4387 | msg->sendMessage(msg->getSender()); | ||
4388 | } | ||
4389 | |||
4390 | void process_template_checksum_request(LLMessageSystem* msg, void**) | ||
4391 | { | ||
4392 | llinfos << "Message template checksum request received from " | ||
4393 | << msg->getSender() << llendl; | ||
4394 | send_template_reply(msg, LLUUID::null); | ||
4395 | } | ||
4396 | |||
4397 | void process_secured_template_checksum_request(LLMessageSystem* msg, void**) | ||
4398 | { | ||
4399 | llinfos << "Secured message template checksum request received from " | ||
4400 | << msg->getSender() << llendl; | ||
4401 | LLUUID token; | ||
4402 | msg->getUUIDFast(_PREHASH_TokenBlock, _PREHASH_Token, token); | ||
4403 | send_template_reply(msg, token); | ||
4404 | } | ||
4405 | |||
4406 | void process_log_control(LLMessageSystem* msg, void**) | ||
4407 | { | ||
4408 | U8 level; | ||
4409 | U32 mask; | ||
4410 | BOOL time; | ||
4411 | BOOL location; | ||
4412 | BOOL remote_infos; | ||
4413 | |||
4414 | msg->getU8Fast(_PREHASH_Options, _PREHASH_Level, level); | ||
4415 | msg->getU32Fast(_PREHASH_Options, _PREHASH_Mask, mask); | ||
4416 | msg->getBOOLFast(_PREHASH_Options, _PREHASH_Time, time); | ||
4417 | msg->getBOOLFast(_PREHASH_Options, _PREHASH_Location, location); | ||
4418 | msg->getBOOLFast(_PREHASH_Options, _PREHASH_RemoteInfos, remote_infos); | ||
4419 | |||
4420 | gErrorStream.setLevel(LLErrorStream::ELevel(level)); | ||
4421 | gErrorStream.setDebugMask(mask); | ||
4422 | gErrorStream.setTime(time); | ||
4423 | gErrorStream.setPrintLocation(location); | ||
4424 | gErrorStream.setElevatedRemote(remote_infos); | ||
4425 | |||
4426 | llinfos << "Logging set to level " << gErrorStream.getLevel() | ||
4427 | << " mask " << std::hex << gErrorStream.getDebugMask() << std::dec | ||
4428 | << " time " << gErrorStream.getTime() | ||
4429 | << " loc " << gErrorStream.getPrintLocation() | ||
4430 | << llendl; | ||
4431 | } | ||
4432 | |||
4433 | void process_log_messages(LLMessageSystem* msg, void**) | ||
4434 | { | ||
4435 | U8 log_message; | ||
4436 | |||
4437 | msg->getU8Fast(_PREHASH_Options, _PREHASH_Enable, log_message); | ||
4438 | |||
4439 | if (log_message) | ||
4440 | { | ||
4441 | llinfos << "Starting logging via message" << llendl; | ||
4442 | msg->startLogging(); | ||
4443 | } | ||
4444 | else | ||
4445 | { | ||
4446 | llinfos << "Stopping logging via message" << llendl; | ||
4447 | msg->stopLogging(); | ||
4448 | } | ||
4449 | } | ||
4450 | |||
4451 | // Make circuit trusted if the MD5 Digest matches, otherwise | ||
4452 | // notify remote end that they are not trusted. | ||
4453 | void process_create_trusted_circuit(LLMessageSystem *msg, void **) | ||
4454 | { | ||
4455 | // don't try to create trust on machines with no shared secret | ||
4456 | std::string shared_secret = get_shared_secret(); | ||
4457 | if(shared_secret.empty()) return; | ||
4458 | |||
4459 | LLUUID remote_id; | ||
4460 | msg->getUUIDFast(_PREHASH_DataBlock, _PREHASH_EndPointID, remote_id); | ||
4461 | |||
4462 | LLCircuitData *cdp = msg->mCircuitInfo.findCircuit(msg->getSender()); | ||
4463 | if (!cdp) | ||
4464 | { | ||
4465 | llwarns << "Attempt to create trusted circuit without circuit data: " | ||
4466 | << msg->getSender() << llendl; | ||
4467 | return; | ||
4468 | } | ||
4469 | |||
4470 | LLUUID local_id; | ||
4471 | local_id = cdp->getLocalEndPointID(); | ||
4472 | if (remote_id == local_id) | ||
4473 | { | ||
4474 | // Don't respond to requests that use the same end point ID | ||
4475 | return; | ||
4476 | } | ||
4477 | |||
4478 | char their_digest[MD5HEX_STR_SIZE]; | ||
4479 | S32 size = msg->getSizeFast(_PREHASH_DataBlock, _PREHASH_Digest); | ||
4480 | if(size != MD5HEX_STR_BYTES) | ||
4481 | { | ||
4482 | // ignore requests which pack the wrong amount of data. | ||
4483 | return; | ||
4484 | } | ||
4485 | msg->getBinaryDataFast(_PREHASH_DataBlock, _PREHASH_Digest, their_digest, MD5HEX_STR_BYTES); | ||
4486 | their_digest[MD5HEX_STR_SIZE - 1] = '\0'; | ||
4487 | if(msg->isMatchingDigestForWindowAndUUIDs(their_digest, TRUST_TIME_WINDOW, local_id, remote_id)) | ||
4488 | { | ||
4489 | cdp->setTrusted(TRUE); | ||
4490 | llinfos << "Trusted digest from " << msg->getSender() << llendl; | ||
4491 | return; | ||
4492 | } | ||
4493 | else if (cdp->getTrusted()) | ||
4494 | { | ||
4495 | // The digest is bad, but this circuit is already trusted. | ||
4496 | // This means that this could just be the result of a stale deny sent from a while back, and | ||
4497 | // the message system is being slow. Don't bother sending the deny, as it may continually | ||
4498 | // ping-pong back and forth on a very hosed circuit. | ||
4499 | llwarns << "Ignoring bad digest from known trusted circuit: " << their_digest | ||
4500 | << " host: " << msg->getSender() << llendl; | ||
4501 | return; | ||
4502 | } | ||
4503 | else | ||
4504 | { | ||
4505 | llwarns << "Bad digest from known circuit: " << their_digest | ||
4506 | << " host: " << msg->getSender() << llendl; | ||
4507 | msg->sendDenyTrustedCircuit(msg->getSender()); | ||
4508 | return; | ||
4509 | } | ||
4510 | } | ||
4511 | |||
4512 | void process_deny_trusted_circuit(LLMessageSystem *msg, void **) | ||
4513 | { | ||
4514 | // don't try to create trust on machines with no shared secret | ||
4515 | std::string shared_secret = get_shared_secret(); | ||
4516 | if(shared_secret.empty()) return; | ||
4517 | |||
4518 | LLUUID remote_id; | ||
4519 | msg->getUUIDFast(_PREHASH_DataBlock, _PREHASH_EndPointID, remote_id); | ||
4520 | |||
4521 | LLCircuitData *cdp = msg->mCircuitInfo.findCircuit(msg->getSender()); | ||
4522 | if (!cdp) | ||
4523 | { | ||
4524 | return; | ||
4525 | } | ||
4526 | |||
4527 | LLUUID local_id; | ||
4528 | local_id = cdp->getLocalEndPointID(); | ||
4529 | if (remote_id == local_id) | ||
4530 | { | ||
4531 | // Don't respond to requests that use the same end point ID | ||
4532 | return; | ||
4533 | } | ||
4534 | |||
4535 | // Assume that we require trust to proceed, so resend. | ||
4536 | // This catches the case where a circuit that was trusted | ||
4537 | // times out, and allows us to re-establish it, but does | ||
4538 | // mean that if our shared_secret or clock is wrong, we'll | ||
4539 | // spin. | ||
4540 | // *TODO: probably should keep a count of number of resends | ||
4541 | // per circuit, and stop resending after a while. | ||
4542 | llinfos << "Got DenyTrustedCircuit. Sending CreateTrustedCircuit to " | ||
4543 | << msg->getSender() << llendl; | ||
4544 | msg->sendCreateTrustedCircuit(msg->getSender(), local_id, remote_id); | ||
4545 | } | ||
4546 | |||
4547 | #define LL_ENCRYPT_BUF_LENGTH 16384 | ||
4548 | |||
4549 | void encrypt_template(const char *src_name, const char *dest_name) | ||
4550 | { | ||
4551 | // encrypt and decrypt are symmetric | ||
4552 | decrypt_template(src_name, dest_name); | ||
4553 | } | ||
4554 | |||
4555 | BOOL decrypt_template(const char *src_name, const char *dest_name) | ||
4556 | { | ||
4557 | S32 buf_length = LL_ENCRYPT_BUF_LENGTH; | ||
4558 | char buf[LL_ENCRYPT_BUF_LENGTH]; | ||
4559 | |||
4560 | FILE* infp = NULL; | ||
4561 | FILE* outfp = NULL; | ||
4562 | BOOL success = FALSE; | ||
4563 | char* bufp = NULL; | ||
4564 | U32 key = 0; | ||
4565 | S32 more_data = 0; | ||
4566 | |||
4567 | if(src_name==NULL) | ||
4568 | { | ||
4569 | llwarns << "Input src_name is NULL!!" << llendl; | ||
4570 | goto exit; | ||
4571 | } | ||
4572 | |||
4573 | infp = LLFile::fopen(src_name,"rb"); | ||
4574 | if (!infp) | ||
4575 | { | ||
4576 | llwarns << "could not open " << src_name << " for reading" << llendl; | ||
4577 | goto exit; | ||
4578 | } | ||
4579 | |||
4580 | if(dest_name==NULL) | ||
4581 | { | ||
4582 | llwarns << "Output dest_name is NULL!!" << llendl; | ||
4583 | goto exit; | ||
4584 | } | ||
4585 | |||
4586 | outfp = LLFile::fopen(dest_name,"w+b"); | ||
4587 | if (!outfp) | ||
4588 | { | ||
4589 | llwarns << "could not open " << src_name << " for writing" << llendl; | ||
4590 | goto exit; | ||
4591 | } | ||
4592 | |||
4593 | while ((buf_length = (S32)fread(buf,1,LL_ENCRYPT_BUF_LENGTH,infp))) | ||
4594 | { | ||
4595 | // unscrozzle bits here | ||
4596 | bufp = buf; | ||
4597 | more_data = buf_length; | ||
4598 | while (more_data--) | ||
4599 | { | ||
4600 | *bufp = *bufp ^ ((key * 43) % 256); | ||
4601 | key++; | ||
4602 | bufp++; | ||
4603 | } | ||
4604 | |||
4605 | if(buf_length != (S32)fwrite(buf,1,buf_length,outfp)) | ||
4606 | { | ||
4607 | goto exit; | ||
4608 | } | ||
4609 | } | ||
4610 | success = TRUE; | ||
4611 | |||
4612 | exit: | ||
4613 | if(infp) fclose(infp); | ||
4614 | if(outfp) fclose(outfp); | ||
4615 | return success; | ||
4616 | } | ||
4617 | |||
4618 | void dump_prehash_files() | ||
4619 | { | ||
4620 | U32 i; | ||
4621 | FILE *fp = LLFile::fopen("../../indra/llmessage/message_prehash.h", "w"); | ||
4622 | if (fp) | ||
4623 | { | ||
4624 | fprintf( | ||
4625 | fp, | ||
4626 | "/**\n" | ||
4627 | " * @file message_prehash.h\n" | ||
4628 | " * @brief header file of externs of prehashed variables plus defines.\n" | ||
4629 | " *\n" | ||
4630 | " * Copyright (c) 2003-$CurrentYear$, Linden Research, Inc.\n" | ||
4631 | " * $License$\n" | ||
4632 | " */\n\n" | ||
4633 | "#ifndef LL_MESSAGE_PREHASH_H\n#define LL_MESSAGE_PREHASH_H\n\n"); | ||
4634 | fprintf( | ||
4635 | fp, | ||
4636 | "/**\n" | ||
4637 | " * Generated from message template version number %.3f\n" | ||
4638 | " */\n", | ||
4639 | gMessageSystem->mMessageFileVersionNumber); | ||
4640 | fprintf(fp, "\n\nextern F32 gPrehashVersionNumber;\n\n"); | ||
4641 | for (i = 0; i < MESSAGE_NUMBER_OF_HASH_BUCKETS; i++) | ||
4642 | { | ||
4643 | if (!gMessageStringTable.mEmpty[i] && gMessageStringTable.mString[i][0] != '.') | ||
4644 | { | ||
4645 | fprintf(fp, "extern char * _PREHASH_%s;\n", gMessageStringTable.mString[i]); | ||
4646 | } | ||
4647 | } | ||
4648 | fprintf(fp, "\n\nvoid init_prehash_data();\n\n"); | ||
4649 | fprintf(fp, "\n\n"); | ||
4650 | fprintf(fp, "\n\n#endif\n"); | ||
4651 | fclose(fp); | ||
4652 | } | ||
4653 | fp = LLFile::fopen("../../indra/llmessage/message_prehash.cpp", "w"); | ||
4654 | if (fp) | ||
4655 | { | ||
4656 | fprintf( | ||
4657 | fp, | ||
4658 | "/**\n" | ||
4659 | " * @file message_prehash.cpp\n" | ||
4660 | " * @brief file of prehashed variables\n" | ||
4661 | " *\n" | ||
4662 | " * Copyright (c) 2003-$CurrentYear$, Linden Research, Inc.\n" | ||
4663 | " * $License$\n" | ||
4664 | " */\n\n" | ||
4665 | "/**\n" | ||
4666 | " * Generated from message template version number %.3f\n" | ||
4667 | " */\n", | ||
4668 | gMessageSystem->mMessageFileVersionNumber); | ||
4669 | fprintf(fp, "#include \"linden_common.h\"\n"); | ||
4670 | fprintf(fp, "#include \"message.h\"\n\n"); | ||
4671 | fprintf(fp, "\n\nF32 gPrehashVersionNumber = %.3ff;\n\n", gMessageSystem->mMessageFileVersionNumber); | ||
4672 | for (i = 0; i < MESSAGE_NUMBER_OF_HASH_BUCKETS; i++) | ||
4673 | { | ||
4674 | if (!gMessageStringTable.mEmpty[i] && gMessageStringTable.mString[i][0] != '.') | ||
4675 | { | ||
4676 | fprintf(fp, "char * _PREHASH_%s;\n", gMessageStringTable.mString[i]); | ||
4677 | } | ||
4678 | } | ||
4679 | fprintf(fp, "\nvoid init_prehash_data()\n"); | ||
4680 | fprintf(fp, "{\n"); | ||
4681 | for (i = 0; i < MESSAGE_NUMBER_OF_HASH_BUCKETS; i++) | ||
4682 | { | ||
4683 | if (!gMessageStringTable.mEmpty[i] && gMessageStringTable.mString[i][0] != '.') | ||
4684 | { | ||
4685 | fprintf(fp, "\t_PREHASH_%s = gMessageStringTable.getString(\"%s\");\n", gMessageStringTable.mString[i], gMessageStringTable.mString[i]); | ||
4686 | } | ||
4687 | } | ||
4688 | fprintf(fp, "}\n"); | ||
4689 | fclose(fp); | ||
4690 | } | ||
4691 | } | ||
4692 | |||
4693 | BOOL start_messaging_system( | ||
4694 | const std::string& template_name, | ||
4695 | U32 port, | ||
4696 | S32 version_major, | ||
4697 | S32 version_minor, | ||
4698 | S32 version_patch, | ||
4699 | BOOL b_dump_prehash_file, | ||
4700 | const std::string& secret) | ||
4701 | { | ||
4702 | gMessageSystem = new LLMessageSystem( | ||
4703 | template_name.c_str(), | ||
4704 | port, | ||
4705 | version_major, | ||
4706 | version_minor, | ||
4707 | version_patch); | ||
4708 | g_shared_secret.assign(secret); | ||
4709 | |||
4710 | if (!gMessageSystem) | ||
4711 | { | ||
4712 | llerrs << "Messaging system initialization failed." << llendl; | ||
4713 | return FALSE; | ||
4714 | } | ||
4715 | |||
4716 | // bail if system encountered an error. | ||
4717 | if(!gMessageSystem->isOK()) | ||
4718 | { | ||
4719 | return FALSE; | ||
4720 | } | ||
4721 | |||
4722 | if (b_dump_prehash_file) | ||
4723 | { | ||
4724 | dump_prehash_files(); | ||
4725 | exit(0); | ||
4726 | } | ||
4727 | else | ||
4728 | { | ||
4729 | init_prehash_data(); | ||
4730 | if (gMessageSystem->mMessageFileVersionNumber != gPrehashVersionNumber) | ||
4731 | { | ||
4732 | llinfos << "Message template version does not match prehash version number" << llendl; | ||
4733 | llinfos << "Run simulator with -prehash command line option to rebuild prehash data" << llendl; | ||
4734 | } | ||
4735 | else | ||
4736 | { | ||
4737 | llinfos << "Message template version matches prehash version number" << llendl; | ||
4738 | } | ||
4739 | } | ||
4740 | |||
4741 | gMessageSystem->setHandlerFuncFast(_PREHASH_StartPingCheck, process_start_ping_check, NULL); | ||
4742 | gMessageSystem->setHandlerFuncFast(_PREHASH_CompletePingCheck, process_complete_ping_check, NULL); | ||
4743 | gMessageSystem->setHandlerFuncFast(_PREHASH_OpenCircuit, open_circuit, NULL); | ||
4744 | gMessageSystem->setHandlerFuncFast(_PREHASH_CloseCircuit, close_circuit, NULL); | ||
4745 | |||
4746 | //gMessageSystem->setHandlerFuncFast(_PREHASH_AssignCircuitCode, LLMessageSystem::processAssignCircuitCode); | ||
4747 | gMessageSystem->setHandlerFuncFast(_PREHASH_AddCircuitCode, LLMessageSystem::processAddCircuitCode); | ||
4748 | //gMessageSystem->setHandlerFuncFast(_PREHASH_AckAddCircuitCode, ack_add_circuit_code, NULL); | ||
4749 | gMessageSystem->setHandlerFuncFast(_PREHASH_UseCircuitCode, LLMessageSystem::processUseCircuitCode); | ||
4750 | gMessageSystem->setHandlerFuncFast(_PREHASH_PacketAck, process_packet_ack, NULL); | ||
4751 | gMessageSystem->setHandlerFuncFast(_PREHASH_TemplateChecksumRequest, process_template_checksum_request, NULL); | ||
4752 | gMessageSystem->setHandlerFuncFast(_PREHASH_SecuredTemplateChecksumRequest, process_secured_template_checksum_request, NULL); | ||
4753 | gMessageSystem->setHandlerFuncFast(_PREHASH_LogControl, process_log_control, NULL); | ||
4754 | gMessageSystem->setHandlerFuncFast(_PREHASH_LogMessages, process_log_messages, NULL); | ||
4755 | gMessageSystem->setHandlerFuncFast(_PREHASH_CreateTrustedCircuit, | ||
4756 | process_create_trusted_circuit, | ||
4757 | NULL); | ||
4758 | gMessageSystem->setHandlerFuncFast(_PREHASH_DenyTrustedCircuit, | ||
4759 | process_deny_trusted_circuit, | ||
4760 | NULL); | ||
4761 | |||
4762 | // We can hand this to the null_message_callback since it is a | ||
4763 | // trusted message, so it will automatically be denied if it isn't | ||
4764 | // trusted and ignored if it is -- exactly what we want. | ||
4765 | gMessageSystem->setHandlerFunc( | ||
4766 | "RequestTrustedCircuit", | ||
4767 | null_message_callback, | ||
4768 | NULL); | ||
4769 | |||
4770 | // Initialize the transfer manager | ||
4771 | gTransferManager.init(); | ||
4772 | |||
4773 | return TRUE; | ||
4774 | } | ||
4775 | |||
4776 | void LLMessageSystem::startLogging() | ||
4777 | { | ||
4778 | mVerboseLog = TRUE; | ||
4779 | std::ostringstream str; | ||
4780 | str << "START MESSAGE LOG" << std::endl; | ||
4781 | str << "Legend:" << std::endl; | ||
4782 | str << "\t<-\tincoming message" <<std::endl; | ||
4783 | str << "\t->\toutgoing message" << std::endl; | ||
4784 | str << " <> host size zero id name"; | ||
4785 | llinfos << str.str() << llendl; | ||
4786 | } | ||
4787 | |||
4788 | void LLMessageSystem::stopLogging() | ||
4789 | { | ||
4790 | if(mVerboseLog) | ||
4791 | { | ||
4792 | mVerboseLog = FALSE; | ||
4793 | llinfos << "END MESSAGE LOG" << llendl; | ||
4794 | } | ||
4795 | } | ||
4796 | |||
4797 | void LLMessageSystem::summarizeLogs(std::ostream& str) | ||
4798 | { | ||
4799 | char buffer[MAX_STRING]; /* Flawfinder: ignore */ | ||
4800 | char tmp_str[MAX_STRING]; /* Flawfinder: ignore */ | ||
4801 | F32 run_time = mMessageSystemTimer.getElapsedTimeF32(); | ||
4802 | str << "START MESSAGE LOG SUMMARY" << std::endl; | ||
4803 | snprintf(buffer, MAX_STRING, "Run time: %12.3f seconds", run_time); /* Flawfinder: ignore */ | ||
4804 | |||
4805 | // Incoming | ||
4806 | str << buffer << std::endl << "Incoming:" << std::endl; | ||
4807 | U64_to_str(mTotalBytesIn, tmp_str, sizeof(tmp_str)); | ||
4808 | snprintf(buffer, MAX_STRING, "Total bytes received: %20s (%5.2f kbits per second)", tmp_str, ((F32)mTotalBytesIn * 0.008f) / run_time); /* Flawfinder: ignore */ | ||
4809 | str << buffer << std::endl; | ||
4810 | U64_to_str(mPacketsIn, tmp_str, sizeof(tmp_str)); | ||
4811 | snprintf(buffer, MAX_STRING, "Total packets received: %20s (%5.2f packets per second)", tmp_str, ((F32) mPacketsIn / run_time)); /* Flawfinder: ignore */ | ||
4812 | str << buffer << std::endl; | ||
4813 | snprintf(buffer, MAX_STRING, "Average packet size: %20.0f bytes", (F32)mTotalBytesIn / (F32)mPacketsIn); /* Flawfinder: ignore */ | ||
4814 | str << buffer << std::endl; | ||
4815 | U64_to_str(mReliablePacketsIn, tmp_str, sizeof(tmp_str)); | ||
4816 | snprintf(buffer, MAX_STRING, "Total reliable packets: %20s (%5.2f%%)", tmp_str, 100.f * ((F32) mReliablePacketsIn)/((F32) mPacketsIn + 1)); /* Flawfinder: ignore */ | ||
4817 | str << buffer << std::endl; | ||
4818 | U64_to_str(mCompressedPacketsIn, tmp_str, sizeof(tmp_str)); | ||
4819 | snprintf(buffer, MAX_STRING, "Total compressed packets: %20s (%5.2f%%)", tmp_str, 100.f * ((F32) mCompressedPacketsIn)/((F32) mPacketsIn + 1)); /* Flawfinder: ignore */ | ||
4820 | str << buffer << std::endl; | ||
4821 | S64 savings = mUncompressedBytesIn - mCompressedBytesIn; | ||
4822 | U64_to_str(savings, tmp_str, sizeof(tmp_str)); | ||
4823 | snprintf(buffer, MAX_STRING, "Total compression savings: %20s bytes", tmp_str); /* Flawfinder: ignore */ | ||
4824 | str << buffer << std::endl; | ||
4825 | U64_to_str(savings/(mCompressedPacketsIn +1), tmp_str, sizeof(tmp_str)); | ||
4826 | snprintf(buffer, MAX_STRING, "Avg comp packet savings: %20s (%5.2f : 1)", tmp_str, ((F32) mUncompressedBytesIn)/((F32) mCompressedBytesIn+1)); /* Flawfinder: ignore */ | ||
4827 | str << buffer << std::endl; | ||
4828 | U64_to_str(savings/(mPacketsIn+1), tmp_str, sizeof(tmp_str)); | ||
4829 | snprintf(buffer, MAX_STRING, "Avg overall comp savings: %20s (%5.2f : 1)", tmp_str, ((F32) mTotalBytesIn + (F32) savings)/((F32) mTotalBytesIn + 1.f)); /* Flawfinder: ignore */ | ||
4830 | |||
4831 | // Outgoing | ||
4832 | str << buffer << std::endl << std::endl << "Outgoing:" << std::endl; | ||
4833 | U64_to_str(mTotalBytesOut, tmp_str, sizeof(tmp_str)); | ||
4834 | snprintf(buffer, MAX_STRING, "Total bytes sent: %20s (%5.2f kbits per second)", tmp_str, ((F32)mTotalBytesOut * 0.008f) / run_time ); /* Flawfinder: ignore */ | ||
4835 | str << buffer << std::endl; | ||
4836 | U64_to_str(mPacketsOut, tmp_str, sizeof(tmp_str)); | ||
4837 | snprintf(buffer, MAX_STRING, "Total packets sent: %20s (%5.2f packets per second)", tmp_str, ((F32)mPacketsOut / run_time)); /* Flawfinder: ignore */ | ||
4838 | str << buffer << std::endl; | ||
4839 | snprintf(buffer, MAX_STRING, "Average packet size: %20.0f bytes", (F32)mTotalBytesOut / (F32)mPacketsOut); /* Flawfinder: ignore */ | ||
4840 | str << buffer << std::endl; | ||
4841 | U64_to_str(mReliablePacketsOut, tmp_str, sizeof(tmp_str)); | ||
4842 | snprintf(buffer, MAX_STRING, "Total reliable packets: %20s (%5.2f%%)", tmp_str, 100.f * ((F32) mReliablePacketsOut)/((F32) mPacketsOut + 1)); /* Flawfinder: ignore */ | ||
4843 | str << buffer << std::endl; | ||
4844 | U64_to_str(mCompressedPacketsOut, tmp_str, sizeof(tmp_str)); | ||
4845 | snprintf(buffer, MAX_STRING, "Total compressed packets: %20s (%5.2f%%)", tmp_str, 100.f * ((F32) mCompressedPacketsOut)/((F32) mPacketsOut + 1)); /* Flawfinder: ignore */ | ||
4846 | str << buffer << std::endl; | ||
4847 | savings = mUncompressedBytesOut - mCompressedBytesOut; | ||
4848 | U64_to_str(savings, tmp_str, sizeof(tmp_str)); | ||
4849 | snprintf(buffer, MAX_STRING, "Total compression savings: %20s bytes", tmp_str); /* Flawfinder: ignore */ | ||
4850 | str << buffer << std::endl; | ||
4851 | U64_to_str(savings/(mCompressedPacketsOut +1), tmp_str, sizeof(tmp_str)); | ||
4852 | snprintf(buffer, MAX_STRING, "Avg comp packet savings: %20s (%5.2f : 1)", tmp_str, ((F32) mUncompressedBytesOut)/((F32) mCompressedBytesOut+1)); /* Flawfinder: ignore */ | ||
4853 | str << buffer << std::endl; | ||
4854 | U64_to_str(savings/(mPacketsOut+1), tmp_str, sizeof(tmp_str)); | ||
4855 | snprintf(buffer, MAX_STRING, "Avg overall comp savings: %20s (%5.2f : 1)", tmp_str, ((F32) mTotalBytesOut + (F32) savings)/((F32) mTotalBytesOut + 1.f)); /* Flawfinder: ignore */ | ||
4856 | str << buffer << std::endl << std::endl; | ||
4857 | snprintf(buffer, MAX_STRING, "SendPacket failures: %20d", mSendPacketFailureCount); /* Flawfinder: ignore */ | ||
4858 | str << buffer << std::endl; | ||
4859 | snprintf(buffer, MAX_STRING, "Dropped packets: %20d", mDroppedPackets); /* Flawfinder: ignore */ | ||
4860 | str << buffer << std::endl; | ||
4861 | snprintf(buffer, MAX_STRING, "Resent packets: %20d", mResentPackets); /* Flawfinder: ignore */ | ||
4862 | str << buffer << std::endl; | ||
4863 | snprintf(buffer, MAX_STRING, "Failed reliable resends: %20d", mFailedResendPackets); /* Flawfinder: ignore */ | ||
4864 | str << buffer << std::endl; | ||
4865 | snprintf(buffer, MAX_STRING, "Off-circuit rejected packets: %17d", mOffCircuitPackets); /* Flawfinder: ignore */ | ||
4866 | str << buffer << std::endl; | ||
4867 | snprintf(buffer, MAX_STRING, "On-circuit invalid packets: %17d", mInvalidOnCircuitPackets); /* Flawfinder: ignore */ | ||
4868 | str << buffer << std::endl << std::endl; | ||
4869 | |||
4870 | str << "Decoding: " << std::endl; | ||
4871 | snprintf(buffer, MAX_STRING, "%35s%10s%10s%10s%10s", "Message", "Count", "Time", "Max", "Avg"); /* Flawfinder: ignore */ | ||
4872 | str << buffer << std:: endl; | ||
4873 | F32 avg; | ||
4874 | for (message_template_name_map_t::iterator iter = mMessageTemplates.begin(), | ||
4875 | end = mMessageTemplates.end(); | ||
4876 | iter != end; iter++) | ||
4877 | { | ||
4878 | LLMessageTemplate* mt = iter->second; | ||
4879 | if(mt->mTotalDecoded > 0) | ||
4880 | { | ||
4881 | avg = mt->mTotalDecodeTime / (F32)mt->mTotalDecoded; | ||
4882 | snprintf(buffer, MAX_STRING, "%35s%10u%10f%10f%10f", mt->mName, mt->mTotalDecoded, mt->mTotalDecodeTime, mt->mMaxDecodeTimePerMsg, avg); /* Flawfinder: ignore */ | ||
4883 | str << buffer << std::endl; | ||
4884 | } | ||
4885 | } | ||
4886 | str << "END MESSAGE LOG SUMMARY" << std::endl; | ||
4887 | } | ||
4888 | |||
4889 | void end_messaging_system() | ||
4890 | { | ||
4891 | gTransferManager.cleanup(); | ||
4892 | LLTransferTargetVFile::updateQueue(true); // shutdown LLTransferTargetVFile | ||
4893 | if (gMessageSystem) | ||
4894 | { | ||
4895 | gMessageSystem->stopLogging(); | ||
4896 | |||
4897 | std::ostringstream str; | ||
4898 | gMessageSystem->summarizeLogs(str); | ||
4899 | llinfos << str.str().c_str() << llendl; | ||
4900 | |||
4901 | delete gMessageSystem; | ||
4902 | gMessageSystem = NULL; | ||
4903 | } | ||
4904 | } | ||
4905 | |||
4906 | void LLMessageSystem::resetReceiveCounts() | ||
4907 | { | ||
4908 | mNumMessageCounts = 0; | ||
4909 | |||
4910 | for (message_template_name_map_t::iterator iter = mMessageTemplates.begin(), | ||
4911 | end = mMessageTemplates.end(); | ||
4912 | iter != end; iter++) | ||
4913 | { | ||
4914 | LLMessageTemplate* mt = iter->second; | ||
4915 | mt->mDecodeTimeThisFrame = 0.f; | ||
4916 | } | ||
4917 | } | ||
4918 | |||
4919 | |||
4920 | void LLMessageSystem::dumpReceiveCounts() | ||
4921 | { | ||
4922 | LLMessageTemplate *mt; | ||
4923 | |||
4924 | for (message_template_name_map_t::iterator iter = mMessageTemplates.begin(), | ||
4925 | end = mMessageTemplates.end(); | ||
4926 | iter != end; iter++) | ||
4927 | { | ||
4928 | LLMessageTemplate* mt = iter->second; | ||
4929 | mt->mReceiveCount = 0; | ||
4930 | mt->mReceiveBytes = 0; | ||
4931 | mt->mReceiveInvalid = 0; | ||
4932 | } | ||
4933 | |||
4934 | S32 i; | ||
4935 | for (i = 0; i < mNumMessageCounts; i++) | ||
4936 | { | ||
4937 | mt = get_ptr_in_map(mMessageNumbers,mMessageCountList[i].mMessageNum); | ||
4938 | if (mt) | ||
4939 | { | ||
4940 | mt->mReceiveCount++; | ||
4941 | mt->mReceiveBytes += mMessageCountList[i].mMessageBytes; | ||
4942 | if (mMessageCountList[i].mInvalid) | ||
4943 | { | ||
4944 | mt->mReceiveInvalid++; | ||
4945 | } | ||
4946 | } | ||
4947 | } | ||
4948 | |||
4949 | if(mNumMessageCounts > 0) | ||
4950 | { | ||
4951 | llinfos << "Dump: " << mNumMessageCounts << " messages processed in " << mReceiveTime << " seconds" << llendl; | ||
4952 | for (message_template_name_map_t::iterator iter = mMessageTemplates.begin(), | ||
4953 | end = mMessageTemplates.end(); | ||
4954 | iter != end; iter++) | ||
4955 | { | ||
4956 | LLMessageTemplate* mt = iter->second; | ||
4957 | if (mt->mReceiveCount > 0) | ||
4958 | { | ||
4959 | llinfos << "Num: " << std::setw(3) << mt->mReceiveCount << " Bytes: " << std::setw(6) << mt->mReceiveBytes | ||
4960 | << " Invalid: " << std::setw(3) << mt->mReceiveInvalid << " " << mt->mName << " " << llround(100 * mt->mDecodeTimeThisFrame / mReceiveTime) << "%" << llendl; | ||
4961 | } | ||
4962 | } | ||
4963 | } | ||
4964 | } | ||
4965 | |||
4966 | |||
4967 | |||
4968 | BOOL LLMessageSystem::isClear() const | ||
4969 | { | ||
4970 | return mbSClear; | ||
4971 | } | ||
4972 | |||
4973 | |||
4974 | S32 LLMessageSystem::flush(const LLHost &host) | ||
4975 | { | ||
4976 | if (mCurrentSendTotal) | ||
4977 | { | ||
4978 | S32 sentbytes = sendMessage(host); | ||
4979 | clearMessage(); | ||
4980 | return sentbytes; | ||
4981 | } | ||
4982 | else | ||
4983 | { | ||
4984 | return 0; | ||
4985 | } | ||
4986 | } | ||
4987 | |||
4988 | U32 LLMessageSystem::getListenPort( void ) const | ||
4989 | { | ||
4990 | return mPort; | ||
4991 | } | ||
4992 | |||
4993 | |||
4994 | S32 LLMessageSystem::zeroCode(U8 **data, S32 *data_size) | ||
4995 | { | ||
4996 | S32 count = *data_size; | ||
4997 | |||
4998 | S32 net_gain = 0; | ||
4999 | U8 num_zeroes = 0; | ||
5000 | |||
5001 | U8 *inptr = (U8 *)*data; | ||
5002 | U8 *outptr = (U8 *)mEncodedSendBuffer; | ||
5003 | |||
5004 | // skip the packet id field | ||
5005 | |||
5006 | for (U32 i=0;i<LL_PACKET_ID_SIZE;i++) | ||
5007 | { | ||
5008 | count--; | ||
5009 | *outptr++ = *inptr++; | ||
5010 | } | ||
5011 | |||
5012 | // build encoded packet, keeping track of net size gain | ||
5013 | |||
5014 | // sequential zero bytes are encoded as 0 [U8 count] | ||
5015 | // with 0 0 [count] representing wrap (>256 zeroes) | ||
5016 | |||
5017 | while (count--) | ||
5018 | { | ||
5019 | if (!(*inptr)) // in a zero count | ||
5020 | { | ||
5021 | if (num_zeroes) | ||
5022 | { | ||
5023 | if (++num_zeroes > 254) | ||
5024 | { | ||
5025 | *outptr++ = num_zeroes; | ||
5026 | num_zeroes = 0; | ||
5027 | } | ||
5028 | net_gain--; // subseqent zeroes save one | ||
5029 | } | ||
5030 | else | ||
5031 | { | ||
5032 | *outptr++ = 0; | ||
5033 | net_gain++; // starting a zero count adds one | ||
5034 | num_zeroes = 1; | ||
5035 | } | ||
5036 | inptr++; | ||
5037 | } | ||
5038 | else | ||
5039 | { | ||
5040 | if (num_zeroes) | ||
5041 | { | ||
5042 | *outptr++ = num_zeroes; | ||
5043 | num_zeroes = 0; | ||
5044 | } | ||
5045 | *outptr++ = *inptr++; | ||
5046 | } | ||
5047 | } | ||
5048 | |||
5049 | if (num_zeroes) | ||
5050 | { | ||
5051 | *outptr++ = num_zeroes; | ||
5052 | } | ||
5053 | |||
5054 | if (net_gain < 0) | ||
5055 | { | ||
5056 | mCompressedPacketsOut++; | ||
5057 | mUncompressedBytesOut += *data_size; | ||
5058 | |||
5059 | *data = mEncodedSendBuffer; | ||
5060 | *data_size += net_gain; | ||
5061 | mEncodedSendBuffer[0] |= LL_ZERO_CODE_FLAG; // set the head bit to indicate zero coding | ||
5062 | |||
5063 | mCompressedBytesOut += *data_size; | ||
5064 | |||
5065 | } | ||
5066 | mTotalBytesOut += *data_size; | ||
5067 | |||
5068 | return(net_gain); | ||
5069 | } | ||
5070 | |||
5071 | S32 LLMessageSystem::zeroCodeAdjustCurrentSendTotal() | ||
5072 | { | ||
5073 | if (!mbSBuilt) | ||
5074 | { | ||
5075 | buildMessage(); | ||
5076 | } | ||
5077 | mbSBuilt = FALSE; | ||
5078 | |||
5079 | S32 count = mSendSize; | ||
5080 | |||
5081 | S32 net_gain = 0; | ||
5082 | U8 num_zeroes = 0; | ||
5083 | |||
5084 | U8 *inptr = (U8 *)mSendBuffer; | ||
5085 | |||
5086 | // skip the packet id field | ||
5087 | |||
5088 | for (U32 i=0;i<LL_PACKET_ID_SIZE;i++) | ||
5089 | { | ||
5090 | count--; | ||
5091 | inptr++; | ||
5092 | } | ||
5093 | |||
5094 | // don't actually build, just test | ||
5095 | |||
5096 | // sequential zero bytes are encoded as 0 [U8 count] | ||
5097 | // with 0 0 [count] representing wrap (>256 zeroes) | ||
5098 | |||
5099 | while (count--) | ||
5100 | { | ||
5101 | if (!(*inptr)) // in a zero count | ||
5102 | { | ||
5103 | if (num_zeroes) | ||
5104 | { | ||
5105 | if (++num_zeroes > 254) | ||
5106 | { | ||
5107 | num_zeroes = 0; | ||
5108 | } | ||
5109 | net_gain--; // subseqent zeroes save one | ||
5110 | } | ||
5111 | else | ||
5112 | { | ||
5113 | net_gain++; // starting a zero count adds one | ||
5114 | num_zeroes = 1; | ||
5115 | } | ||
5116 | inptr++; | ||
5117 | } | ||
5118 | else | ||
5119 | { | ||
5120 | if (num_zeroes) | ||
5121 | { | ||
5122 | num_zeroes = 0; | ||
5123 | } | ||
5124 | inptr++; | ||
5125 | } | ||
5126 | } | ||
5127 | if (net_gain < 0) | ||
5128 | { | ||
5129 | return net_gain; | ||
5130 | } | ||
5131 | else | ||
5132 | { | ||
5133 | return 0; | ||
5134 | } | ||
5135 | } | ||
5136 | |||
5137 | |||
5138 | |||
5139 | S32 LLMessageSystem::zeroCodeExpand(U8 **data, S32 *data_size) | ||
5140 | { | ||
5141 | |||
5142 | if ((*data_size ) < LL_PACKET_ID_SIZE) | ||
5143 | { | ||
5144 | llwarns << "zeroCodeExpand() called with data_size of " << *data_size << llendl; | ||
5145 | } | ||
5146 | |||
5147 | mTotalBytesIn += *data_size; | ||
5148 | |||
5149 | if (!(*data[0] & LL_ZERO_CODE_FLAG)) // if we're not zero-coded, just go 'way | ||
5150 | { | ||
5151 | return(0); | ||
5152 | } | ||
5153 | |||
5154 | S32 in_size = *data_size; | ||
5155 | mCompressedPacketsIn++; | ||
5156 | mCompressedBytesIn += *data_size; | ||
5157 | |||
5158 | *data[0] &= (~LL_ZERO_CODE_FLAG); | ||
5159 | |||
5160 | S32 count = (*data_size); | ||
5161 | |||
5162 | U8 *inptr = (U8 *)*data; | ||
5163 | U8 *outptr = (U8 *)mEncodedRecvBuffer; | ||
5164 | |||
5165 | // skip the packet id field | ||
5166 | |||
5167 | for (U32 i=0;i<LL_PACKET_ID_SIZE;i++) | ||
5168 | { | ||
5169 | count--; | ||
5170 | *outptr++ = *inptr++; | ||
5171 | } | ||
5172 | |||
5173 | // reconstruct encoded packet, keeping track of net size gain | ||
5174 | |||
5175 | // sequential zero bytes are encoded as 0 [U8 count] | ||
5176 | // with 0 0 [count] representing wrap (>256 zeroes) | ||
5177 | |||
5178 | while (count--) | ||
5179 | { | ||
5180 | if (outptr > (&mEncodedRecvBuffer[MAX_BUFFER_SIZE-1])) | ||
5181 | { | ||
5182 | llwarns << "attempt to write past reasonable encoded buffer size 1" << llendl; | ||
5183 | callExceptionFunc(MX_WROTE_PAST_BUFFER_SIZE); | ||
5184 | outptr = mEncodedRecvBuffer; | ||
5185 | break; | ||
5186 | } | ||
5187 | if (!((*outptr++ = *inptr++))) | ||
5188 | { | ||
5189 | while (((count--)) && (!(*inptr))) | ||
5190 | { | ||
5191 | *outptr++ = *inptr++; | ||
5192 | if (outptr > (&mEncodedRecvBuffer[MAX_BUFFER_SIZE-256])) | ||
5193 | { | ||
5194 | llwarns << "attempt to write past reasonable encoded buffer size 2" << llendl; | ||
5195 | callExceptionFunc(MX_WROTE_PAST_BUFFER_SIZE); | ||
5196 | outptr = mEncodedRecvBuffer; | ||
5197 | count = -1; | ||
5198 | break; | ||
5199 | } | ||
5200 | memset(outptr,0,255); | ||
5201 | outptr += 255; | ||
5202 | } | ||
5203 | |||
5204 | if (count < 0) | ||
5205 | { | ||
5206 | break; | ||
5207 | } | ||
5208 | |||
5209 | else | ||
5210 | { | ||
5211 | if (outptr > (&mEncodedRecvBuffer[MAX_BUFFER_SIZE-(*inptr)])) | ||
5212 | { | ||
5213 | llwarns << "attempt to write past reasonable encoded buffer size 3" << llendl; | ||
5214 | callExceptionFunc(MX_WROTE_PAST_BUFFER_SIZE); | ||
5215 | outptr = mEncodedRecvBuffer; | ||
5216 | } | ||
5217 | memset(outptr,0,(*inptr) - 1); | ||
5218 | outptr += ((*inptr) - 1); | ||
5219 | inptr++; | ||
5220 | } | ||
5221 | } | ||
5222 | } | ||
5223 | |||
5224 | *data = mEncodedRecvBuffer; | ||
5225 | *data_size = (S32)(outptr - mEncodedRecvBuffer); | ||
5226 | mUncompressedBytesIn += *data_size; | ||
5227 | |||
5228 | return(in_size); | ||
5229 | } | ||
5230 | |||
5231 | |||
5232 | void LLMessageSystem::addTemplate(LLMessageTemplate *templatep) | ||
5233 | { | ||
5234 | if (mMessageTemplates.count(templatep->mName) > 0) | ||
5235 | { | ||
5236 | llerrs << templatep->mName << " already used as a template name!" | ||
5237 | << llendl; | ||
5238 | } | ||
5239 | mMessageTemplates[templatep->mName] = templatep; | ||
5240 | mMessageNumbers[templatep->mMessageNumber] = templatep; | ||
5241 | } | ||
5242 | |||
5243 | |||
5244 | void LLMessageSystem::setHandlerFuncFast(const char *name, void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data) | ||
5245 | { | ||
5246 | LLMessageTemplate* msgtemplate = get_ptr_in_map(mMessageTemplates, name); | ||
5247 | if (msgtemplate) | ||
5248 | { | ||
5249 | msgtemplate->setHandlerFunc(handler_func, user_data); | ||
5250 | } | ||
5251 | else | ||
5252 | { | ||
5253 | llerrs << name << " is not a known message name!" << llendl; | ||
5254 | } | ||
5255 | } | ||
5256 | |||
5257 | |||
5258 | bool LLMessageSystem::callHandler(const char *name, | ||
5259 | bool trustedSource, LLMessageSystem* msg) | ||
5260 | { | ||
5261 | name = gMessageStringTable.getString(name); | ||
5262 | LLMessageTemplate* msg_template = mMessageTemplates[(char*)name]; | ||
5263 | if (!msg_template) | ||
5264 | { | ||
5265 | llwarns << "LLMessageSystem::callHandler: unknown message " | ||
5266 | << name << llendl; | ||
5267 | return false; | ||
5268 | } | ||
5269 | |||
5270 | if (msg_template->isBanned(trustedSource)) | ||
5271 | { | ||
5272 | llwarns << "LLMessageSystem::callHandler: banned message " | ||
5273 | << name | ||
5274 | << " from " | ||
5275 | << (trustedSource ? "trusted " : "untrusted ") | ||
5276 | << "source" << llendl; | ||
5277 | return false; | ||
5278 | } | ||
5279 | |||
5280 | return msg_template->callHandlerFunc(msg); | ||
5281 | } | ||
5282 | |||
5283 | |||
5284 | void LLMessageSystem::setExceptionFunc(EMessageException e, | ||
5285 | msg_exception_callback func, | ||
5286 | void* data) | ||
5287 | { | ||
5288 | callbacks_t::iterator it = mExceptionCallbacks.find(e); | ||
5289 | if(it != mExceptionCallbacks.end()) | ||
5290 | { | ||
5291 | mExceptionCallbacks.erase(it); | ||
5292 | } | ||
5293 | if(func) | ||
5294 | { | ||
5295 | mExceptionCallbacks.insert(callbacks_t::value_type(e, exception_t(func, data))); | ||
5296 | } | ||
5297 | } | ||
5298 | |||
5299 | BOOL LLMessageSystem::callExceptionFunc(EMessageException exception) | ||
5300 | { | ||
5301 | callbacks_t::iterator it = mExceptionCallbacks.find(exception); | ||
5302 | if(it != mExceptionCallbacks.end()) | ||
5303 | { | ||
5304 | ((*it).second.first)(this, (*it).second.second,exception); | ||
5305 | return TRUE; | ||
5306 | } | ||
5307 | return FALSE; | ||
5308 | } | ||
5309 | |||
5310 | BOOL LLMessageSystem::isCircuitCodeKnown(U32 code) const | ||
5311 | { | ||
5312 | if(mCircuitCodes.find(code) == mCircuitCodes.end()) | ||
5313 | return FALSE; | ||
5314 | return TRUE; | ||
5315 | } | ||
5316 | |||
5317 | BOOL LLMessageSystem::isMessageFast(const char *msg) | ||
5318 | { | ||
5319 | if (mCurrentRMessageTemplate) | ||
5320 | { | ||
5321 | return(msg == mCurrentRMessageTemplate->mName); | ||
5322 | } | ||
5323 | else | ||
5324 | { | ||
5325 | return FALSE; | ||
5326 | } | ||
5327 | } | ||
5328 | |||
5329 | |||
5330 | char* LLMessageSystem::getMessageName() | ||
5331 | { | ||
5332 | if (mCurrentRMessageTemplate) | ||
5333 | { | ||
5334 | return mCurrentRMessageTemplate->mName; | ||
5335 | } | ||
5336 | else | ||
5337 | { | ||
5338 | return NULL; | ||
5339 | } | ||
5340 | } | ||
5341 | |||
5342 | const LLUUID& LLMessageSystem::getSenderID() const | ||
5343 | { | ||
5344 | LLCircuitData *cdp = mCircuitInfo.findCircuit(mLastSender); | ||
5345 | if (cdp) | ||
5346 | { | ||
5347 | return (cdp->mRemoteID); | ||
5348 | } | ||
5349 | |||
5350 | return LLUUID::null; | ||
5351 | } | ||
5352 | |||
5353 | const LLUUID& LLMessageSystem::getSenderSessionID() const | ||
5354 | { | ||
5355 | LLCircuitData *cdp = mCircuitInfo.findCircuit(mLastSender); | ||
5356 | if (cdp) | ||
5357 | { | ||
5358 | return (cdp->mRemoteSessionID); | ||
5359 | } | ||
5360 | return LLUUID::null; | ||
5361 | } | ||
5362 | |||
5363 | void LLMessageSystem::addVector3Fast(const char *varname, const LLVector3& vec) | ||
5364 | { | ||
5365 | addDataFast(varname, vec.mV, MVT_LLVector3, sizeof(vec.mV)); | ||
5366 | } | ||
5367 | |||
5368 | void LLMessageSystem::addVector3(const char *varname, const LLVector3& vec) | ||
5369 | { | ||
5370 | addDataFast(gMessageStringTable.getString(varname), vec.mV, MVT_LLVector3, sizeof(vec.mV)); | ||
5371 | } | ||
5372 | |||
5373 | void LLMessageSystem::addVector4Fast(const char *varname, const LLVector4& vec) | ||
5374 | { | ||
5375 | addDataFast(varname, vec.mV, MVT_LLVector4, sizeof(vec.mV)); | ||
5376 | } | ||
5377 | |||
5378 | void LLMessageSystem::addVector4(const char *varname, const LLVector4& vec) | ||
5379 | { | ||
5380 | addDataFast(gMessageStringTable.getString(varname), vec.mV, MVT_LLVector4, sizeof(vec.mV)); | ||
5381 | } | ||
5382 | |||
5383 | |||
5384 | void LLMessageSystem::addVector3dFast(const char *varname, const LLVector3d& vec) | ||
5385 | { | ||
5386 | addDataFast(varname, vec.mdV, MVT_LLVector3d, sizeof(vec.mdV)); | ||
5387 | } | ||
5388 | |||
5389 | void LLMessageSystem::addVector3d(const char *varname, const LLVector3d& vec) | ||
5390 | { | ||
5391 | addDataFast(gMessageStringTable.getString(varname), vec.mdV, MVT_LLVector3d, sizeof(vec.mdV)); | ||
5392 | } | ||
5393 | |||
5394 | |||
5395 | void LLMessageSystem::addQuatFast(const char *varname, const LLQuaternion& quat) | ||
5396 | { | ||
5397 | addDataFast(varname, quat.packToVector3().mV, MVT_LLQuaternion, sizeof(LLVector3)); | ||
5398 | } | ||
5399 | |||
5400 | void LLMessageSystem::addQuat(const char *varname, const LLQuaternion& quat) | ||
5401 | { | ||
5402 | addDataFast(gMessageStringTable.getString(varname), quat.packToVector3().mV, MVT_LLQuaternion, sizeof(LLVector3)); | ||
5403 | } | ||
5404 | |||
5405 | |||
5406 | void LLMessageSystem::addUUIDFast(const char *varname, const LLUUID& uuid) | ||
5407 | { | ||
5408 | addDataFast(varname, uuid.mData, MVT_LLUUID, sizeof(uuid.mData)); | ||
5409 | } | ||
5410 | |||
5411 | void LLMessageSystem::addUUID(const char *varname, const LLUUID& uuid) | ||
5412 | { | ||
5413 | addDataFast(gMessageStringTable.getString(varname), uuid.mData, MVT_LLUUID, sizeof(uuid.mData)); | ||
5414 | } | ||
5415 | |||
5416 | void LLMessageSystem::getF32Fast(const char *block, const char *var, F32 &d, S32 blocknum) | ||
5417 | { | ||
5418 | getDataFast(block, var, &d, sizeof(F32), blocknum); | ||
5419 | |||
5420 | if( !llfinite( d ) ) | ||
5421 | { | ||
5422 | llwarns << "non-finite in getF32Fast " << block << " " << var << llendl; | ||
5423 | d = 0; | ||
5424 | } | ||
5425 | } | ||
5426 | |||
5427 | void LLMessageSystem::getF32(const char *block, const char *var, F32 &d, S32 blocknum) | ||
5428 | { | ||
5429 | getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &d, sizeof(F32), blocknum); | ||
5430 | |||
5431 | if( !llfinite( d ) ) | ||
5432 | { | ||
5433 | llwarns << "non-finite in getF32 " << block << " " << var << llendl; | ||
5434 | d = 0; | ||
5435 | } | ||
5436 | } | ||
5437 | |||
5438 | void LLMessageSystem::getF64Fast(const char *block, const char *var, F64 &d, S32 blocknum) | ||
5439 | { | ||
5440 | getDataFast(block, var, &d, sizeof(F64), blocknum); | ||
5441 | |||
5442 | if( !llfinite( d ) ) | ||
5443 | { | ||
5444 | llwarns << "non-finite in getF64Fast " << block << " " << var << llendl; | ||
5445 | d = 0; | ||
5446 | } | ||
5447 | } | ||
5448 | |||
5449 | void LLMessageSystem::getF64(const char *block, const char *var, F64 &d, S32 blocknum) | ||
5450 | { | ||
5451 | getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &d, sizeof(F64), blocknum); | ||
5452 | |||
5453 | if( !llfinite( d ) ) | ||
5454 | { | ||
5455 | llwarns << "non-finite in getF64 " << block << " " << var << llendl; | ||
5456 | d = 0; | ||
5457 | } | ||
5458 | } | ||
5459 | |||
5460 | |||
5461 | void LLMessageSystem::getVector3Fast(const char *block, const char *var, LLVector3 &v, S32 blocknum ) | ||
5462 | { | ||
5463 | getDataFast(block, var, v.mV, sizeof(v.mV), blocknum); | ||
5464 | |||
5465 | if( !v.isFinite() ) | ||
5466 | { | ||
5467 | llwarns << "non-finite in getVector3Fast " << block << " " << var << llendl; | ||
5468 | v.zeroVec(); | ||
5469 | } | ||
5470 | } | ||
5471 | |||
5472 | void LLMessageSystem::getVector3(const char *block, const char *var, LLVector3 &v, S32 blocknum ) | ||
5473 | { | ||
5474 | getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), v.mV, sizeof(v.mV), blocknum); | ||
5475 | |||
5476 | if( !v.isFinite() ) | ||
5477 | { | ||
5478 | llwarns << "non-finite in getVector4 " << block << " " << var << llendl; | ||
5479 | v.zeroVec(); | ||
5480 | } | ||
5481 | } | ||
5482 | |||
5483 | void LLMessageSystem::getVector4Fast(const char *block, const char *var, LLVector4 &v, S32 blocknum ) | ||
5484 | { | ||
5485 | getDataFast(block, var, v.mV, sizeof(v.mV), blocknum); | ||
5486 | |||
5487 | if( !v.isFinite() ) | ||
5488 | { | ||
5489 | llwarns << "non-finite in getVector4Fast " << block << " " << var << llendl; | ||
5490 | v.zeroVec(); | ||
5491 | } | ||
5492 | } | ||
5493 | |||
5494 | void LLMessageSystem::getVector4(const char *block, const char *var, LLVector4 &v, S32 blocknum ) | ||
5495 | { | ||
5496 | getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), v.mV, sizeof(v.mV), blocknum); | ||
5497 | |||
5498 | if( !v.isFinite() ) | ||
5499 | { | ||
5500 | llwarns << "non-finite in getVector3 " << block << " " << var << llendl; | ||
5501 | v.zeroVec(); | ||
5502 | } | ||
5503 | } | ||
5504 | |||
5505 | void LLMessageSystem::getVector3dFast(const char *block, const char *var, LLVector3d &v, S32 blocknum ) | ||
5506 | { | ||
5507 | getDataFast(block, var, v.mdV, sizeof(v.mdV), blocknum); | ||
5508 | |||
5509 | if( !v.isFinite() ) | ||
5510 | { | ||
5511 | llwarns << "non-finite in getVector3dFast " << block << " " << var << llendl; | ||
5512 | v.zeroVec(); | ||
5513 | } | ||
5514 | |||
5515 | } | ||
5516 | |||
5517 | void LLMessageSystem::getVector3d(const char *block, const char *var, LLVector3d &v, S32 blocknum ) | ||
5518 | { | ||
5519 | getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), v.mdV, sizeof(v.mdV), blocknum); | ||
5520 | |||
5521 | if( !v.isFinite() ) | ||
5522 | { | ||
5523 | llwarns << "non-finite in getVector3d " << block << " " << var << llendl; | ||
5524 | v.zeroVec(); | ||
5525 | } | ||
5526 | } | ||
5527 | |||
5528 | void LLMessageSystem::getQuatFast(const char *block, const char *var, LLQuaternion &q, S32 blocknum ) | ||
5529 | { | ||
5530 | LLVector3 vec; | ||
5531 | getDataFast(block, var, vec.mV, sizeof(vec.mV), blocknum); | ||
5532 | if( vec.isFinite() ) | ||
5533 | { | ||
5534 | q.unpackFromVector3( vec ); | ||
5535 | } | ||
5536 | else | ||
5537 | { | ||
5538 | llwarns << "non-finite in getQuatFast " << block << " " << var << llendl; | ||
5539 | q.loadIdentity(); | ||
5540 | } | ||
5541 | } | ||
5542 | |||
5543 | void LLMessageSystem::getQuat(const char *block, const char *var, LLQuaternion &q, S32 blocknum ) | ||
5544 | { | ||
5545 | LLVector3 vec; | ||
5546 | getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), vec.mV, sizeof(vec.mV), blocknum); | ||
5547 | if( vec.isFinite() ) | ||
5548 | { | ||
5549 | q.unpackFromVector3( vec ); | ||
5550 | } | ||
5551 | else | ||
5552 | { | ||
5553 | llwarns << "non-finite in getQuat " << block << " " << var << llendl; | ||
5554 | q.loadIdentity(); | ||
5555 | } | ||
5556 | } | ||
5557 | |||
5558 | void LLMessageSystem::getUUIDFast(const char *block, const char *var, LLUUID &u, S32 blocknum ) | ||
5559 | { | ||
5560 | getDataFast(block, var, u.mData, sizeof(u.mData), blocknum); | ||
5561 | } | ||
5562 | |||
5563 | void LLMessageSystem::getUUID(const char *block, const char *var, LLUUID &u, S32 blocknum ) | ||
5564 | { | ||
5565 | getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), u.mData, sizeof(u.mData), blocknum); | ||
5566 | } | ||
5567 | |||
5568 | bool LLMessageSystem::generateDigestForNumberAndUUIDs(char* digest, const U32 number, const LLUUID &id1, const LLUUID &id2) const | ||
5569 | { | ||
5570 | const char *colon = ":"; | ||
5571 | char tbuf[16]; /* Flawfinder: ignore */ | ||
5572 | LLMD5 d; | ||
5573 | LLString id1string = id1.getString(); | ||
5574 | LLString id2string = id2.getString(); | ||
5575 | std::string shared_secret = get_shared_secret(); | ||
5576 | unsigned char * secret = (unsigned char*)shared_secret.c_str(); | ||
5577 | unsigned char * id1str = (unsigned char*)id1string.c_str(); | ||
5578 | unsigned char * id2str = (unsigned char*)id2string.c_str(); | ||
5579 | |||
5580 | memset(digest, 0, MD5HEX_STR_SIZE); | ||
5581 | |||
5582 | if( secret != NULL) | ||
5583 | { | ||
5584 | d.update(secret, (U32)strlen((char *) secret)); | ||
5585 | } | ||
5586 | |||
5587 | d.update((const unsigned char *) colon, (U32)strlen(colon)); /* Flawfinder: ignore */ | ||
5588 | |||
5589 | snprintf(tbuf, sizeof(tbuf),"%i", number); /* Flawfinder: ignore */ | ||
5590 | d.update((unsigned char *) tbuf, (U32)strlen(tbuf)); /* Flawfinder: ignore */ | ||
5591 | |||
5592 | d.update((const unsigned char *) colon, (U32)strlen(colon)); /* Flawfinder: ignore */ | ||
5593 | if( (char*) id1str != NULL) | ||
5594 | { | ||
5595 | d.update(id1str, (U32)strlen((char *) id1str)); | ||
5596 | } | ||
5597 | d.update((const unsigned char *) colon, (U32)strlen(colon)); /* Flawfinder: ignore */ | ||
5598 | |||
5599 | if( (char*) id2str != NULL) | ||
5600 | { | ||
5601 | d.update(id2str, (U32)strlen((char *) id2str)); | ||
5602 | } | ||
5603 | |||
5604 | d.finalize(); | ||
5605 | d.hex_digest(digest); | ||
5606 | digest[MD5HEX_STR_SIZE - 1] = '\0'; | ||
5607 | |||
5608 | return true; | ||
5609 | } | ||
5610 | |||
5611 | bool LLMessageSystem::generateDigestForWindowAndUUIDs(char* digest, const S32 window, const LLUUID &id1, const LLUUID &id2) const | ||
5612 | { | ||
5613 | if(0 == window) return false; | ||
5614 | std::string shared_secret = get_shared_secret(); | ||
5615 | if(shared_secret.empty()) | ||
5616 | { | ||
5617 | llerrs << "Trying to generate complex digest on a machine without a shared secret!" << llendl; | ||
5618 | } | ||
5619 | |||
5620 | U32 now = time(NULL); | ||
5621 | |||
5622 | now /= window; | ||
5623 | |||
5624 | bool result = generateDigestForNumberAndUUIDs(digest, now, id1, id2); | ||
5625 | |||
5626 | return result; | ||
5627 | } | ||
5628 | |||
5629 | bool LLMessageSystem::isMatchingDigestForWindowAndUUIDs(const char* digest, const S32 window, const LLUUID &id1, const LLUUID &id2) const | ||
5630 | { | ||
5631 | if(0 == window) return false; | ||
5632 | |||
5633 | std::string shared_secret = get_shared_secret(); | ||
5634 | if(shared_secret.empty()) | ||
5635 | { | ||
5636 | llerrs << "Trying to compare complex digests on a machine without a shared secret!" << llendl; | ||
5637 | } | ||
5638 | |||
5639 | char our_digest[MD5HEX_STR_SIZE]; /* Flawfinder: ignore */ | ||
5640 | U32 now = time(NULL); | ||
5641 | |||
5642 | now /= window; | ||
5643 | |||
5644 | // Check 1 window ago, now, and one window from now to catch edge | ||
5645 | // conditions. Process them as current window, one window ago, and | ||
5646 | // one window in the future to catch the edges. | ||
5647 | const S32 WINDOW_BIN_COUNT = 3; | ||
5648 | U32 window_bin[WINDOW_BIN_COUNT]; | ||
5649 | window_bin[0] = now; | ||
5650 | window_bin[1] = now - 1; | ||
5651 | window_bin[2] = now + 1; | ||
5652 | for(S32 i = 0; i < WINDOW_BIN_COUNT; ++i) | ||
5653 | { | ||
5654 | generateDigestForNumberAndUUIDs(our_digest, window_bin[i], id2, id1); | ||
5655 | if(0 == strncmp(digest, our_digest, MD5HEX_STR_BYTES)) | ||
5656 | { | ||
5657 | return true; | ||
5658 | } | ||
5659 | } | ||
5660 | return false; | ||
5661 | } | ||
5662 | |||
5663 | bool LLMessageSystem::generateDigestForNumber(char* digest, const U32 number) const | ||
5664 | { | ||
5665 | memset(digest, 0, MD5HEX_STR_SIZE); | ||
5666 | |||
5667 | LLMD5 d; | ||
5668 | std::string shared_secret = get_shared_secret(); | ||
5669 | d = LLMD5((const unsigned char *)shared_secret.c_str(), number); | ||
5670 | d.hex_digest(digest); | ||
5671 | digest[MD5HEX_STR_SIZE - 1] = '\0'; | ||
5672 | |||
5673 | return true; | ||
5674 | } | ||
5675 | |||
5676 | bool LLMessageSystem::generateDigestForWindow(char* digest, const S32 window) const | ||
5677 | { | ||
5678 | if(0 == window) return false; | ||
5679 | |||
5680 | std::string shared_secret = get_shared_secret(); | ||
5681 | if(shared_secret.empty()) | ||
5682 | { | ||
5683 | llerrs << "Trying to generate simple digest on a machine without a shared secret!" << llendl; | ||
5684 | } | ||
5685 | |||
5686 | U32 now = time(NULL); | ||
5687 | |||
5688 | now /= window; | ||
5689 | |||
5690 | bool result = generateDigestForNumber(digest, now); | ||
5691 | |||
5692 | return result; | ||
5693 | } | ||
5694 | |||
5695 | bool LLMessageSystem::isMatchingDigestForWindow(const char* digest, S32 const window) const | ||
5696 | { | ||
5697 | if(0 == window) return false; | ||
5698 | |||
5699 | std::string shared_secret = get_shared_secret(); | ||
5700 | if(shared_secret.empty()) | ||
5701 | { | ||
5702 | llerrs << "Trying to compare simple digests on a machine without a shared secret!" << llendl; | ||
5703 | } | ||
5704 | |||
5705 | char our_digest[MD5HEX_STR_SIZE]; /* Flawfinder: ignore */ | ||
5706 | U32 now = (S32)time(NULL); | ||
5707 | |||
5708 | now /= window; | ||
5709 | |||
5710 | // Check 1 window ago, now, and one window from now to catch edge | ||
5711 | // conditions. Process them as current window, one window ago, and | ||
5712 | // one window in the future to catch the edges. | ||
5713 | const S32 WINDOW_BIN_COUNT = 3; | ||
5714 | U32 window_bin[WINDOW_BIN_COUNT]; | ||
5715 | window_bin[0] = now; | ||
5716 | window_bin[1] = now - 1; | ||
5717 | window_bin[2] = now + 1; | ||
5718 | for(S32 i = 0; i < WINDOW_BIN_COUNT; ++i) | ||
5719 | { | ||
5720 | generateDigestForNumber(our_digest, window_bin[i]); | ||
5721 | if(0 == strncmp(digest, our_digest, MD5HEX_STR_BYTES)) | ||
5722 | { | ||
5723 | return true; | ||
5724 | } | ||
5725 | } | ||
5726 | return false; | ||
5727 | } | ||
5728 | |||
5729 | void LLMessageSystem::sendCreateTrustedCircuit(const LLHost &host, const LLUUID & id1, const LLUUID & id2) | ||
5730 | { | ||
5731 | std::string shared_secret = get_shared_secret(); | ||
5732 | if(shared_secret.empty()) return; | ||
5733 | char digest[MD5HEX_STR_SIZE]; /* Flawfinder: ignore */ | ||
5734 | if (id1.isNull()) | ||
5735 | { | ||
5736 | llwarns << "Can't send CreateTrustedCircuit to " << host << " because we don't have the local end point ID" << llendl; | ||
5737 | return; | ||
5738 | } | ||
5739 | if (id2.isNull()) | ||
5740 | { | ||
5741 | llwarns << "Can't send CreateTrustedCircuit to " << host << " because we don't have the remote end point ID" << llendl; | ||
5742 | return; | ||
5743 | } | ||
5744 | generateDigestForWindowAndUUIDs(digest, TRUST_TIME_WINDOW, id1, id2); | ||
5745 | newMessageFast(_PREHASH_CreateTrustedCircuit); | ||
5746 | nextBlockFast(_PREHASH_DataBlock); | ||
5747 | addUUIDFast(_PREHASH_EndPointID, id1); | ||
5748 | addBinaryDataFast(_PREHASH_Digest, digest, MD5HEX_STR_BYTES); | ||
5749 | llinfos << "xmitting digest: " << digest << " Host: " << host << llendl; | ||
5750 | sendMessage(host); | ||
5751 | } | ||
5752 | |||
5753 | void LLMessageSystem::sendDenyTrustedCircuit(const LLHost &host) | ||
5754 | { | ||
5755 | mDenyTrustedCircuitSet.insert(host); | ||
5756 | } | ||
5757 | |||
5758 | void LLMessageSystem::reallySendDenyTrustedCircuit(const LLHost &host) | ||
5759 | { | ||
5760 | LLCircuitData *cdp = mCircuitInfo.findCircuit(host); | ||
5761 | if (!cdp) | ||
5762 | { | ||
5763 | llwarns << "Not sending DenyTrustedCircuit to host without a circuit." << llendl; | ||
5764 | return; | ||
5765 | } | ||
5766 | llinfos << "Sending DenyTrustedCircuit to " << host << llendl; | ||
5767 | newMessageFast(_PREHASH_DenyTrustedCircuit); | ||
5768 | nextBlockFast(_PREHASH_DataBlock); | ||
5769 | addUUIDFast(_PREHASH_EndPointID, cdp->getLocalEndPointID()); | ||
5770 | sendMessage(host); | ||
5771 | } | ||
5772 | |||
5773 | void null_message_callback(LLMessageSystem *msg, void **data) | ||
5774 | { | ||
5775 | // Nothing should ever go here, but we use this to register messages | ||
5776 | // that we are expecting to see (and spinning on) at startup. | ||
5777 | return; | ||
5778 | } | ||
5779 | |||
5780 | // Try to establish a bidirectional trust metric by pinging a host until it's | ||
5781 | // up, and then sending auth messages. | ||
5782 | void LLMessageSystem::establishBidirectionalTrust(const LLHost &host, S64 frame_count ) | ||
5783 | { | ||
5784 | std::string shared_secret = get_shared_secret(); | ||
5785 | if(shared_secret.empty()) | ||
5786 | { | ||
5787 | llerrs << "Trying to establish bidirectional trust on a machine without a shared secret!" << llendl; | ||
5788 | } | ||
5789 | LLTimer timeout; | ||
5790 | |||
5791 | timeout.setTimerExpirySec(20.0); | ||
5792 | setHandlerFuncFast(_PREHASH_StartPingCheck, null_message_callback, NULL); | ||
5793 | setHandlerFuncFast(_PREHASH_CompletePingCheck, null_message_callback, | ||
5794 | NULL); | ||
5795 | |||
5796 | while (! timeout.hasExpired()) | ||
5797 | { | ||
5798 | newMessageFast(_PREHASH_StartPingCheck); | ||
5799 | nextBlockFast(_PREHASH_PingID); | ||
5800 | addU8Fast(_PREHASH_PingID, 0); | ||
5801 | addU32Fast(_PREHASH_OldestUnacked, 0); | ||
5802 | sendMessage(host); | ||
5803 | if (checkMessages( frame_count )) | ||
5804 | { | ||
5805 | if (isMessageFast(_PREHASH_CompletePingCheck) && | ||
5806 | (getSender() == host)) | ||
5807 | { | ||
5808 | break; | ||
5809 | } | ||
5810 | } | ||
5811 | processAcks(); | ||
5812 | ms_sleep(1); | ||
5813 | } | ||
5814 | |||
5815 | // Send a request, a deny, and give the host 2 seconds to complete | ||
5816 | // the trust handshake. | ||
5817 | newMessage("RequestTrustedCircuit"); | ||
5818 | sendMessage(host); | ||
5819 | reallySendDenyTrustedCircuit(host); | ||
5820 | setHandlerFuncFast(_PREHASH_StartPingCheck, process_start_ping_check, NULL); | ||
5821 | setHandlerFuncFast(_PREHASH_CompletePingCheck, process_complete_ping_check, NULL); | ||
5822 | |||
5823 | timeout.setTimerExpirySec(2.0); | ||
5824 | LLCircuitData* cdp = NULL; | ||
5825 | while(!timeout.hasExpired()) | ||
5826 | { | ||
5827 | cdp = mCircuitInfo.findCircuit(host); | ||
5828 | if(!cdp) break; // no circuit anymore, no point continuing. | ||
5829 | if(cdp->getTrusted()) break; // circuit is trusted. | ||
5830 | checkMessages(frame_count); | ||
5831 | processAcks(); | ||
5832 | ms_sleep(1); | ||
5833 | } | ||
5834 | } | ||
5835 | |||
5836 | |||
5837 | void LLMessageSystem::dumpPacketToLog() | ||
5838 | { | ||
5839 | llwarns << "Packet Dump from:" << mPacketRing.getLastSender() << llendl; | ||
5840 | llwarns << "Packet Size:" << mTrueReceiveSize << llendl; | ||
5841 | char line_buffer[256]; /* Flawfinder: ignore */ | ||
5842 | S32 i; | ||
5843 | S32 cur_line_pos = 0; | ||
5844 | |||
5845 | S32 cur_line = 0; | ||
5846 | for (i = 0; i < mTrueReceiveSize; i++) | ||
5847 | { | ||
5848 | snprintf(line_buffer + cur_line_pos*3, sizeof(line_buffer),"%02x ", mTrueReceiveBuffer[i]); /* Flawfinder: ignore */ | ||
5849 | cur_line_pos++; | ||
5850 | if (cur_line_pos >= 16) | ||
5851 | { | ||
5852 | cur_line_pos = 0; | ||
5853 | llwarns << "PD:" << cur_line << "PD:" << line_buffer << llendl; | ||
5854 | cur_line++; | ||
5855 | } | ||
5856 | } | ||
5857 | if (cur_line_pos) | ||
5858 | { | ||
5859 | llwarns << "PD:" << cur_line << "PD:" << line_buffer << llendl; | ||
5860 | } | ||
5861 | } | ||
5862 | |||
5863 | //static | ||
5864 | U64 LLMessageSystem::getMessageTimeUsecs(const BOOL update) | ||
5865 | { | ||
5866 | if (gMessageSystem) | ||
5867 | { | ||
5868 | if (update) | ||
5869 | { | ||
5870 | gMessageSystem->mCurrentMessageTimeSeconds = totalTime()*SEC_PER_USEC; | ||
5871 | } | ||
5872 | return (U64)(gMessageSystem->mCurrentMessageTimeSeconds * USEC_PER_SEC); | ||
5873 | } | ||
5874 | else | ||
5875 | { | ||
5876 | return totalTime(); | ||
5877 | } | ||
5878 | } | ||
5879 | |||
5880 | //static | ||
5881 | F64 LLMessageSystem::getMessageTimeSeconds(const BOOL update) | ||
5882 | { | ||
5883 | if (gMessageSystem) | ||
5884 | { | ||
5885 | if (update) | ||
5886 | { | ||
5887 | gMessageSystem->mCurrentMessageTimeSeconds = totalTime()*SEC_PER_USEC; | ||
5888 | } | ||
5889 | return gMessageSystem->mCurrentMessageTimeSeconds; | ||
5890 | } | ||
5891 | else | ||
5892 | { | ||
5893 | return totalTime()*SEC_PER_USEC; | ||
5894 | } | ||
5895 | } | ||
5896 | |||
5897 | std::string get_shared_secret() | ||
5898 | { | ||
5899 | static const std::string SHARED_SECRET_KEY("shared_secret"); | ||
5900 | if(g_shared_secret.empty()) | ||
5901 | { | ||
5902 | LLApp* app = LLApp::instance(); | ||
5903 | if(app) return app->getOption(SHARED_SECRET_KEY); | ||
5904 | } | ||
5905 | return g_shared_secret; | ||
5906 | } | ||
5907 | |||