aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llmessage/message.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/llmessage/message.cpp')
-rw-r--r--linden/indra/llmessage/message.cpp5907
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";
73static const F32 CIRCUIT_DUMP_TIMEOUT = 30.f;
74static const S32 TRUST_TIME_WINDOW = 3;
75
76class LLMsgVarData
77{
78public:
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
107protected:
108 char *mName;
109 S32 mSize;
110 S32 mDataSize;
111
112 U8 *mData;
113 EMsgVariableType mType;
114};
115
116
117class LLMsgBlkData
118{
119public:
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
155class LLMsgData
156{
157public:
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
174public:
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
182inline 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
207inline 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
226class LLMessageVariable
227{
228public:
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; }
250protected:
251 char *mName;
252 EMsgVariableType mType;
253 S32 mSize;
254};
255
256
257typedef enum e_message_block_type
258{
259 MBT_NULL,
260 MBT_SINGLE,
261 MBT_MULTIPLE,
262 MBT_VARIABLE,
263 MBT_EOF
264} EMsgBlockType;
265
266class LLMessageBlock
267{
268public:
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
319enum 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
327typedef enum e_message_trust
328{
329 MT_TRUST,
330 MT_NOTRUST
331} EMsgTrust;
332
333enum EMsgEncoding
334{
335 ME_UNENCODED,
336 ME_ZEROCODED
337};
338
339class LLMessageTemplate
340{
341public:
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
442public:
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
462private:
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
471BOOL LLMessageSystem::mTimeDecodes = FALSE;
472
473// static, 50ms per message decode
474F32 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.
480static std::string g_shared_secret;
481std::string get_shared_secret();
482
483class LLMessagePollInfo
484{
485public:
486 apr_socket_t *mAPRSocketp;
487 apr_pollfd_t mPollFD;
488};
489
490
491// LLMessageVariable functions and friends
492
493std::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
513std::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
553std::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'
608BOOL 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'
623BOOL 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'
636BOOL 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'
650BOOL 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'
666BOOL 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'
678BOOL b_return_integer_ok(char c)
679{
680 if ( (c < '0')
681 ||(c > '9'))
682 {
683 return FALSE;
684 }
685 return TRUE;
686}
687
688BOOL (*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
698S32 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
722BOOL 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
766BOOL 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 '-'
777BOOL 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
788BOOL 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
798void 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
851LLMessageSystem::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
891LLMessageSystem::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
960void 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
1715LLMessageSystem::~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
1736void 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
1748BOOL 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.
1769BOOL 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
2159S32 LLMessageSystem::getReceiveBytes() const
2160{
2161 if (getReceiveCompressedSize())
2162 {
2163 return getReceiveCompressedSize() * 8;
2164 }
2165 else
2166 {
2167 return getReceiveSize() * 8;
2168 }
2169}
2170
2171
2172void 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
2243void 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
2282void 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
2327void 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
2347void 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
2446void 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
2506void 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
2546BOOL LLMessageSystem::isSendFull(const char* blockname)
2547{
2548 if(!blockname)
2549 {
2550 return (mCurrentSendTotal > MTUBYTES);
2551 }
2552 return isSendFullFast(gMessageStringTable.getString(blockname));
2553}
2554
2555BOOL 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
2592BOOL 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
2650void 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
2838S32 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
2844S32 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
2863S32 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
2889void LLMessageSystem::forwardMessage(const LLHost &host)
2890{
2891 copyMessageRtoS();
2892 sendMessage(host);
2893}
2894
2895void LLMessageSystem::forwardReliable(const LLHost &host)
2896{
2897 copyMessageRtoS();
2898 sendReliable(host);
2899}
2900
2901void LLMessageSystem::forwardReliable(const U32 circuit_code)
2902{
2903 copyMessageRtoS();
2904 sendReliable(findHost(circuit_code));
2905}
2906
2907S32 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
2938S32 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.
2952S32 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
3155BOOL 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
3221void 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
3252void 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
3281void 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
3318void 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
3335BOOL 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
3532void 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
3615S32 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
3645S32 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
3694S32 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
3735void 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
3778void LLMessageSystem::showCircuitInfo()
3779{
3780 llinfos << mCircuitInfo << llendl;
3781}
3782
3783
3784void LLMessageSystem::dumpCircuitInfo()
3785{
3786 lldebugst(LLERR_CIRCUIT_INFO) << mCircuitInfo << llendl;
3787}
3788
3789/* virtual */
3790U32 LLMessageSystem::getOurCircuitCode()
3791{
3792 return mOurCircuitCode;
3793}
3794
3795LLString 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
3804BOOL 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).
3817void 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
3831void 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
3878void 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
3887void 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
3897BOOL 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
3919BOOL 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
3941BOOL 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
3956void LLMessageSystem::setCircuitProtection(BOOL b_protect)
3957{
3958 mbProtected = b_protect;
3959}
3960
3961
3962U32 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
3971LLHost 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
3983void LLMessageSystem::setMaxMessageTime(const F32 seconds)
3984{
3985 mMaxMessageTime = seconds;
3986}
3987
3988void LLMessageSystem::setMaxMessageCounts(const S32 num)
3989{
3990 mMaxMessageCounts = num;
3991}
3992
3993
3994std::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
4030LLMessageSystem *gMessageSystem = NULL;
4031
4032// update appropriate ping info
4033void 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
4048void 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
4073void 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
4085void close_circuit(LLMessageSystem *msgsystem, void** /*user_data*/)
4086{
4087 msgsystem->disableCircuit(msgsystem->getSender());
4088}
4089
4090// static
4091/*
4092void 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
4118void 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
4133bool 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
4161void 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
4290static 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
4310void 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
4350void 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
4375void 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
4390void 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
4397void 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
4406void 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
4433void 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.
4453void 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
4512void 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
4549void 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
4555BOOL 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
4618void 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
4693BOOL 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
4776void 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
4788void LLMessageSystem::stopLogging()
4789{
4790 if(mVerboseLog)
4791 {
4792 mVerboseLog = FALSE;
4793 llinfos << "END MESSAGE LOG" << llendl;
4794 }
4795}
4796
4797void 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
4889void 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
4906void 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
4920void 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
4968BOOL LLMessageSystem::isClear() const
4969{
4970 return mbSClear;
4971}
4972
4973
4974S32 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
4988U32 LLMessageSystem::getListenPort( void ) const
4989{
4990 return mPort;
4991}
4992
4993
4994S32 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
5071S32 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
5139S32 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
5232void 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
5244void 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
5258bool 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
5284void 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
5299BOOL 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
5310BOOL LLMessageSystem::isCircuitCodeKnown(U32 code) const
5311{
5312 if(mCircuitCodes.find(code) == mCircuitCodes.end())
5313 return FALSE;
5314 return TRUE;
5315}
5316
5317BOOL 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
5330char* LLMessageSystem::getMessageName()
5331{
5332 if (mCurrentRMessageTemplate)
5333 {
5334 return mCurrentRMessageTemplate->mName;
5335 }
5336 else
5337 {
5338 return NULL;
5339 }
5340}
5341
5342const 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
5353const 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
5363void LLMessageSystem::addVector3Fast(const char *varname, const LLVector3& vec)
5364{
5365 addDataFast(varname, vec.mV, MVT_LLVector3, sizeof(vec.mV));
5366}
5367
5368void LLMessageSystem::addVector3(const char *varname, const LLVector3& vec)
5369{
5370 addDataFast(gMessageStringTable.getString(varname), vec.mV, MVT_LLVector3, sizeof(vec.mV));
5371}
5372
5373void LLMessageSystem::addVector4Fast(const char *varname, const LLVector4& vec)
5374{
5375 addDataFast(varname, vec.mV, MVT_LLVector4, sizeof(vec.mV));
5376}
5377
5378void LLMessageSystem::addVector4(const char *varname, const LLVector4& vec)
5379{
5380 addDataFast(gMessageStringTable.getString(varname), vec.mV, MVT_LLVector4, sizeof(vec.mV));
5381}
5382
5383
5384void LLMessageSystem::addVector3dFast(const char *varname, const LLVector3d& vec)
5385{
5386 addDataFast(varname, vec.mdV, MVT_LLVector3d, sizeof(vec.mdV));
5387}
5388
5389void LLMessageSystem::addVector3d(const char *varname, const LLVector3d& vec)
5390{
5391 addDataFast(gMessageStringTable.getString(varname), vec.mdV, MVT_LLVector3d, sizeof(vec.mdV));
5392}
5393
5394
5395void LLMessageSystem::addQuatFast(const char *varname, const LLQuaternion& quat)
5396{
5397 addDataFast(varname, quat.packToVector3().mV, MVT_LLQuaternion, sizeof(LLVector3));
5398}
5399
5400void LLMessageSystem::addQuat(const char *varname, const LLQuaternion& quat)
5401{
5402 addDataFast(gMessageStringTable.getString(varname), quat.packToVector3().mV, MVT_LLQuaternion, sizeof(LLVector3));
5403}
5404
5405
5406void LLMessageSystem::addUUIDFast(const char *varname, const LLUUID& uuid)
5407{
5408 addDataFast(varname, uuid.mData, MVT_LLUUID, sizeof(uuid.mData));
5409}
5410
5411void LLMessageSystem::addUUID(const char *varname, const LLUUID& uuid)
5412{
5413 addDataFast(gMessageStringTable.getString(varname), uuid.mData, MVT_LLUUID, sizeof(uuid.mData));
5414}
5415
5416void 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
5427void 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
5438void 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
5449void 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
5461void 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
5472void 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
5483void 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
5494void 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
5505void 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
5517void 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
5528void 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
5543void 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
5558void 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
5563void 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
5568bool 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
5611bool 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
5629bool 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
5663bool 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
5676bool 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
5695bool 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
5729void 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
5753void LLMessageSystem::sendDenyTrustedCircuit(const LLHost &host)
5754{
5755 mDenyTrustedCircuitSet.insert(host);
5756}
5757
5758void 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
5773void 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.
5782void 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
5837void 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
5864U64 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
5881F64 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
5897std::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