summaryrefslogtreecommitdiff
path: root/indra/llmessage/message.h
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llmessage/message.h')
-rw-r--r--indra/llmessage/message.h1253
1 files changed, 1253 insertions, 0 deletions
diff --git a/indra/llmessage/message.h b/indra/llmessage/message.h
new file mode 100644
index 0000000000..c33016669d
--- /dev/null
+++ b/indra/llmessage/message.h
@@ -0,0 +1,1253 @@
+/**
+ * @file message.h
+ * @brief LLMessageSystem class header file
+ *
+ * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#ifndef LL_MESSAGE_H
+#define LL_MESSAGE_H
+
+#include <cstring>
+#include <stdio.h>
+#include <map>
+#include <set>
+
+#if LL_LINUX
+#include <endian.h>
+#include <netinet/in.h>
+#endif
+
+#if LL_WINDOWS
+#include "winsock2.h" // htons etc.
+#endif
+
+#include "llerror.h"
+#include "net.h"
+#include "string_table.h"
+#include "llptrskipmap.h"
+#include "llcircuit.h"
+#include "lltimer.h"
+#include "llpacketring.h"
+#include "llhost.h"
+#include "llpacketack.h"
+#include "doublelinkedlist.h"
+#include "message_prehash.h"
+#include "llstl.h"
+#include "lldarray.h"
+
+const U32 MESSAGE_MAX_STRINGS_LENGTH = 64;
+const U32 MESSAGE_NUMBER_OF_HASH_BUCKETS = 8192;
+
+const S32 MESSAGE_MAX_PER_FRAME = 400;
+
+// FIXME: This needs to be moved to a server-side only header.
+// 30 Sep 2002 mark
+//extern char *MESSAGE_SHARED_SECRET;
+
+class LLMessageStringTable
+{
+public:
+ LLMessageStringTable();
+ ~LLMessageStringTable();
+
+ char *getString(const char *str);
+
+ U32 mUsed;
+ BOOL mEmpty[MESSAGE_NUMBER_OF_HASH_BUCKETS];
+ char mString[MESSAGE_NUMBER_OF_HASH_BUCKETS][MESSAGE_MAX_STRINGS_LENGTH]; /* Flawfinder: ignore */
+};
+
+extern LLMessageStringTable gMessageStringTable;
+
+// Individual Messages are described with the following format
+// Note that to ease parsing, keywords are used
+//
+// // Comment (Comment like a C++ single line comment)
+// Comments can only be placed between Messages
+// {
+// MessageName (same naming restrictions as C variable)
+// Frequency ("High", "Medium", or "Low" - determines whether message ID is 8, 16, or 32-bits --
+// there can 254 messages in the first 2 groups, 32K in the last group)
+// (A message can be made up only of the Name if it is only a signal)
+// Trust ("Trusted", "NotTrusted" - determines if a message will be accepted
+// on a circuit. "Trusted" messages are not accepted from NotTrusted circuits
+// while NotTrusted messages are accepted on any circuit. An example of a
+// NotTrusted circuit is any circuit from the viewer.)
+// Encoding ("Zerocoded", "Unencoded" - zerocoded messages attempt to compress sequences of
+// zeros, but if there is no space win, it discards the compression and goes unencoded)
+// {
+// Block Name (same naming restrictions as C variable)
+// Block Type ("Single", "Multiple", or "Variable" - determines if the block is coded once,
+// a known number of times, or has a 8 bit argument encoded to tell the decoder
+// how many times the group is repeated)
+// Block Repeat Number (Optional - used only with the "Multiple" type - tells how many times the field is repeated
+// {
+// Variable 1 Name (same naming restrictions as C variable)
+// Variable Type ("Fixed" or "Variable" - determines if the variable is of fixed size or needs to
+// encode an argument describing the size in bytes)
+// Variable Size (In bytes, either of the "Fixed" variable itself or of the size argument)
+//
+// repeat variables
+//
+// }
+//
+// Repeat for number of variables in block
+// }
+//
+// Repeat for number of blocks in message
+// }
+// Repeat for number of messages in file
+//
+
+// Constants
+const S32 MAX_MESSAGE_INTERNAL_NAME_SIZE = 255;
+const S32 MAX_BUFFER_SIZE = NET_BUFFER_SIZE;
+const S32 MAX_BLOCKS = 255;
+
+const U8 LL_ZERO_CODE_FLAG = 0x80;
+const U8 LL_RELIABLE_FLAG = 0x40;
+const U8 LL_RESENT_FLAG = 0x20;
+const U8 LL_ACK_FLAG = 0x10;
+
+const S32 LL_MINIMUM_VALID_PACKET_SIZE = LL_PACKET_ID_SIZE + 1; // 4 bytes id + 1 byte message name (high)
+
+const S32 LL_DEFAULT_RELIABLE_RETRIES = 3;
+const F32 LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS = 1.f;
+const F32 LL_MINIMUM_SEMIRELIABLE_TIMEOUT_SECONDS = 1.f;
+const F32 LL_PING_BASED_TIMEOUT_DUMMY = 0.0f;
+
+// FIXME: These factors shouldn't include the msec to sec conversion implicitly
+const F32 LL_SEMIRELIABLE_TIMEOUT_FACTOR = 5.f / 1000.f; // factor * averaged ping
+const F32 LL_RELIABLE_TIMEOUT_FACTOR = 5.f / 1000.f; // factor * averaged ping
+const F32 LL_FILE_XFER_TIMEOUT_FACTOR = 5.f / 1000.f; // factor * averaged ping
+const F32 LL_LOST_TIMEOUT_FACTOR = 16.f / 1000.f; // factor * averaged ping for marking packets "Lost"
+const F32 LL_MAX_LOST_TIMEOUT = 5.f; // Maximum amount of time before considering something "lost"
+
+const S32 MAX_MESSAGE_COUNT_NUM = 1024;
+
+// Forward declarations
+class LLCircuit;
+class LLVector3;
+class LLVector4;
+class LLVector3d;
+class LLQuaternion;
+class LLSD;
+class LLUUID;
+class LLMessageSystem;
+
+// message data pieces are used to collect the data called for by the message template
+
+// iterator typedefs precede each class as needed
+typedef enum e_message_variable_type
+{
+ MVT_NULL,
+ MVT_FIXED,
+ MVT_VARIABLE,
+ MVT_U8,
+ MVT_U16,
+ MVT_U32,
+ MVT_U64,
+ MVT_S8,
+ MVT_S16,
+ MVT_S32,
+ MVT_S64,
+ MVT_F32,
+ MVT_F64,
+ MVT_LLVector3,
+ MVT_LLVector3d,
+ MVT_LLVector4,
+ MVT_LLQuaternion,
+ MVT_LLUUID,
+ MVT_BOOL,
+ MVT_IP_ADDR,
+ MVT_IP_PORT,
+ MVT_U16Vec3,
+ MVT_U16Quat,
+ MVT_S16Array,
+ MVT_EOL
+} EMsgVariableType;
+
+// message system exceptional condition handlers.
+enum EMessageException
+{
+ MX_UNREGISTERED_MESSAGE, // message number not part of template
+ MX_PACKET_TOO_SHORT, // invalid packet, shorter than minimum packet size
+ MX_RAN_OFF_END_OF_PACKET, // ran off the end of the packet during decode
+ MX_WROTE_PAST_BUFFER_SIZE // wrote past buffer size in zero code expand
+};
+typedef void (*msg_exception_callback)(LLMessageSystem*,void*,EMessageException);
+
+
+
+class LLMsgData;
+class LLMsgBlkData;
+class LLMessageTemplate;
+
+class LLMessagePollInfo;
+
+class LLMessageSystem
+{
+public:
+ U8 mSendBuffer[MAX_BUFFER_SIZE];
+ // Encoded send buffer needs to be slightly larger since the zero
+ // coding can potentially increase the size of the send data.
+ U8 mEncodedSendBuffer[2 * MAX_BUFFER_SIZE];
+ S32 mSendSize;
+ S32 mCurrentSendTotal;
+
+ LLPacketRing mPacketRing;
+ LLReliablePacketParams mReliablePacketParams;
+
+ //LLLinkedList<LLPacketAck> mAckList;
+
+ // Set this flag to TRUE when you want *very* verbose logs.
+ BOOL mVerboseLog;
+
+ U32 mMessageFileChecksum;
+ F32 mMessageFileVersionNumber;
+
+ typedef std::map<const char *, LLMessageTemplate*> message_template_name_map_t;
+ typedef std::map<U32, LLMessageTemplate*> message_template_number_map_t;
+
+private:
+ message_template_name_map_t mMessageTemplates;
+ message_template_number_map_t mMessageNumbers;
+
+public:
+ S32 mSystemVersionMajor;
+ S32 mSystemVersionMinor;
+ S32 mSystemVersionPatch;
+ S32 mSystemVersionServer;
+ U32 mVersionFlags;
+
+
+ BOOL mbProtected;
+
+ U32 mNumberHighFreqMessages;
+ U32 mNumberMediumFreqMessages;
+ U32 mNumberLowFreqMessages;
+ S32 mPort;
+ S32 mSocket;
+
+ U32 mPacketsIn; // total packets in, including compressed and uncompressed
+ U32 mPacketsOut; // total packets out, including compressed and uncompressed
+
+ U64 mBytesIn; // total bytes in, including compressed and uncompressed
+ U64 mBytesOut; // total bytes out, including compressed and uncompressed
+
+ U32 mCompressedPacketsIn; // total compressed packets in
+ U32 mCompressedPacketsOut; // total compressed packets out
+
+ U32 mReliablePacketsIn; // total reliable packets in
+ U32 mReliablePacketsOut; // total reliable packets out
+
+ U32 mDroppedPackets; // total dropped packets in
+ U32 mResentPackets; // total resent packets out
+ U32 mFailedResendPackets; // total resend failure packets out
+ U32 mOffCircuitPackets; // total # of off-circuit packets rejected
+ U32 mInvalidOnCircuitPackets; // total # of on-circuit but invalid packets rejected
+
+ S64 mUncompressedBytesIn; // total uncompressed size of compressed packets in
+ S64 mUncompressedBytesOut; // total uncompressed size of compressed packets out
+ S64 mCompressedBytesIn; // total compressed size of compressed packets in
+ S64 mCompressedBytesOut; // total compressed size of compressed packets out
+ S64 mTotalBytesIn; // total size of all uncompressed packets in
+ S64 mTotalBytesOut; // total size of all uncompressed packets out
+
+ BOOL mSendReliable; // does the outgoing message require a pos ack?
+
+ LLCircuit mCircuitInfo;
+ F64 mCircuitPrintTime; // used to print circuit debug info every couple minutes
+ F32 mCircuitPrintFreq; // seconds
+
+ std::map<U64, U32> mIPPortToCircuitCode;
+ std::map<U32, U64> mCircuitCodeToIPPort;
+ U32 mOurCircuitCode;
+ S32 mSendPacketFailureCount;
+ S32 mUnackedListDepth;
+ S32 mUnackedListSize;
+ S32 mDSMaxListDepth;
+
+public:
+ // Read file and build message templates
+ LLMessageSystem(const char *filename, U32 port, S32 version_major,
+ S32 version_minor, S32 version_patch);
+
+public:
+ // Subclass use.
+ LLMessageSystem();
+
+public:
+ virtual ~LLMessageSystem();
+
+ BOOL isOK() const { return !mbError; }
+ S32 getErrorCode() const { return mErrorCode; }
+
+ // Read file and build message templates filename must point to a
+ // valid string which specifies the path of a valid linden
+ // template.
+ void loadTemplateFile(const char* filename);
+
+
+ // methods for building, sending, receiving, and handling messages
+ void setHandlerFuncFast(const char *name, void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data = NULL);
+ void setHandlerFunc(const char *name, void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data = NULL)
+ {
+ setHandlerFuncFast(gMessageStringTable.getString(name), handler_func, user_data);
+ }
+
+ bool callHandler(const char *name, bool trustedSource,
+ LLMessageSystem* msg);
+
+ // Set a callback function for a message system exception.
+ void setExceptionFunc(EMessageException exception, msg_exception_callback func, void* data = NULL);
+ // Call the specified exception func, and return TRUE if a
+ // function was found and called. Otherwise return FALSE.
+ BOOL callExceptionFunc(EMessageException exception);
+
+ // This method returns true if the code is in the circuit codes map.
+ BOOL isCircuitCodeKnown(U32 code) const;
+
+ // usually called in response to an AddCircuitCode message, but
+ // may also be called by the login process.
+ bool addCircuitCode(U32 code, const LLUUID& session_id);
+
+ BOOL poll(F32 seconds); // Number of seconds that we want to block waiting for data, returns if data was received
+ BOOL checkMessages( S64 frame_count = 0 );
+ void processAcks();
+
+ BOOL isMessageFast(const char *msg);
+ BOOL isMessage(const char *msg)
+ {
+ return isMessageFast(gMessageStringTable.getString(msg));
+ }
+
+ void dumpPacketToLog();
+
+ char *getMessageName();
+
+ const LLHost& getSender() const;
+ U32 getSenderIP() const; // getSender() is preferred
+ U32 getSenderPort() const; // getSender() is preferred
+
+ // This method returns the uuid associated with the sender. The
+ // UUID will be null if it is not yet known or is a server
+ // circuit.
+ const LLUUID& getSenderID() const;
+
+ // This method returns the session id associated with the last
+ // sender.
+ const LLUUID& getSenderSessionID() const;
+
+ // set & get the session id (useful for viewers for now.)
+ void setMySessionID(const LLUUID& session_id) { mSessionID = session_id; }
+ const LLUUID& getMySessionID() { return mSessionID; }
+
+ virtual void newMessageFast(const char *name);
+ void newMessage(const char *name)
+ {
+ newMessageFast(gMessageStringTable.getString(name));
+ }
+
+ void copyMessageRtoS();
+ void clearMessage();
+
+ virtual void nextBlockFast(const char *blockname);
+ void nextBlock(const char *blockname)
+ {
+ nextBlockFast(gMessageStringTable.getString(blockname));
+ }
+private:
+ void addDataFast(const char *varname, const void *data, EMsgVariableType type, S32 size); // Use only for types not in system already
+ void addData(const char *varname, const void *data, EMsgVariableType type, S32 size)
+ {
+ addDataFast(gMessageStringTable.getString(varname), data, type, size);
+ }
+
+
+ void addDataFast(const char *varname, const void *data, EMsgVariableType type); // DEPRECATED - not typed, doesn't check storage space
+ void addData(const char *varname, const void *data, EMsgVariableType type)
+ {
+ addDataFast(gMessageStringTable.getString(varname), data, type);
+ }
+public:
+ void addBinaryDataFast(const char *varname, const void *data, S32 size)
+ {
+ addDataFast(varname, data, MVT_FIXED, size);
+ }
+ void addBinaryData(const char *varname, const void *data, S32 size)
+ {
+ addDataFast(gMessageStringTable.getString(varname), data, MVT_FIXED, size);
+ }
+
+ void addBOOLFast( const char* varname, BOOL b); // typed, checks storage space
+ void addBOOL( const char* varname, BOOL b); // typed, checks storage space
+ void addS8Fast( const char *varname, S8 s); // typed, checks storage space
+ void addS8( const char *varname, S8 s); // typed, checks storage space
+ void addU8Fast( const char *varname, U8 u); // typed, checks storage space
+ void addU8( const char *varname, U8 u); // typed, checks storage space
+ void addS16Fast( const char *varname, S16 i); // typed, checks storage space
+ void addS16( const char *varname, S16 i); // typed, checks storage space
+ void addU16Fast( const char *varname, U16 i); // typed, checks storage space
+ void addU16( const char *varname, U16 i); // typed, checks storage space
+ void addF32Fast( const char *varname, F32 f); // typed, checks storage space
+ void addF32( const char *varname, F32 f); // typed, checks storage space
+ void addS32Fast( const char *varname, S32 s); // typed, checks storage space
+ void addS32( const char *varname, S32 s); // typed, checks storage space
+ virtual void addU32Fast( const char *varname, U32 u); // typed, checks storage space
+ void addU32( const char *varname, U32 u); // typed, checks storage space
+ void addU64Fast( const char *varname, U64 lu); // typed, checks storage space
+ void addU64( const char *varname, U64 lu); // typed, checks storage space
+ void addF64Fast( const char *varname, F64 d); // typed, checks storage space
+ void addF64( const char *varname, F64 d); // typed, checks storage space
+ void addVector3Fast( const char *varname, const LLVector3& vec); // typed, checks storage space
+ void addVector3( const char *varname, const LLVector3& vec); // typed, checks storage space
+ void addVector4Fast( const char *varname, const LLVector4& vec); // typed, checks storage space
+ void addVector4( const char *varname, const LLVector4& vec); // typed, checks storage space
+ void addVector3dFast( const char *varname, const LLVector3d& vec); // typed, checks storage space
+ void addVector3d( const char *varname, const LLVector3d& vec); // typed, checks storage space
+ void addQuatFast( const char *varname, const LLQuaternion& quat); // typed, checks storage space
+ void addQuat( const char *varname, const LLQuaternion& quat); // typed, checks storage space
+ virtual void addUUIDFast( const char *varname, const LLUUID& uuid); // typed, checks storage space
+ void addUUID( const char *varname, const LLUUID& uuid); // typed, checks storage space
+ void addIPAddrFast( const char *varname, const U32 ip); // typed, checks storage space
+ void addIPAddr( const char *varname, const U32 ip); // typed, checks storage space
+ void addIPPortFast( const char *varname, const U16 port); // typed, checks storage space
+ void addIPPort( const char *varname, const U16 port); // typed, checks storage space
+ void addStringFast( const char* varname, const char* s); // typed, checks storage space
+ void addString( const char* varname, const char* s); // typed, checks storage space
+ void addStringFast( const char* varname, const std::string& s); // typed, checks storage space
+ void addString( const char* varname, const std::string& s); // typed, checks storage space
+
+ S32 getCurrentSendTotal() const { return mCurrentSendTotal; }
+
+ // This method checks for current send total and returns true if
+ // you need to go to the next block type or need to start a new
+ // message. Specify the current blockname to check block counts,
+ // otherwise the method only checks against MTU.
+ BOOL isSendFull(const char* blockname = NULL);
+ BOOL isSendFullFast(const char* blockname = NULL);
+
+ BOOL removeLastBlock();
+
+ void buildMessage();
+
+ S32 zeroCode(U8 **data, S32 *data_size);
+ S32 zeroCodeExpand(U8 **data, S32 *data_size);
+ S32 zeroCodeAdjustCurrentSendTotal();
+
+ // Uses ping-based retry
+ virtual S32 sendReliable(const LLHost &host);
+
+ // Uses ping-based retry
+ S32 sendReliable(const U32 circuit) { return sendReliable(findHost(circuit)); }
+
+ // Use this one if you DON'T want automatic ping-based retry.
+ S32 sendReliable( const LLHost &host,
+ S32 retries,
+ BOOL ping_based_retries,
+ F32 timeout,
+ void (*callback)(void **,S32),
+ void ** callback_data);
+
+ S32 sendSemiReliable( const LLHost &host,
+ void (*callback)(void **,S32), void ** callback_data);
+
+ // flush sends a message only if data's been pushed on it.
+ S32 flushSemiReliable( const LLHost &host,
+ void (*callback)(void **,S32), void ** callback_data);
+
+ S32 flushReliable( const LLHost &host );
+
+ void forwardMessage(const LLHost &host);
+ void forwardReliable(const LLHost &host);
+ void forwardReliable(const U32 circuit_code);
+
+ S32 sendMessage(const LLHost &host);
+ S32 sendMessage(const U32 circuit);
+
+ BOOL decodeData(const U8 *buffer, const LLHost &host);
+
+ // TODO: Consolide these functions
+ // TODO: Make these private, force use of typed functions.
+ // If size is not 0, an error is generated if size doesn't exactly match the size of the data.
+ // At all times, the number if bytes written to *datap is <= max_size.
+private:
+ void getDataFast(const char *blockname, const char *varname, void *datap, S32 size = 0, S32 blocknum = 0, S32 max_size = S32_MAX);
+ void getData(const char *blockname, const char *varname, void *datap, S32 size = 0, S32 blocknum = 0, S32 max_size = S32_MAX)
+ {
+ getDataFast(gMessageStringTable.getString(blockname), gMessageStringTable.getString(varname), datap, size, blocknum, max_size);
+ }
+public:
+ void getBinaryDataFast(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum = 0, S32 max_size = S32_MAX)
+ {
+ getDataFast(blockname, varname, datap, size, blocknum, max_size);
+ }
+ void getBinaryData(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum = 0, S32 max_size = S32_MAX)
+ {
+ getDataFast(gMessageStringTable.getString(blockname), gMessageStringTable.getString(varname), datap, size, blocknum, max_size);
+ }
+
+ void getBOOLFast( const char *block, const char *var, BOOL &data, S32 blocknum = 0);
+ void getBOOL( const char *block, const char *var, BOOL &data, S32 blocknum = 0);
+ void getS8Fast( const char *block, const char *var, S8 &data, S32 blocknum = 0);
+ void getS8( const char *block, const char *var, S8 &data, S32 blocknum = 0);
+ void getU8Fast( const char *block, const char *var, U8 &data, S32 blocknum = 0);
+ void getU8( const char *block, const char *var, U8 &data, S32 blocknum = 0);
+ void getS16Fast( const char *block, const char *var, S16 &data, S32 blocknum = 0);
+ void getS16( const char *block, const char *var, S16 &data, S32 blocknum = 0);
+ void getU16Fast( const char *block, const char *var, U16 &data, S32 blocknum = 0);
+ void getU16( const char *block, const char *var, U16 &data, S32 blocknum = 0);
+ void getS32Fast( const char *block, const char *var, S32 &data, S32 blocknum = 0);
+ void getS32( const char *block, const char *var, S32 &data, S32 blocknum = 0);
+ void getF32Fast( const char *block, const char *var, F32 &data, S32 blocknum = 0);
+ void getF32( const char *block, const char *var, F32 &data, S32 blocknum = 0);
+ virtual void getU32Fast( const char *block, const char *var, U32 &data, S32 blocknum = 0);
+ void getU32( const char *block, const char *var, U32 &data, S32 blocknum = 0);
+ virtual void getU64Fast( const char *block, const char *var, U64 &data, S32 blocknum = 0);
+ void getU64( const char *block, const char *var, U64 &data, S32 blocknum = 0);
+ void getF64Fast( const char *block, const char *var, F64 &data, S32 blocknum = 0);
+ void getF64( const char *block, const char *var, F64 &data, S32 blocknum = 0);
+ void getVector3Fast( const char *block, const char *var, LLVector3 &vec, S32 blocknum = 0);
+ void getVector3( const char *block, const char *var, LLVector3 &vec, S32 blocknum = 0);
+ void getVector4Fast( const char *block, const char *var, LLVector4 &vec, S32 blocknum = 0);
+ void getVector4( const char *block, const char *var, LLVector4 &vec, S32 blocknum = 0);
+ void getVector3dFast(const char *block, const char *var, LLVector3d &vec, S32 blocknum = 0);
+ void getVector3d(const char *block, const char *var, LLVector3d &vec, S32 blocknum = 0);
+ void getQuatFast( const char *block, const char *var, LLQuaternion &q, S32 blocknum = 0);
+ void getQuat( const char *block, const char *var, LLQuaternion &q, S32 blocknum = 0);
+ virtual void getUUIDFast( const char *block, const char *var, LLUUID &uuid, S32 blocknum = 0);
+ void getUUID( const char *block, const char *var, LLUUID &uuid, S32 blocknum = 0);
+ virtual void getIPAddrFast( const char *block, const char *var, U32 &ip, S32 blocknum = 0);
+ void getIPAddr( const char *block, const char *var, U32 &ip, S32 blocknum = 0);
+ virtual void getIPPortFast( const char *block, const char *var, U16 &port, S32 blocknum = 0);
+ void getIPPort( const char *block, const char *var, U16 &port, S32 blocknum = 0);
+ virtual void getStringFast( const char *block, const char *var, S32 buffer_size, char *buffer, S32 blocknum = 0);
+ void getString( const char *block, const char *var, S32 buffer_size, char *buffer, S32 blocknum = 0);
+
+
+ // Utility functions to generate a replay-resistant digest check
+ // against the shared secret. The window specifies how much of a
+ // time window is allowed - 1 second is good for tight
+ // connections, but multi-process windows might want to be upwards
+ // of 5 seconds. For generateDigest, you want to pass in a
+ // character array of at least MD5HEX_STR_SIZE so that the hex
+ // digest and null termination will fit.
+ bool generateDigestForNumberAndUUIDs(char* digest, const U32 number, const LLUUID &id1, const LLUUID &id2) const;
+ bool generateDigestForWindowAndUUIDs(char* digest, const S32 window, const LLUUID &id1, const LLUUID &id2) const;
+ bool isMatchingDigestForWindowAndUUIDs(const char* digest, const S32 window, const LLUUID &id1, const LLUUID &id2) const;
+
+ bool generateDigestForNumber(char* digest, const U32 number) const;
+ bool generateDigestForWindow(char* digest, const S32 window) const;
+ bool isMatchingDigestForWindow(const char* digest, const S32 window) const;
+
+ void showCircuitInfo();
+ LLString getCircuitInfoString();
+
+ virtual U32 getOurCircuitCode();
+
+ void enableCircuit(const LLHost &host, BOOL trusted);
+ void disableCircuit(const LLHost &host);
+
+ // Use this to establish trust on startup and in response to
+ // DenyTrustedCircuit.
+ void sendCreateTrustedCircuit(const LLHost& host, const LLUUID & id1, const LLUUID & id2);
+
+ // Use this to inform a peer that they aren't currently trusted...
+ // This now enqueues the request so that we can ensure that we only send
+ // one deny per circuit per message loop so that this doesn't become a DoS.
+ // The actual sending is done by reallySendDenyTrustedCircuit()
+ void sendDenyTrustedCircuit(const LLHost &host);
+
+private:
+ // A list of the circuits that need to be sent DenyTrustedCircuit messages.
+ typedef std::set<LLHost> host_set_t;
+ host_set_t mDenyTrustedCircuitSet;
+
+ // Really sends the DenyTrustedCircuit message to a given host
+ // related to sendDenyTrustedCircuit()
+ void reallySendDenyTrustedCircuit(const LLHost &host);
+
+
+public:
+ // Use this to establish trust to and from a host. This blocks
+ // until trust has been established, and probably should only be
+ // used on startup.
+ void establishBidirectionalTrust(const LLHost &host, S64 frame_count = 0);
+
+ // returns whether the given host is on a trusted circuit
+ BOOL getCircuitTrust(const LLHost &host);
+
+ void setCircuitAllowTimeout(const LLHost &host, BOOL allow);
+ void setCircuitTimeoutCallback(const LLHost &host, void (*callback_func)(const LLHost &host, void *user_data), void *user_data);
+
+ BOOL checkCircuitBlocked(const U32 circuit);
+ BOOL checkCircuitAlive(const U32 circuit);
+ BOOL checkCircuitAlive(const LLHost &host);
+ void setCircuitProtection(BOOL b_protect);
+ U32 findCircuitCode(const LLHost &host);
+ LLHost findHost(const U32 circuit_code);
+ void sanityCheck();
+
+ S32 getNumberOfBlocksFast(const char *blockname);
+ S32 getNumberOfBlocks(const char *blockname)
+ {
+ return getNumberOfBlocksFast(gMessageStringTable.getString(blockname));
+ }
+ S32 getSizeFast(const char *blockname, const char *varname);
+ S32 getSize(const char *blockname, const char *varname)
+ {
+ return getSizeFast(gMessageStringTable.getString(blockname), gMessageStringTable.getString(varname));
+ }
+ S32 getSizeFast(const char *blockname, S32 blocknum, const char *varname); // size in bytes of variable length data
+ S32 getSize(const char *blockname, S32 blocknum, const char *varname)
+ {
+ return getSizeFast(gMessageStringTable.getString(blockname), blocknum, gMessageStringTable.getString(varname));
+ }
+
+ void resetReceiveCounts(); // resets receive counts for all message types to 0
+ void dumpReceiveCounts(); // dumps receive count for each message type to llinfos
+ void dumpCircuitInfo(); // Circuit information to llinfos
+
+ BOOL isClear() const; // returns mbSClear;
+ S32 flush(const LLHost &host);
+
+ U32 getListenPort( void ) const;
+
+ void startLogging(); // start verbose logging
+ void stopLogging(); // flush and close file
+ void summarizeLogs(std::ostream& str); // log statistics
+
+ S32 getReceiveSize() const { return mReceiveSize; }
+ S32 getReceiveCompressedSize() const { return mIncomingCompressedSize; }
+ S32 getReceiveBytes() const;
+
+ S32 getUnackedListSize() const { return mUnackedListSize; }
+
+ const char* getCurrentSMessageName() const { return mCurrentSMessageName; }
+ const char* getCurrentSBlockName() const { return mCurrentSBlockName; }
+
+ // friends
+ friend std::ostream& operator<<(std::ostream& s, LLMessageSystem &msg);
+
+ void setMaxMessageTime(const F32 seconds); // Max time to process messages before warning and dumping (neg to disable)
+ void setMaxMessageCounts(const S32 num); // Max number of messages before dumping (neg to disable)
+
+ // statics
+public:
+ static U64 getMessageTimeUsecs(const BOOL update = FALSE); // Get the current message system time in microseconds
+ static F64 getMessageTimeSeconds(const BOOL update = FALSE); // Get the current message system time in seconds
+
+ static void setTimeDecodes( BOOL b )
+ { LLMessageSystem::mTimeDecodes = b; }
+
+ static void setTimeDecodesSpamThreshold( F32 seconds )
+ { LLMessageSystem::mTimeDecodesSpamThreshold = seconds; }
+
+ // message handlers internal to the message systesm
+ //static void processAssignCircuitCode(LLMessageSystem* msg, void**);
+ static void processAddCircuitCode(LLMessageSystem* msg, void**);
+ static void processUseCircuitCode(LLMessageSystem* msg, void**);
+
+ void setMessageBans(const LLSD& trusted, const LLSD& untrusted);
+
+private:
+ // data used in those internal handlers
+
+ // The mCircuitCodes is a map from circuit codes to session
+ // ids. This allows us to verify sessions on connect.
+ typedef std::map<U32, LLUUID> code_session_map_t;
+ code_session_map_t mCircuitCodes;
+
+ // Viewers need to track a process session in order to make sure
+ // that no one gives them a bad circuit code.
+ LLUUID mSessionID;
+
+private:
+ void addTemplate(LLMessageTemplate *templatep);
+ void clearReceiveState();
+ BOOL decodeTemplate( const U8* buffer, S32 buffer_size, LLMessageTemplate** msg_template );
+
+ void logMsgFromInvalidCircuit( const LLHost& sender, BOOL recv_reliable );
+ void logTrustedMsgFromUntrustedCircuit( const LLHost& sender );
+ void logValidMsg(LLCircuitData *cdp, const LLHost& sender, BOOL recv_reliable, BOOL recv_resent, BOOL recv_acks );
+ void logRanOffEndOfPacket( const LLHost& sender );
+
+private:
+ class LLMessageCountInfo
+ {
+ public:
+ U32 mMessageNum;
+ U32 mMessageBytes;
+ BOOL mInvalid;
+ };
+
+ LLMessagePollInfo *mPollInfop;
+
+ U8 mEncodedRecvBuffer[MAX_BUFFER_SIZE];
+ U8 mTrueReceiveBuffer[MAX_BUFFER_SIZE];
+ S32 mTrueReceiveSize;
+
+ // Must be valid during decode
+ S32 mReceiveSize;
+ TPACKETID mCurrentRecvPacketID; // packet ID of current receive packet (for reporting)
+ LLMessageTemplate *mCurrentRMessageTemplate;
+ LLMsgData *mCurrentRMessageData;
+ S32 mIncomingCompressedSize; // original size of compressed msg (0 if uncomp.)
+ LLHost mLastSender;
+
+ // send message storage
+ LLMsgData *mCurrentSMessageData;
+ LLMessageTemplate *mCurrentSMessageTemplate;
+ LLMsgBlkData *mCurrentSDataBlock;
+ char *mCurrentSMessageName;
+ char *mCurrentSBlockName;
+
+ BOOL mbError;
+ S32 mErrorCode;
+
+ BOOL mbSBuilt; // is send message built?
+ BOOL mbSClear; // is the send message clear?
+
+ F64 mResendDumpTime; // The last time we dumped resends
+
+ LLMessageCountInfo mMessageCountList[MAX_MESSAGE_COUNT_NUM];
+ S32 mNumMessageCounts;
+ F32 mReceiveTime;
+ F32 mMaxMessageTime; // Max number of seconds for processing messages
+ S32 mMaxMessageCounts; // Max number of messages to process before dumping.
+ F64 mMessageCountTime;
+
+ F64 mCurrentMessageTimeSeconds; // The current "message system time" (updated the first call to checkMessages after a resetReceiveCount
+
+ // message system exceptions
+ typedef std::pair<msg_exception_callback, void*> exception_t;
+ typedef std::map<EMessageException, exception_t> callbacks_t;
+ callbacks_t mExceptionCallbacks;
+
+ // stuff for logging
+ LLTimer mMessageSystemTimer;
+
+ static F32 mTimeDecodesSpamThreshold; // If mTimeDecodes is on, all this many seconds for each msg decode before spamming
+ static BOOL mTimeDecodes; // Measure time for all message decodes if TRUE;
+
+ void LLMessageSystem::init(); // ctor shared initialisation.
+};
+
+
+// external hook into messaging system
+extern LLMessageSystem *gMessageSystem;
+//extern const char* MESSAGE_LOG_FILENAME;
+
+void encrypt_template(const char *src_name, const char *dest_name);
+BOOL decrypt_template(const char *src_name, const char *dest_name);
+
+// Must specific overall system version, which is used to determine
+// if a patch is available in the message template checksum verification.
+// Return TRUE if able to initialize system.
+BOOL start_messaging_system(
+ const std::string& template_name,
+ U32 port,
+ S32 version_major,
+ S32 version_minor,
+ S32 version_patch,
+ BOOL b_dump_prehash_file,
+ const std::string& secret);
+
+void end_messaging_system();
+
+void null_message_callback(LLMessageSystem *msg, void **data);
+void process_log_control(LLMessageSystem* msg, void**);
+
+//
+// Inlines
+//
+
+static inline void *htonmemcpy(void *vs, const void *vct, EMsgVariableType type, size_t n)
+{
+ char *s = (char *)vs;
+ const char *ct = (const char *)vct;
+#ifdef LL_BIG_ENDIAN
+ S32 i, length;
+#endif
+ switch(type)
+ {
+ case MVT_FIXED:
+ case MVT_VARIABLE:
+ case MVT_U8:
+ case MVT_S8:
+ case MVT_BOOL:
+ case MVT_LLUUID:
+ case MVT_IP_ADDR: // these two are swizzled in the getters and setters
+ case MVT_IP_PORT: // these two are swizzled in the getters and setters
+ return(memcpy(s,ct,n)); /* Flawfinder: ignore */
+
+ case MVT_U16:
+ case MVT_S16:
+ if (n != 2)
+ {
+ llerrs << "Size argument passed to htonmemcpy doesn't match swizzle type size" << llendl;
+ }
+#ifdef LL_BIG_ENDIAN
+ *(s + 1) = *(ct);
+ *(s) = *(ct + 1);
+ return(vs);
+#else
+ return(memcpy(s,ct,n)); /* Flawfinder: ignore */
+#endif
+
+ case MVT_U32:
+ case MVT_S32:
+ case MVT_F32:
+ if (n != 4)
+ {
+ llerrs << "Size argument passed to htonmemcpy doesn't match swizzle type size" << llendl;
+ }
+#ifdef LL_BIG_ENDIAN
+ *(s + 3) = *(ct);
+ *(s + 2) = *(ct + 1);
+ *(s + 1) = *(ct + 2);
+ *(s) = *(ct + 3);
+ return(vs);
+#else
+ return(memcpy(s,ct,n)); /* Flawfinder: ignore */
+#endif
+
+ case MVT_U64:
+ case MVT_S64:
+ case MVT_F64:
+ if (n != 8)
+ {
+ llerrs << "Size argument passed to htonmemcpy doesn't match swizzle type size" << llendl;
+ }
+#ifdef LL_BIG_ENDIAN
+ *(s + 7) = *(ct);
+ *(s + 6) = *(ct + 1);
+ *(s + 5) = *(ct + 2);
+ *(s + 4) = *(ct + 3);
+ *(s + 3) = *(ct + 4);
+ *(s + 2) = *(ct + 5);
+ *(s + 1) = *(ct + 6);
+ *(s) = *(ct + 7);
+ return(vs);
+#else
+ return(memcpy(s,ct,n)); /* Flawfinder: ignore */
+#endif
+
+ case MVT_LLVector3:
+ case MVT_LLQuaternion: // We only send x, y, z and infer w (we set x, y, z to ensure that w >= 0)
+ if (n != 12)
+ {
+ llerrs << "Size argument passed to htonmemcpy doesn't match swizzle type size" << llendl;
+ }
+#ifdef LL_BIG_ENDIAN
+ htonmemcpy(s + 8, ct + 8, MVT_F32, 4);
+ htonmemcpy(s + 4, ct + 4, MVT_F32, 4);
+ return(htonmemcpy(s, ct, MVT_F32, 4));
+#else
+ return(memcpy(s,ct,n)); /* Flawfinder: ignore */
+#endif
+
+ case MVT_LLVector3d:
+ if (n != 24)
+ {
+ llerrs << "Size argument passed to htonmemcpy doesn't match swizzle type size" << llendl;
+ }
+#ifdef LL_BIG_ENDIAN
+ htonmemcpy(s + 16, ct + 16, MVT_F64, 8);
+ htonmemcpy(s + 8, ct + 8, MVT_F64, 8);
+ return(htonmemcpy(s, ct, MVT_F64, 8));
+#else
+ return(memcpy(s,ct,n)); /* Flawfinder: ignore */
+#endif
+
+ case MVT_LLVector4:
+ if (n != 16)
+ {
+ llerrs << "Size argument passed to htonmemcpy doesn't match swizzle type size" << llendl;
+ }
+#ifdef LL_BIG_ENDIAN
+ htonmemcpy(s + 12, ct + 12, MVT_F32, 4);
+ htonmemcpy(s + 8, ct + 8, MVT_F32, 4);
+ htonmemcpy(s + 4, ct + 4, MVT_F32, 4);
+ return(htonmemcpy(s, ct, MVT_F32, 4));
+#else
+ return(memcpy(s,ct,n)); /* Flawfinder: ignore */
+#endif
+
+ case MVT_U16Vec3:
+ if (n != 6)
+ {
+ llerrs << "Size argument passed to htonmemcpy doesn't match swizzle type size" << llendl;
+ }
+#ifdef LL_BIG_ENDIAN
+ htonmemcpy(s + 4, ct + 4, MVT_U16, 2);
+ htonmemcpy(s + 2, ct + 2, MVT_U16, 2);
+ return(htonmemcpy(s, ct, MVT_U16, 2));
+#else
+ return(memcpy(s,ct,n)); /* Flawfinder: ignore */
+#endif
+
+ case MVT_U16Quat:
+ if (n != 8)
+ {
+ llerrs << "Size argument passed to htonmemcpy doesn't match swizzle type size" << llendl;
+ }
+#ifdef LL_BIG_ENDIAN
+ htonmemcpy(s + 6, ct + 6, MVT_U16, 2);
+ htonmemcpy(s + 4, ct + 4, MVT_U16, 2);
+ htonmemcpy(s + 2, ct + 2, MVT_U16, 2);
+ return(htonmemcpy(s, ct, MVT_U16, 2));
+#else
+ return(memcpy(s,ct,n)); /* Flawfinder: ignore */
+#endif
+
+ case MVT_S16Array:
+ if (n % 2)
+ {
+ llerrs << "Size argument passed to htonmemcpy doesn't match swizzle type size" << llendl;
+ }
+#ifdef LL_BIG_ENDIAN
+ length = n % 2;
+ for (i = 1; i < length; i++)
+ {
+ htonmemcpy(s + i*2, ct + i*2, MVT_S16, 2);
+ }
+ return(htonmemcpy(s, ct, MVT_S16, 2));
+#else
+ return(memcpy(s,ct,n));
+#endif
+
+ default:
+ return(memcpy(s,ct,n)); /* Flawfinder: ignore */
+ }
+}
+
+inline void *ntohmemcpy(void *s, const void *ct, EMsgVariableType type, size_t n)
+{
+ return(htonmemcpy(s,ct,type, n));
+}
+
+
+inline const LLHost& LLMessageSystem::getSender() const
+{
+ return mLastSender;
+}
+
+inline U32 LLMessageSystem::getSenderIP() const
+{
+ return mLastSender.getAddress();
+}
+
+inline U32 LLMessageSystem::getSenderPort() const
+{
+ return mLastSender.getPort();
+}
+
+inline void LLMessageSystem::addS8Fast(const char *varname, S8 s)
+{
+ addDataFast(varname, &s, MVT_S8, sizeof(s));
+}
+
+inline void LLMessageSystem::addS8(const char *varname, S8 s)
+{
+ addDataFast(gMessageStringTable.getString(varname), &s, MVT_S8, sizeof(s));
+}
+
+inline void LLMessageSystem::addU8Fast(const char *varname, U8 u)
+{
+ addDataFast(varname, &u, MVT_U8, sizeof(u));
+}
+
+inline void LLMessageSystem::addU8(const char *varname, U8 u)
+{
+ addDataFast(gMessageStringTable.getString(varname), &u, MVT_U8, sizeof(u));
+}
+
+inline void LLMessageSystem::addS16Fast(const char *varname, S16 i)
+{
+ addDataFast(varname, &i, MVT_S16, sizeof(i));
+}
+
+inline void LLMessageSystem::addS16(const char *varname, S16 i)
+{
+ addDataFast(gMessageStringTable.getString(varname), &i, MVT_S16, sizeof(i));
+}
+
+inline void LLMessageSystem::addU16Fast(const char *varname, U16 i)
+{
+ addDataFast(varname, &i, MVT_U16, sizeof(i));
+}
+
+inline void LLMessageSystem::addU16(const char *varname, U16 i)
+{
+ addDataFast(gMessageStringTable.getString(varname), &i, MVT_U16, sizeof(i));
+}
+
+inline void LLMessageSystem::addF32Fast(const char *varname, F32 f)
+{
+ addDataFast(varname, &f, MVT_F32, sizeof(f));
+}
+
+inline void LLMessageSystem::addF32(const char *varname, F32 f)
+{
+ addDataFast(gMessageStringTable.getString(varname), &f, MVT_F32, sizeof(f));
+}
+
+inline void LLMessageSystem::addS32Fast(const char *varname, S32 s)
+{
+ addDataFast(varname, &s, MVT_S32, sizeof(s));
+}
+
+inline void LLMessageSystem::addS32(const char *varname, S32 s)
+{
+ addDataFast(gMessageStringTable.getString(varname), &s, MVT_S32, sizeof(s));
+}
+
+inline void LLMessageSystem::addU32Fast(const char *varname, U32 u)
+{
+ addDataFast(varname, &u, MVT_U32, sizeof(u));
+}
+
+inline void LLMessageSystem::addU32(const char *varname, U32 u)
+{
+ addDataFast(gMessageStringTable.getString(varname), &u, MVT_U32, sizeof(u));
+}
+
+inline void LLMessageSystem::addU64Fast(const char *varname, U64 lu)
+{
+ addDataFast(varname, &lu, MVT_U64, sizeof(lu));
+}
+
+inline void LLMessageSystem::addU64(const char *varname, U64 lu)
+{
+ addDataFast(gMessageStringTable.getString(varname), &lu, MVT_U64, sizeof(lu));
+}
+
+inline void LLMessageSystem::addF64Fast(const char *varname, F64 d)
+{
+ addDataFast(varname, &d, MVT_F64, sizeof(d));
+}
+
+inline void LLMessageSystem::addF64(const char *varname, F64 d)
+{
+ addDataFast(gMessageStringTable.getString(varname), &d, MVT_F64, sizeof(d));
+}
+
+inline void LLMessageSystem::addIPAddrFast(const char *varname, U32 u)
+{
+ addDataFast(varname, &u, MVT_IP_ADDR, sizeof(u));
+}
+
+inline void LLMessageSystem::addIPAddr(const char *varname, U32 u)
+{
+ addDataFast(gMessageStringTable.getString(varname), &u, MVT_IP_ADDR, sizeof(u));
+}
+
+inline void LLMessageSystem::addIPPortFast(const char *varname, U16 u)
+{
+ u = htons(u);
+ addDataFast(varname, &u, MVT_IP_PORT, sizeof(u));
+}
+
+inline void LLMessageSystem::addIPPort(const char *varname, U16 u)
+{
+ u = htons(u);
+ addDataFast(gMessageStringTable.getString(varname), &u, MVT_IP_PORT, sizeof(u));
+}
+
+inline void LLMessageSystem::addBOOLFast(const char* varname, BOOL b)
+{
+ // Can't just cast a BOOL (actually a U32) to a U8.
+ // In some cases the low order bits will be zero.
+ U8 temp = (b != 0);
+ addDataFast(varname, &temp, MVT_BOOL, sizeof(temp));
+}
+
+inline void LLMessageSystem::addBOOL(const char* varname, BOOL b)
+{
+ // Can't just cast a BOOL (actually a U32) to a U8.
+ // In some cases the low order bits will be zero.
+ U8 temp = (b != 0);
+ addDataFast(gMessageStringTable.getString(varname), &temp, MVT_BOOL, sizeof(temp));
+}
+
+inline void LLMessageSystem::addStringFast(const char* varname, const char* s)
+{
+ if (s)
+ addDataFast( varname, (void *)s, MVT_VARIABLE, (S32)strlen(s) + 1); /* Flawfinder: ignore */
+ else
+ addDataFast( varname, NULL, MVT_VARIABLE, 0);
+}
+
+inline void LLMessageSystem::addString(const char* varname, const char* s)
+{
+ if (s)
+ addDataFast( gMessageStringTable.getString(varname), (void *)s, MVT_VARIABLE, (S32)strlen(s) + 1); /* Flawfinder: ignore */
+ else
+ addDataFast( gMessageStringTable.getString(varname), NULL, MVT_VARIABLE, 0);
+}
+
+inline void LLMessageSystem::addStringFast(const char* varname, const std::string& s)
+{
+ if (s.size())
+ addDataFast( varname, (void *)s.c_str(), MVT_VARIABLE, (S32)(s.size()) + 1);
+ else
+ addDataFast( varname, NULL, MVT_VARIABLE, 0);
+}
+
+inline void LLMessageSystem::addString(const char* varname, const std::string& s)
+{
+ if (s.size())
+ addDataFast( gMessageStringTable.getString(varname), (void *)s.c_str(), MVT_VARIABLE, (S32)(s.size()) + 1);
+ else
+ addDataFast( gMessageStringTable.getString(varname), NULL, MVT_VARIABLE, 0);
+}
+
+
+//-----------------------------------------------------------------------------
+// Retrieval aliases
+//-----------------------------------------------------------------------------
+inline void LLMessageSystem::getS8Fast(const char *block, const char *var, S8 &u, S32 blocknum)
+{
+ getDataFast(block, var, &u, sizeof(S8), blocknum);
+}
+
+inline void LLMessageSystem::getS8(const char *block, const char *var, S8 &u, S32 blocknum)
+{
+ getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &u, sizeof(S8), blocknum);
+}
+
+inline void LLMessageSystem::getU8Fast(const char *block, const char *var, U8 &u, S32 blocknum)
+{
+ getDataFast(block, var, &u, sizeof(U8), blocknum);
+}
+
+inline void LLMessageSystem::getU8(const char *block, const char *var, U8 &u, S32 blocknum)
+{
+ getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &u, sizeof(U8), blocknum);
+}
+
+inline void LLMessageSystem::getBOOLFast(const char *block, const char *var, BOOL &b, S32 blocknum )
+{
+ U8 value;
+ getDataFast(block, var, &value, sizeof(U8), blocknum);
+ b = (BOOL) value;
+}
+
+inline void LLMessageSystem::getBOOL(const char *block, const char *var, BOOL &b, S32 blocknum )
+{
+ U8 value;
+ getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &value, sizeof(U8), blocknum);
+ b = (BOOL) value;
+}
+
+inline void LLMessageSystem::getS16Fast(const char *block, const char *var, S16 &d, S32 blocknum)
+{
+ getDataFast(block, var, &d, sizeof(S16), blocknum);
+}
+
+inline void LLMessageSystem::getS16(const char *block, const char *var, S16 &d, S32 blocknum)
+{
+ getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &d, sizeof(S16), blocknum);
+}
+
+inline void LLMessageSystem::getU16Fast(const char *block, const char *var, U16 &d, S32 blocknum)
+{
+ getDataFast(block, var, &d, sizeof(U16), blocknum);
+}
+
+inline void LLMessageSystem::getU16(const char *block, const char *var, U16 &d, S32 blocknum)
+{
+ getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &d, sizeof(U16), blocknum);
+}
+
+inline void LLMessageSystem::getS32Fast(const char *block, const char *var, S32 &d, S32 blocknum)
+{
+ getDataFast(block, var, &d, sizeof(S32), blocknum);
+}
+
+inline void LLMessageSystem::getS32(const char *block, const char *var, S32 &d, S32 blocknum)
+{
+ getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &d, sizeof(S32), blocknum);
+}
+
+inline void LLMessageSystem::getU32Fast(const char *block, const char *var, U32 &d, S32 blocknum)
+{
+ getDataFast(block, var, &d, sizeof(U32), blocknum);
+}
+
+inline void LLMessageSystem::getU32(const char *block, const char *var, U32 &d, S32 blocknum)
+{
+ getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &d, sizeof(U32), blocknum);
+}
+
+inline void LLMessageSystem::getU64Fast(const char *block, const char *var, U64 &d, S32 blocknum)
+{
+ getDataFast(block, var, &d, sizeof(U64), blocknum);
+}
+
+inline void LLMessageSystem::getU64(const char *block, const char *var, U64 &d, S32 blocknum)
+{
+ getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &d, sizeof(U64), blocknum);
+}
+
+
+inline void LLMessageSystem::getIPAddrFast(const char *block, const char *var, U32 &u, S32 blocknum)
+{
+ getDataFast(block, var, &u, sizeof(U32), blocknum);
+}
+
+inline void LLMessageSystem::getIPAddr(const char *block, const char *var, U32 &u, S32 blocknum)
+{
+ getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &u, sizeof(U32), blocknum);
+}
+
+inline void LLMessageSystem::getIPPortFast(const char *block, const char *var, U16 &u, S32 blocknum)
+{
+ getDataFast(block, var, &u, sizeof(U16), blocknum);
+ u = ntohs(u);
+}
+
+inline void LLMessageSystem::getIPPort(const char *block, const char *var, U16 &u, S32 blocknum)
+{
+ getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &u, sizeof(U16), blocknum);
+ u = ntohs(u);
+}
+
+
+inline void LLMessageSystem::getStringFast(const char *block, const char *var, S32 buffer_size, char *s, S32 blocknum )
+{
+ s[0] = '\0';
+ getDataFast(block, var, s, 0, blocknum, buffer_size);
+ s[buffer_size - 1] = '\0';
+}
+
+inline void LLMessageSystem::getString(const char *block, const char *var, S32 buffer_size, char *s, S32 blocknum )
+{
+ s[0] = '\0';
+ getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), s, 0, blocknum, buffer_size);
+ s[buffer_size - 1] = '\0';
+}
+
+//-----------------------------------------------------------------------------
+// Transmission aliases
+//-----------------------------------------------------------------------------
+//inline S32 LLMessageSystem::sendMessage(U32 ip, U32 port, BOOL zero_code)
+//{
+// return sendMessage(LLHost(ip, port), zero_code);
+//}
+
+//inline S32 LLMessageSystem::sendMessage(const char *ip_str, U32 port, BOOL zero_code)
+//{
+// return sendMessage(LLHost(ip_str, port), zero_code);
+//}
+
+inline S32 LLMessageSystem::sendMessage(const U32 circuit)//, BOOL zero_code)
+{
+ return sendMessage(findHost(circuit));//, zero_code);
+}
+
+#endif