diff options
Diffstat (limited to 'linden/indra/llmessage/message.h')
-rw-r--r-- | linden/indra/llmessage/message.h | 1270 |
1 files changed, 1270 insertions, 0 deletions
diff --git a/linden/indra/llmessage/message.h b/linden/indra/llmessage/message.h new file mode 100644 index 0000000..df062e7 --- /dev/null +++ b/linden/indra/llmessage/message.h | |||
@@ -0,0 +1,1270 @@ | |||
1 | /** | ||
2 | * @file message.h | ||
3 | * @brief LLMessageSystem class header file | ||
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 | #ifndef LL_MESSAGE_H | ||
29 | #define LL_MESSAGE_H | ||
30 | |||
31 | #include <cstring> | ||
32 | #include <stdio.h> | ||
33 | #include <map> | ||
34 | #include <set> | ||
35 | |||
36 | #if LL_LINUX | ||
37 | #include <endian.h> | ||
38 | #include <netinet/in.h> | ||
39 | #endif | ||
40 | |||
41 | #if LL_WINDOWS | ||
42 | #include "winsock2.h" // htons etc. | ||
43 | #endif | ||
44 | |||
45 | #include "llerror.h" | ||
46 | #include "net.h" | ||
47 | #include "string_table.h" | ||
48 | #include "llptrskipmap.h" | ||
49 | #include "llcircuit.h" | ||
50 | #include "lltimer.h" | ||
51 | #include "llpacketring.h" | ||
52 | #include "llhost.h" | ||
53 | #include "llpacketack.h" | ||
54 | #include "doublelinkedlist.h" | ||
55 | #include "message_prehash.h" | ||
56 | #include "llstl.h" | ||
57 | #include "lldarray.h" | ||
58 | |||
59 | const U32 MESSAGE_MAX_STRINGS_LENGTH = 64; | ||
60 | const U32 MESSAGE_NUMBER_OF_HASH_BUCKETS = 8192; | ||
61 | |||
62 | const S32 MESSAGE_MAX_PER_FRAME = 400; | ||
63 | |||
64 | class LLMessageStringTable | ||
65 | { | ||
66 | public: | ||
67 | LLMessageStringTable(); | ||
68 | ~LLMessageStringTable(); | ||
69 | |||
70 | char *getString(const char *str); | ||
71 | |||
72 | U32 mUsed; | ||
73 | BOOL mEmpty[MESSAGE_NUMBER_OF_HASH_BUCKETS]; | ||
74 | char mString[MESSAGE_NUMBER_OF_HASH_BUCKETS][MESSAGE_MAX_STRINGS_LENGTH]; /* Flawfinder: ignore */ | ||
75 | }; | ||
76 | |||
77 | extern LLMessageStringTable gMessageStringTable; | ||
78 | |||
79 | // Individual Messages are described with the following format | ||
80 | // Note that to ease parsing, keywords are used | ||
81 | // | ||
82 | // // Comment (Comment like a C++ single line comment) | ||
83 | // Comments can only be placed between Messages | ||
84 | // { | ||
85 | // MessageName (same naming restrictions as C variable) | ||
86 | // Frequency ("High", "Medium", or "Low" - determines whether message ID is 8, 16, or 32-bits -- | ||
87 | // there can 254 messages in the first 2 groups, 32K in the last group) | ||
88 | // (A message can be made up only of the Name if it is only a signal) | ||
89 | // Trust ("Trusted", "NotTrusted" - determines if a message will be accepted | ||
90 | // on a circuit. "Trusted" messages are not accepted from NotTrusted circuits | ||
91 | // while NotTrusted messages are accepted on any circuit. An example of a | ||
92 | // NotTrusted circuit is any circuit from the viewer.) | ||
93 | // Encoding ("Zerocoded", "Unencoded" - zerocoded messages attempt to compress sequences of | ||
94 | // zeros, but if there is no space win, it discards the compression and goes unencoded) | ||
95 | // { | ||
96 | // Block Name (same naming restrictions as C variable) | ||
97 | // Block Type ("Single", "Multiple", or "Variable" - determines if the block is coded once, | ||
98 | // a known number of times, or has a 8 bit argument encoded to tell the decoder | ||
99 | // how many times the group is repeated) | ||
100 | // Block Repeat Number (Optional - used only with the "Multiple" type - tells how many times the field is repeated | ||
101 | // { | ||
102 | // Variable 1 Name (same naming restrictions as C variable) | ||
103 | // Variable Type ("Fixed" or "Variable" - determines if the variable is of fixed size or needs to | ||
104 | // encode an argument describing the size in bytes) | ||
105 | // Variable Size (In bytes, either of the "Fixed" variable itself or of the size argument) | ||
106 | // | ||
107 | // repeat variables | ||
108 | // | ||
109 | // } | ||
110 | // | ||
111 | // Repeat for number of variables in block | ||
112 | // } | ||
113 | // | ||
114 | // Repeat for number of blocks in message | ||
115 | // } | ||
116 | // Repeat for number of messages in file | ||
117 | // | ||
118 | |||
119 | // Constants | ||
120 | const S32 MAX_MESSAGE_INTERNAL_NAME_SIZE = 255; | ||
121 | const S32 MAX_BUFFER_SIZE = NET_BUFFER_SIZE; | ||
122 | const S32 MAX_BLOCKS = 255; | ||
123 | |||
124 | const U8 LL_ZERO_CODE_FLAG = 0x80; | ||
125 | const U8 LL_RELIABLE_FLAG = 0x40; | ||
126 | const U8 LL_RESENT_FLAG = 0x20; | ||
127 | const U8 LL_ACK_FLAG = 0x10; | ||
128 | |||
129 | const S32 LL_MINIMUM_VALID_PACKET_SIZE = LL_PACKET_ID_SIZE + 1; // 4 bytes id + 1 byte message name (high) | ||
130 | |||
131 | const S32 LL_DEFAULT_RELIABLE_RETRIES = 3; | ||
132 | const F32 LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS = 1.f; | ||
133 | const F32 LL_MINIMUM_SEMIRELIABLE_TIMEOUT_SECONDS = 1.f; | ||
134 | const F32 LL_PING_BASED_TIMEOUT_DUMMY = 0.0f; | ||
135 | |||
136 | // *NOTE: Maybe these factors shouldn't include the msec to sec conversion | ||
137 | // implicitly. | ||
138 | // However, all units should be MKS. | ||
139 | const F32 LL_SEMIRELIABLE_TIMEOUT_FACTOR = 5.f / 1000.f; // factor * averaged ping | ||
140 | const F32 LL_RELIABLE_TIMEOUT_FACTOR = 5.f / 1000.f; // factor * averaged ping | ||
141 | const F32 LL_FILE_XFER_TIMEOUT_FACTOR = 5.f / 1000.f; // factor * averaged ping | ||
142 | const F32 LL_LOST_TIMEOUT_FACTOR = 16.f / 1000.f; // factor * averaged ping for marking packets "Lost" | ||
143 | const F32 LL_MAX_LOST_TIMEOUT = 5.f; // Maximum amount of time before considering something "lost" | ||
144 | |||
145 | const S32 MAX_MESSAGE_COUNT_NUM = 1024; | ||
146 | |||
147 | // Forward declarations | ||
148 | class LLCircuit; | ||
149 | class LLVector3; | ||
150 | class LLVector4; | ||
151 | class LLVector3d; | ||
152 | class LLQuaternion; | ||
153 | class LLSD; | ||
154 | class LLUUID; | ||
155 | class LLMessageSystem; | ||
156 | |||
157 | // message data pieces are used to collect the data called for by the message template | ||
158 | |||
159 | // iterator typedefs precede each class as needed | ||
160 | typedef enum e_message_variable_type | ||
161 | { | ||
162 | MVT_NULL, | ||
163 | MVT_FIXED, | ||
164 | MVT_VARIABLE, | ||
165 | MVT_U8, | ||
166 | MVT_U16, | ||
167 | MVT_U32, | ||
168 | MVT_U64, | ||
169 | MVT_S8, | ||
170 | MVT_S16, | ||
171 | MVT_S32, | ||
172 | MVT_S64, | ||
173 | MVT_F32, | ||
174 | MVT_F64, | ||
175 | MVT_LLVector3, | ||
176 | MVT_LLVector3d, | ||
177 | MVT_LLVector4, | ||
178 | MVT_LLQuaternion, | ||
179 | MVT_LLUUID, | ||
180 | MVT_BOOL, | ||
181 | MVT_IP_ADDR, | ||
182 | MVT_IP_PORT, | ||
183 | MVT_U16Vec3, | ||
184 | MVT_U16Quat, | ||
185 | MVT_S16Array, | ||
186 | MVT_EOL | ||
187 | } EMsgVariableType; | ||
188 | |||
189 | // message system exceptional condition handlers. | ||
190 | enum EMessageException | ||
191 | { | ||
192 | MX_UNREGISTERED_MESSAGE, // message number not part of template | ||
193 | MX_PACKET_TOO_SHORT, // invalid packet, shorter than minimum packet size | ||
194 | MX_RAN_OFF_END_OF_PACKET, // ran off the end of the packet during decode | ||
195 | MX_WROTE_PAST_BUFFER_SIZE // wrote past buffer size in zero code expand | ||
196 | }; | ||
197 | typedef void (*msg_exception_callback)(LLMessageSystem*,void*,EMessageException); | ||
198 | |||
199 | |||
200 | |||
201 | class LLMsgData; | ||
202 | class LLMsgBlkData; | ||
203 | class LLMessageTemplate; | ||
204 | |||
205 | class LLMessagePollInfo; | ||
206 | |||
207 | class LLMessageSystem | ||
208 | { | ||
209 | public: | ||
210 | U8 mSendBuffer[MAX_BUFFER_SIZE]; | ||
211 | // Encoded send buffer needs to be slightly larger since the zero | ||
212 | // coding can potentially increase the size of the send data. | ||
213 | U8 mEncodedSendBuffer[2 * MAX_BUFFER_SIZE]; | ||
214 | S32 mSendSize; | ||
215 | S32 mCurrentSendTotal; | ||
216 | |||
217 | LLPacketRing mPacketRing; | ||
218 | LLReliablePacketParams mReliablePacketParams; | ||
219 | |||
220 | //LLLinkedList<LLPacketAck> mAckList; | ||
221 | |||
222 | // Set this flag to TRUE when you want *very* verbose logs. | ||
223 | BOOL mVerboseLog; | ||
224 | |||
225 | U32 mMessageFileChecksum; | ||
226 | F32 mMessageFileVersionNumber; | ||
227 | |||
228 | typedef std::map<const char *, LLMessageTemplate*> message_template_name_map_t; | ||
229 | typedef std::map<U32, LLMessageTemplate*> message_template_number_map_t; | ||
230 | |||
231 | private: | ||
232 | message_template_name_map_t mMessageTemplates; | ||
233 | message_template_number_map_t mMessageNumbers; | ||
234 | |||
235 | public: | ||
236 | S32 mSystemVersionMajor; | ||
237 | S32 mSystemVersionMinor; | ||
238 | S32 mSystemVersionPatch; | ||
239 | S32 mSystemVersionServer; | ||
240 | U32 mVersionFlags; | ||
241 | |||
242 | |||
243 | BOOL mbProtected; | ||
244 | |||
245 | U32 mNumberHighFreqMessages; | ||
246 | U32 mNumberMediumFreqMessages; | ||
247 | U32 mNumberLowFreqMessages; | ||
248 | S32 mPort; | ||
249 | S32 mSocket; | ||
250 | |||
251 | U32 mPacketsIn; // total packets in, including compressed and uncompressed | ||
252 | U32 mPacketsOut; // total packets out, including compressed and uncompressed | ||
253 | |||
254 | U64 mBytesIn; // total bytes in, including compressed and uncompressed | ||
255 | U64 mBytesOut; // total bytes out, including compressed and uncompressed | ||
256 | |||
257 | U32 mCompressedPacketsIn; // total compressed packets in | ||
258 | U32 mCompressedPacketsOut; // total compressed packets out | ||
259 | |||
260 | U32 mReliablePacketsIn; // total reliable packets in | ||
261 | U32 mReliablePacketsOut; // total reliable packets out | ||
262 | |||
263 | U32 mDroppedPackets; // total dropped packets in | ||
264 | U32 mResentPackets; // total resent packets out | ||
265 | U32 mFailedResendPackets; // total resend failure packets out | ||
266 | U32 mOffCircuitPackets; // total # of off-circuit packets rejected | ||
267 | U32 mInvalidOnCircuitPackets; // total # of on-circuit but invalid packets rejected | ||
268 | |||
269 | S64 mUncompressedBytesIn; // total uncompressed size of compressed packets in | ||
270 | S64 mUncompressedBytesOut; // total uncompressed size of compressed packets out | ||
271 | S64 mCompressedBytesIn; // total compressed size of compressed packets in | ||
272 | S64 mCompressedBytesOut; // total compressed size of compressed packets out | ||
273 | S64 mTotalBytesIn; // total size of all uncompressed packets in | ||
274 | S64 mTotalBytesOut; // total size of all uncompressed packets out | ||
275 | |||
276 | BOOL mSendReliable; // does the outgoing message require a pos ack? | ||
277 | |||
278 | LLCircuit mCircuitInfo; | ||
279 | F64 mCircuitPrintTime; // used to print circuit debug info every couple minutes | ||
280 | F32 mCircuitPrintFreq; // seconds | ||
281 | |||
282 | std::map<U64, U32> mIPPortToCircuitCode; | ||
283 | std::map<U32, U64> mCircuitCodeToIPPort; | ||
284 | U32 mOurCircuitCode; | ||
285 | S32 mSendPacketFailureCount; | ||
286 | S32 mUnackedListDepth; | ||
287 | S32 mUnackedListSize; | ||
288 | S32 mDSMaxListDepth; | ||
289 | |||
290 | public: | ||
291 | // Read file and build message templates | ||
292 | LLMessageSystem(const char *filename, U32 port, S32 version_major, | ||
293 | S32 version_minor, S32 version_patch); | ||
294 | |||
295 | public: | ||
296 | // Subclass use. | ||
297 | LLMessageSystem(); | ||
298 | |||
299 | public: | ||
300 | virtual ~LLMessageSystem(); | ||
301 | |||
302 | BOOL isOK() const { return !mbError; } | ||
303 | S32 getErrorCode() const { return mErrorCode; } | ||
304 | |||
305 | // Read file and build message templates filename must point to a | ||
306 | // valid string which specifies the path of a valid linden | ||
307 | // template. | ||
308 | void loadTemplateFile(const char* filename); | ||
309 | |||
310 | |||
311 | // methods for building, sending, receiving, and handling messages | ||
312 | void setHandlerFuncFast(const char *name, void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data = NULL); | ||
313 | void setHandlerFunc(const char *name, void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data = NULL) | ||
314 | { | ||
315 | setHandlerFuncFast(gMessageStringTable.getString(name), handler_func, user_data); | ||
316 | } | ||
317 | |||
318 | bool callHandler(const char *name, bool trustedSource, | ||
319 | LLMessageSystem* msg); | ||
320 | |||
321 | // Set a callback function for a message system exception. | ||
322 | void setExceptionFunc(EMessageException exception, msg_exception_callback func, void* data = NULL); | ||
323 | // Call the specified exception func, and return TRUE if a | ||
324 | // function was found and called. Otherwise return FALSE. | ||
325 | BOOL callExceptionFunc(EMessageException exception); | ||
326 | |||
327 | // This method returns true if the code is in the circuit codes map. | ||
328 | BOOL isCircuitCodeKnown(U32 code) const; | ||
329 | |||
330 | // usually called in response to an AddCircuitCode message, but | ||
331 | // may also be called by the login process. | ||
332 | bool addCircuitCode(U32 code, const LLUUID& session_id); | ||
333 | |||
334 | BOOL poll(F32 seconds); // Number of seconds that we want to block waiting for data, returns if data was received | ||
335 | BOOL checkMessages( S64 frame_count = 0 ); | ||
336 | void processAcks(); | ||
337 | |||
338 | BOOL isMessageFast(const char *msg); | ||
339 | BOOL isMessage(const char *msg) | ||
340 | { | ||
341 | return isMessageFast(gMessageStringTable.getString(msg)); | ||
342 | } | ||
343 | |||
344 | void dumpPacketToLog(); | ||
345 | |||
346 | char *getMessageName(); | ||
347 | |||
348 | const LLHost& getSender() const; | ||
349 | U32 getSenderIP() const; // getSender() is preferred | ||
350 | U32 getSenderPort() const; // getSender() is preferred | ||
351 | |||
352 | // This method returns the uuid associated with the sender. The | ||
353 | // UUID will be null if it is not yet known or is a server | ||
354 | // circuit. | ||
355 | const LLUUID& getSenderID() const; | ||
356 | |||
357 | // This method returns the session id associated with the last | ||
358 | // sender. | ||
359 | const LLUUID& getSenderSessionID() const; | ||
360 | |||
361 | // set & get the session id (useful for viewers for now.) | ||
362 | void setMySessionID(const LLUUID& session_id) { mSessionID = session_id; } | ||
363 | const LLUUID& getMySessionID() { return mSessionID; } | ||
364 | |||
365 | virtual void newMessageFast(const char *name); | ||
366 | void newMessage(const char *name) | ||
367 | { | ||
368 | newMessageFast(gMessageStringTable.getString(name)); | ||
369 | } | ||
370 | |||
371 | void copyMessageRtoS(); | ||
372 | void clearMessage(); | ||
373 | |||
374 | virtual void nextBlockFast(const char *blockname); | ||
375 | void nextBlock(const char *blockname) | ||
376 | { | ||
377 | nextBlockFast(gMessageStringTable.getString(blockname)); | ||
378 | } | ||
379 | private: | ||
380 | void addDataFast(const char *varname, const void *data, EMsgVariableType type, S32 size); // Use only for types not in system already | ||
381 | void addData(const char *varname, const void *data, EMsgVariableType type, S32 size) | ||
382 | { | ||
383 | addDataFast(gMessageStringTable.getString(varname), data, type, size); | ||
384 | } | ||
385 | |||
386 | |||
387 | void addDataFast(const char *varname, const void *data, EMsgVariableType type); // DEPRECATED - not typed, doesn't check storage space | ||
388 | void addData(const char *varname, const void *data, EMsgVariableType type) | ||
389 | { | ||
390 | addDataFast(gMessageStringTable.getString(varname), data, type); | ||
391 | } | ||
392 | public: | ||
393 | void addBinaryDataFast(const char *varname, const void *data, S32 size) | ||
394 | { | ||
395 | addDataFast(varname, data, MVT_FIXED, size); | ||
396 | } | ||
397 | void addBinaryData(const char *varname, const void *data, S32 size) | ||
398 | { | ||
399 | addDataFast(gMessageStringTable.getString(varname), data, MVT_FIXED, size); | ||
400 | } | ||
401 | |||
402 | void addBOOLFast( const char* varname, BOOL b); // typed, checks storage space | ||
403 | void addBOOL( const char* varname, BOOL b); // typed, checks storage space | ||
404 | void addS8Fast( const char *varname, S8 s); // typed, checks storage space | ||
405 | void addS8( const char *varname, S8 s); // typed, checks storage space | ||
406 | void addU8Fast( const char *varname, U8 u); // typed, checks storage space | ||
407 | void addU8( const char *varname, U8 u); // typed, checks storage space | ||
408 | void addS16Fast( const char *varname, S16 i); // typed, checks storage space | ||
409 | void addS16( const char *varname, S16 i); // typed, checks storage space | ||
410 | void addU16Fast( const char *varname, U16 i); // typed, checks storage space | ||
411 | void addU16( const char *varname, U16 i); // typed, checks storage space | ||
412 | void addF32Fast( const char *varname, F32 f); // typed, checks storage space | ||
413 | void addF32( const char *varname, F32 f); // typed, checks storage space | ||
414 | void addS32Fast( const char *varname, S32 s); // typed, checks storage space | ||
415 | void addS32( const char *varname, S32 s); // typed, checks storage space | ||
416 | virtual void addU32Fast( const char *varname, U32 u); // typed, checks storage space | ||
417 | void addU32( const char *varname, U32 u); // typed, checks storage space | ||
418 | void addU64Fast( const char *varname, U64 lu); // typed, checks storage space | ||
419 | void addU64( const char *varname, U64 lu); // typed, checks storage space | ||
420 | void addF64Fast( const char *varname, F64 d); // typed, checks storage space | ||
421 | void addF64( const char *varname, F64 d); // typed, checks storage space | ||
422 | void addVector3Fast( const char *varname, const LLVector3& vec); // typed, checks storage space | ||
423 | void addVector3( const char *varname, const LLVector3& vec); // typed, checks storage space | ||
424 | void addVector4Fast( const char *varname, const LLVector4& vec); // typed, checks storage space | ||
425 | void addVector4( const char *varname, const LLVector4& vec); // typed, checks storage space | ||
426 | void addVector3dFast( const char *varname, const LLVector3d& vec); // typed, checks storage space | ||
427 | void addVector3d( const char *varname, const LLVector3d& vec); // typed, checks storage space | ||
428 | void addQuatFast( const char *varname, const LLQuaternion& quat); // typed, checks storage space | ||
429 | void addQuat( const char *varname, const LLQuaternion& quat); // typed, checks storage space | ||
430 | virtual void addUUIDFast( const char *varname, const LLUUID& uuid); // typed, checks storage space | ||
431 | void addUUID( const char *varname, const LLUUID& uuid); // typed, checks storage space | ||
432 | void addIPAddrFast( const char *varname, const U32 ip); // typed, checks storage space | ||
433 | void addIPAddr( const char *varname, const U32 ip); // typed, checks storage space | ||
434 | void addIPPortFast( const char *varname, const U16 port); // typed, checks storage space | ||
435 | void addIPPort( const char *varname, const U16 port); // typed, checks storage space | ||
436 | void addStringFast( const char* varname, const char* s); // typed, checks storage space | ||
437 | void addString( const char* varname, const char* s); // typed, checks storage space | ||
438 | void addStringFast( const char* varname, const std::string& s); // typed, checks storage space | ||
439 | void addString( const char* varname, const std::string& s); // typed, checks storage space | ||
440 | |||
441 | S32 getCurrentSendTotal() const { return mCurrentSendTotal; } | ||
442 | |||
443 | // This method checks for current send total and returns true if | ||
444 | // you need to go to the next block type or need to start a new | ||
445 | // message. Specify the current blockname to check block counts, | ||
446 | // otherwise the method only checks against MTU. | ||
447 | BOOL isSendFull(const char* blockname = NULL); | ||
448 | BOOL isSendFullFast(const char* blockname = NULL); | ||
449 | |||
450 | BOOL removeLastBlock(); | ||
451 | |||
452 | void buildMessage(); | ||
453 | |||
454 | S32 zeroCode(U8 **data, S32 *data_size); | ||
455 | S32 zeroCodeExpand(U8 **data, S32 *data_size); | ||
456 | S32 zeroCodeAdjustCurrentSendTotal(); | ||
457 | |||
458 | // Uses ping-based retry | ||
459 | virtual S32 sendReliable(const LLHost &host); | ||
460 | |||
461 | // Uses ping-based retry | ||
462 | S32 sendReliable(const U32 circuit) { return sendReliable(findHost(circuit)); } | ||
463 | |||
464 | // Use this one if you DON'T want automatic ping-based retry. | ||
465 | S32 sendReliable( const LLHost &host, | ||
466 | S32 retries, | ||
467 | BOOL ping_based_retries, | ||
468 | F32 timeout, | ||
469 | void (*callback)(void **,S32), | ||
470 | void ** callback_data); | ||
471 | |||
472 | S32 sendSemiReliable( const LLHost &host, | ||
473 | void (*callback)(void **,S32), void ** callback_data); | ||
474 | |||
475 | // flush sends a message only if data's been pushed on it. | ||
476 | S32 flushSemiReliable( const LLHost &host, | ||
477 | void (*callback)(void **,S32), void ** callback_data); | ||
478 | |||
479 | S32 flushReliable( const LLHost &host ); | ||
480 | |||
481 | void forwardMessage(const LLHost &host); | ||
482 | void forwardReliable(const LLHost &host); | ||
483 | void forwardReliable(const U32 circuit_code); | ||
484 | |||
485 | S32 sendMessage(const LLHost &host); | ||
486 | S32 sendMessage(const U32 circuit); | ||
487 | |||
488 | BOOL decodeData(const U8 *buffer, const LLHost &host); | ||
489 | |||
490 | // TODO: Consolide these functions | ||
491 | // TODO: Make these private, force use of typed functions. | ||
492 | // If size is not 0, an error is generated if size doesn't exactly match the size of the data. | ||
493 | // At all times, the number if bytes written to *datap is <= max_size. | ||
494 | private: | ||
495 | void getDataFast(const char *blockname, const char *varname, void *datap, S32 size = 0, S32 blocknum = 0, S32 max_size = S32_MAX); | ||
496 | void getData(const char *blockname, const char *varname, void *datap, S32 size = 0, S32 blocknum = 0, S32 max_size = S32_MAX) | ||
497 | { | ||
498 | getDataFast(gMessageStringTable.getString(blockname), gMessageStringTable.getString(varname), datap, size, blocknum, max_size); | ||
499 | } | ||
500 | public: | ||
501 | void getBinaryDataFast(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum = 0, S32 max_size = S32_MAX) | ||
502 | { | ||
503 | getDataFast(blockname, varname, datap, size, blocknum, max_size); | ||
504 | } | ||
505 | void getBinaryData(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum = 0, S32 max_size = S32_MAX) | ||
506 | { | ||
507 | getDataFast(gMessageStringTable.getString(blockname), gMessageStringTable.getString(varname), datap, size, blocknum, max_size); | ||
508 | } | ||
509 | |||
510 | void getBOOLFast( const char *block, const char *var, BOOL &data, S32 blocknum = 0); | ||
511 | void getBOOL( const char *block, const char *var, BOOL &data, S32 blocknum = 0); | ||
512 | void getS8Fast( const char *block, const char *var, S8 &data, S32 blocknum = 0); | ||
513 | void getS8( const char *block, const char *var, S8 &data, S32 blocknum = 0); | ||
514 | void getU8Fast( const char *block, const char *var, U8 &data, S32 blocknum = 0); | ||
515 | void getU8( const char *block, const char *var, U8 &data, S32 blocknum = 0); | ||
516 | void getS16Fast( const char *block, const char *var, S16 &data, S32 blocknum = 0); | ||
517 | void getS16( const char *block, const char *var, S16 &data, S32 blocknum = 0); | ||
518 | void getU16Fast( const char *block, const char *var, U16 &data, S32 blocknum = 0); | ||
519 | void getU16( const char *block, const char *var, U16 &data, S32 blocknum = 0); | ||
520 | void getS32Fast( const char *block, const char *var, S32 &data, S32 blocknum = 0); | ||
521 | void getS32( const char *block, const char *var, S32 &data, S32 blocknum = 0); | ||
522 | void getF32Fast( const char *block, const char *var, F32 &data, S32 blocknum = 0); | ||
523 | void getF32( const char *block, const char *var, F32 &data, S32 blocknum = 0); | ||
524 | virtual void getU32Fast( const char *block, const char *var, U32 &data, S32 blocknum = 0); | ||
525 | void getU32( const char *block, const char *var, U32 &data, S32 blocknum = 0); | ||
526 | virtual void getU64Fast( const char *block, const char *var, U64 &data, S32 blocknum = 0); | ||
527 | void getU64( const char *block, const char *var, U64 &data, S32 blocknum = 0); | ||
528 | void getF64Fast( const char *block, const char *var, F64 &data, S32 blocknum = 0); | ||
529 | void getF64( const char *block, const char *var, F64 &data, S32 blocknum = 0); | ||
530 | void getVector3Fast( const char *block, const char *var, LLVector3 &vec, S32 blocknum = 0); | ||
531 | void getVector3( const char *block, const char *var, LLVector3 &vec, S32 blocknum = 0); | ||
532 | void getVector4Fast( const char *block, const char *var, LLVector4 &vec, S32 blocknum = 0); | ||
533 | void getVector4( const char *block, const char *var, LLVector4 &vec, S32 blocknum = 0); | ||
534 | void getVector3dFast(const char *block, const char *var, LLVector3d &vec, S32 blocknum = 0); | ||
535 | void getVector3d(const char *block, const char *var, LLVector3d &vec, S32 blocknum = 0); | ||
536 | void getQuatFast( const char *block, const char *var, LLQuaternion &q, S32 blocknum = 0); | ||
537 | void getQuat( const char *block, const char *var, LLQuaternion &q, S32 blocknum = 0); | ||
538 | virtual void getUUIDFast( const char *block, const char *var, LLUUID &uuid, S32 blocknum = 0); | ||
539 | void getUUID( const char *block, const char *var, LLUUID &uuid, S32 blocknum = 0); | ||
540 | virtual void getIPAddrFast( const char *block, const char *var, U32 &ip, S32 blocknum = 0); | ||
541 | void getIPAddr( const char *block, const char *var, U32 &ip, S32 blocknum = 0); | ||
542 | virtual void getIPPortFast( const char *block, const char *var, U16 &port, S32 blocknum = 0); | ||
543 | void getIPPort( const char *block, const char *var, U16 &port, S32 blocknum = 0); | ||
544 | virtual void getStringFast( const char *block, const char *var, S32 buffer_size, char *buffer, S32 blocknum = 0); | ||
545 | void getString( const char *block, const char *var, S32 buffer_size, char *buffer, S32 blocknum = 0); | ||
546 | |||
547 | |||
548 | // Utility functions to generate a replay-resistant digest check | ||
549 | // against the shared secret. The window specifies how much of a | ||
550 | // time window is allowed - 1 second is good for tight | ||
551 | // connections, but multi-process windows might want to be upwards | ||
552 | // of 5 seconds. For generateDigest, you want to pass in a | ||
553 | // character array of at least MD5HEX_STR_SIZE so that the hex | ||
554 | // digest and null termination will fit. | ||
555 | bool generateDigestForNumberAndUUIDs(char* digest, const U32 number, const LLUUID &id1, const LLUUID &id2) const; | ||
556 | bool generateDigestForWindowAndUUIDs(char* digest, const S32 window, const LLUUID &id1, const LLUUID &id2) const; | ||
557 | bool isMatchingDigestForWindowAndUUIDs(const char* digest, const S32 window, const LLUUID &id1, const LLUUID &id2) const; | ||
558 | |||
559 | bool generateDigestForNumber(char* digest, const U32 number) const; | ||
560 | bool generateDigestForWindow(char* digest, const S32 window) const; | ||
561 | bool isMatchingDigestForWindow(const char* digest, const S32 window) const; | ||
562 | |||
563 | void showCircuitInfo(); | ||
564 | LLString getCircuitInfoString(); | ||
565 | |||
566 | virtual U32 getOurCircuitCode(); | ||
567 | |||
568 | void enableCircuit(const LLHost &host, BOOL trusted); | ||
569 | void disableCircuit(const LLHost &host); | ||
570 | |||
571 | // Use this to establish trust on startup and in response to | ||
572 | // DenyTrustedCircuit. | ||
573 | void sendCreateTrustedCircuit(const LLHost& host, const LLUUID & id1, const LLUUID & id2); | ||
574 | |||
575 | // Use this to inform a peer that they aren't currently trusted... | ||
576 | // This now enqueues the request so that we can ensure that we only send | ||
577 | // one deny per circuit per message loop so that this doesn't become a DoS. | ||
578 | // The actual sending is done by reallySendDenyTrustedCircuit() | ||
579 | void sendDenyTrustedCircuit(const LLHost &host); | ||
580 | |||
581 | private: | ||
582 | // A list of the circuits that need to be sent DenyTrustedCircuit messages. | ||
583 | typedef std::set<LLHost> host_set_t; | ||
584 | host_set_t mDenyTrustedCircuitSet; | ||
585 | |||
586 | // Really sends the DenyTrustedCircuit message to a given host | ||
587 | // related to sendDenyTrustedCircuit() | ||
588 | void reallySendDenyTrustedCircuit(const LLHost &host); | ||
589 | |||
590 | |||
591 | public: | ||
592 | // Use this to establish trust to and from a host. This blocks | ||
593 | // until trust has been established, and probably should only be | ||
594 | // used on startup. | ||
595 | void establishBidirectionalTrust(const LLHost &host, S64 frame_count = 0); | ||
596 | |||
597 | // returns whether the given host is on a trusted circuit | ||
598 | BOOL getCircuitTrust(const LLHost &host); | ||
599 | |||
600 | void setCircuitAllowTimeout(const LLHost &host, BOOL allow); | ||
601 | void setCircuitTimeoutCallback(const LLHost &host, void (*callback_func)(const LLHost &host, void *user_data), void *user_data); | ||
602 | |||
603 | BOOL checkCircuitBlocked(const U32 circuit); | ||
604 | BOOL checkCircuitAlive(const U32 circuit); | ||
605 | BOOL checkCircuitAlive(const LLHost &host); | ||
606 | void setCircuitProtection(BOOL b_protect); | ||
607 | U32 findCircuitCode(const LLHost &host); | ||
608 | LLHost findHost(const U32 circuit_code); | ||
609 | void sanityCheck(); | ||
610 | |||
611 | S32 getNumberOfBlocksFast(const char *blockname); | ||
612 | S32 getNumberOfBlocks(const char *blockname) | ||
613 | { | ||
614 | return getNumberOfBlocksFast(gMessageStringTable.getString(blockname)); | ||
615 | } | ||
616 | S32 getSizeFast(const char *blockname, const char *varname); | ||
617 | S32 getSize(const char *blockname, const char *varname) | ||
618 | { | ||
619 | return getSizeFast(gMessageStringTable.getString(blockname), gMessageStringTable.getString(varname)); | ||
620 | } | ||
621 | S32 getSizeFast(const char *blockname, S32 blocknum, const char *varname); // size in bytes of variable length data | ||
622 | S32 getSize(const char *blockname, S32 blocknum, const char *varname) | ||
623 | { | ||
624 | return getSizeFast(gMessageStringTable.getString(blockname), blocknum, gMessageStringTable.getString(varname)); | ||
625 | } | ||
626 | |||
627 | void resetReceiveCounts(); // resets receive counts for all message types to 0 | ||
628 | void dumpReceiveCounts(); // dumps receive count for each message type to llinfos | ||
629 | void dumpCircuitInfo(); // Circuit information to llinfos | ||
630 | |||
631 | BOOL isClear() const; // returns mbSClear; | ||
632 | S32 flush(const LLHost &host); | ||
633 | |||
634 | U32 getListenPort( void ) const; | ||
635 | |||
636 | void startLogging(); // start verbose logging | ||
637 | void stopLogging(); // flush and close file | ||
638 | void summarizeLogs(std::ostream& str); // log statistics | ||
639 | |||
640 | S32 getReceiveSize() const { return mReceiveSize; } | ||
641 | S32 getReceiveCompressedSize() const { return mIncomingCompressedSize; } | ||
642 | S32 getReceiveBytes() const; | ||
643 | |||
644 | S32 getUnackedListSize() const { return mUnackedListSize; } | ||
645 | |||
646 | const char* getCurrentSMessageName() const { return mCurrentSMessageName; } | ||
647 | const char* getCurrentSBlockName() const { return mCurrentSBlockName; } | ||
648 | |||
649 | // friends | ||
650 | friend std::ostream& operator<<(std::ostream& s, LLMessageSystem &msg); | ||
651 | |||
652 | void setMaxMessageTime(const F32 seconds); // Max time to process messages before warning and dumping (neg to disable) | ||
653 | void setMaxMessageCounts(const S32 num); // Max number of messages before dumping (neg to disable) | ||
654 | |||
655 | // statics | ||
656 | public: | ||
657 | static U64 getMessageTimeUsecs(const BOOL update = FALSE); // Get the current message system time in microseconds | ||
658 | static F64 getMessageTimeSeconds(const BOOL update = FALSE); // Get the current message system time in seconds | ||
659 | |||
660 | static void setTimeDecodes( BOOL b ) | ||
661 | { LLMessageSystem::mTimeDecodes = b; } | ||
662 | |||
663 | static void setTimeDecodesSpamThreshold( F32 seconds ) | ||
664 | { LLMessageSystem::mTimeDecodesSpamThreshold = seconds; } | ||
665 | |||
666 | // message handlers internal to the message systesm | ||
667 | //static void processAssignCircuitCode(LLMessageSystem* msg, void**); | ||
668 | static void processAddCircuitCode(LLMessageSystem* msg, void**); | ||
669 | static void processUseCircuitCode(LLMessageSystem* msg, void**); | ||
670 | |||
671 | void setMessageBans(const LLSD& trusted, const LLSD& untrusted); | ||
672 | |||
673 | private: | ||
674 | // data used in those internal handlers | ||
675 | |||
676 | // The mCircuitCodes is a map from circuit codes to session | ||
677 | // ids. This allows us to verify sessions on connect. | ||
678 | typedef std::map<U32, LLUUID> code_session_map_t; | ||
679 | code_session_map_t mCircuitCodes; | ||
680 | |||
681 | // Viewers need to track a process session in order to make sure | ||
682 | // that no one gives them a bad circuit code. | ||
683 | LLUUID mSessionID; | ||
684 | |||
685 | private: | ||
686 | void addTemplate(LLMessageTemplate *templatep); | ||
687 | void clearReceiveState(); | ||
688 | BOOL decodeTemplate( const U8* buffer, S32 buffer_size, LLMessageTemplate** msg_template ); | ||
689 | |||
690 | void logMsgFromInvalidCircuit( const LLHost& sender, BOOL recv_reliable ); | ||
691 | void logTrustedMsgFromUntrustedCircuit( const LLHost& sender ); | ||
692 | void logValidMsg(LLCircuitData *cdp, const LLHost& sender, BOOL recv_reliable, BOOL recv_resent, BOOL recv_acks ); | ||
693 | void logRanOffEndOfPacket( const LLHost& sender ); | ||
694 | |||
695 | private: | ||
696 | class LLMessageCountInfo | ||
697 | { | ||
698 | public: | ||
699 | U32 mMessageNum; | ||
700 | U32 mMessageBytes; | ||
701 | BOOL mInvalid; | ||
702 | }; | ||
703 | |||
704 | LLMessagePollInfo *mPollInfop; | ||
705 | |||
706 | U8 mEncodedRecvBuffer[MAX_BUFFER_SIZE]; | ||
707 | U8 mTrueReceiveBuffer[MAX_BUFFER_SIZE]; | ||
708 | S32 mTrueReceiveSize; | ||
709 | |||
710 | // Must be valid during decode | ||
711 | S32 mReceiveSize; | ||
712 | TPACKETID mCurrentRecvPacketID; // packet ID of current receive packet (for reporting) | ||
713 | LLMessageTemplate *mCurrentRMessageTemplate; | ||
714 | LLMsgData *mCurrentRMessageData; | ||
715 | S32 mIncomingCompressedSize; // original size of compressed msg (0 if uncomp.) | ||
716 | LLHost mLastSender; | ||
717 | |||
718 | // send message storage | ||
719 | LLMsgData *mCurrentSMessageData; | ||
720 | LLMessageTemplate *mCurrentSMessageTemplate; | ||
721 | LLMsgBlkData *mCurrentSDataBlock; | ||
722 | char *mCurrentSMessageName; | ||
723 | char *mCurrentSBlockName; | ||
724 | |||
725 | BOOL mbError; | ||
726 | S32 mErrorCode; | ||
727 | |||
728 | BOOL mbSBuilt; // is send message built? | ||
729 | BOOL mbSClear; // is the send message clear? | ||
730 | |||
731 | F64 mResendDumpTime; // The last time we dumped resends | ||
732 | |||
733 | LLMessageCountInfo mMessageCountList[MAX_MESSAGE_COUNT_NUM]; | ||
734 | S32 mNumMessageCounts; | ||
735 | F32 mReceiveTime; | ||
736 | F32 mMaxMessageTime; // Max number of seconds for processing messages | ||
737 | S32 mMaxMessageCounts; // Max number of messages to process before dumping. | ||
738 | F64 mMessageCountTime; | ||
739 | |||
740 | F64 mCurrentMessageTimeSeconds; // The current "message system time" (updated the first call to checkMessages after a resetReceiveCount | ||
741 | |||
742 | // message system exceptions | ||
743 | typedef std::pair<msg_exception_callback, void*> exception_t; | ||
744 | typedef std::map<EMessageException, exception_t> callbacks_t; | ||
745 | callbacks_t mExceptionCallbacks; | ||
746 | |||
747 | // stuff for logging | ||
748 | LLTimer mMessageSystemTimer; | ||
749 | |||
750 | static F32 mTimeDecodesSpamThreshold; // If mTimeDecodes is on, all this many seconds for each msg decode before spamming | ||
751 | static BOOL mTimeDecodes; // Measure time for all message decodes if TRUE; | ||
752 | |||
753 | void init(); // ctor shared initialisation. | ||
754 | }; | ||
755 | |||
756 | |||
757 | // external hook into messaging system | ||
758 | extern LLMessageSystem *gMessageSystem; | ||
759 | //extern const char* MESSAGE_LOG_FILENAME; | ||
760 | |||
761 | void encrypt_template(const char *src_name, const char *dest_name); | ||
762 | BOOL decrypt_template(const char *src_name, const char *dest_name); | ||
763 | |||
764 | // Must specific overall system version, which is used to determine | ||
765 | // if a patch is available in the message template checksum verification. | ||
766 | // Return TRUE if able to initialize system. | ||
767 | BOOL start_messaging_system( | ||
768 | const std::string& template_name, | ||
769 | U32 port, | ||
770 | S32 version_major, | ||
771 | S32 version_minor, | ||
772 | S32 version_patch, | ||
773 | BOOL b_dump_prehash_file, | ||
774 | const std::string& secret); | ||
775 | |||
776 | void end_messaging_system(); | ||
777 | |||
778 | void null_message_callback(LLMessageSystem *msg, void **data); | ||
779 | void process_log_control(LLMessageSystem* msg, void**); | ||
780 | |||
781 | // | ||
782 | // Inlines | ||
783 | // | ||
784 | |||
785 | static inline void *htonmemcpy(void *vs, const void *vct, EMsgVariableType type, size_t n) | ||
786 | { | ||
787 | char *s = (char *)vs; | ||
788 | const char *ct = (const char *)vct; | ||
789 | #ifdef LL_BIG_ENDIAN | ||
790 | S32 i, length; | ||
791 | #endif | ||
792 | switch(type) | ||
793 | { | ||
794 | case MVT_FIXED: | ||
795 | case MVT_VARIABLE: | ||
796 | case MVT_U8: | ||
797 | case MVT_S8: | ||
798 | case MVT_BOOL: | ||
799 | case MVT_LLUUID: | ||
800 | case MVT_IP_ADDR: // these two are swizzled in the getters and setters | ||
801 | case MVT_IP_PORT: // these two are swizzled in the getters and setters | ||
802 | return(memcpy(s,ct,n)); /* Flawfinder: ignore */ | ||
803 | |||
804 | case MVT_U16: | ||
805 | case MVT_S16: | ||
806 | if (n != 2) | ||
807 | { | ||
808 | llerrs << "Size argument passed to htonmemcpy doesn't match swizzle type size" << llendl; | ||
809 | } | ||
810 | #ifdef LL_BIG_ENDIAN | ||
811 | *(s + 1) = *(ct); | ||
812 | *(s) = *(ct + 1); | ||
813 | return(vs); | ||
814 | #else | ||
815 | return(memcpy(s,ct,n)); /* Flawfinder: ignore */ | ||
816 | #endif | ||
817 | |||
818 | case MVT_U32: | ||
819 | case MVT_S32: | ||
820 | case MVT_F32: | ||
821 | if (n != 4) | ||
822 | { | ||
823 | llerrs << "Size argument passed to htonmemcpy doesn't match swizzle type size" << llendl; | ||
824 | } | ||
825 | #ifdef LL_BIG_ENDIAN | ||
826 | *(s + 3) = *(ct); | ||
827 | *(s + 2) = *(ct + 1); | ||
828 | *(s + 1) = *(ct + 2); | ||
829 | *(s) = *(ct + 3); | ||
830 | return(vs); | ||
831 | #else | ||
832 | return(memcpy(s,ct,n)); /* Flawfinder: ignore */ | ||
833 | #endif | ||
834 | |||
835 | case MVT_U64: | ||
836 | case MVT_S64: | ||
837 | case MVT_F64: | ||
838 | if (n != 8) | ||
839 | { | ||
840 | llerrs << "Size argument passed to htonmemcpy doesn't match swizzle type size" << llendl; | ||
841 | } | ||
842 | #ifdef LL_BIG_ENDIAN | ||
843 | *(s + 7) = *(ct); | ||
844 | *(s + 6) = *(ct + 1); | ||
845 | *(s + 5) = *(ct + 2); | ||
846 | *(s + 4) = *(ct + 3); | ||
847 | *(s + 3) = *(ct + 4); | ||
848 | *(s + 2) = *(ct + 5); | ||
849 | *(s + 1) = *(ct + 6); | ||
850 | *(s) = *(ct + 7); | ||
851 | return(vs); | ||
852 | #else | ||
853 | return(memcpy(s,ct,n)); /* Flawfinder: ignore */ | ||
854 | #endif | ||
855 | |||
856 | case MVT_LLVector3: | ||
857 | case MVT_LLQuaternion: // We only send x, y, z and infer w (we set x, y, z to ensure that w >= 0) | ||
858 | if (n != 12) | ||
859 | { | ||
860 | llerrs << "Size argument passed to htonmemcpy doesn't match swizzle type size" << llendl; | ||
861 | } | ||
862 | #ifdef LL_BIG_ENDIAN | ||
863 | htonmemcpy(s + 8, ct + 8, MVT_F32, 4); | ||
864 | htonmemcpy(s + 4, ct + 4, MVT_F32, 4); | ||
865 | return(htonmemcpy(s, ct, MVT_F32, 4)); | ||
866 | #else | ||
867 | return(memcpy(s,ct,n)); /* Flawfinder: ignore */ | ||
868 | #endif | ||
869 | |||
870 | case MVT_LLVector3d: | ||
871 | if (n != 24) | ||
872 | { | ||
873 | llerrs << "Size argument passed to htonmemcpy doesn't match swizzle type size" << llendl; | ||
874 | } | ||
875 | #ifdef LL_BIG_ENDIAN | ||
876 | htonmemcpy(s + 16, ct + 16, MVT_F64, 8); | ||
877 | htonmemcpy(s + 8, ct + 8, MVT_F64, 8); | ||
878 | return(htonmemcpy(s, ct, MVT_F64, 8)); | ||
879 | #else | ||
880 | return(memcpy(s,ct,n)); /* Flawfinder: ignore */ | ||
881 | #endif | ||
882 | |||
883 | case MVT_LLVector4: | ||
884 | if (n != 16) | ||
885 | { | ||
886 | llerrs << "Size argument passed to htonmemcpy doesn't match swizzle type size" << llendl; | ||
887 | } | ||
888 | #ifdef LL_BIG_ENDIAN | ||
889 | htonmemcpy(s + 12, ct + 12, MVT_F32, 4); | ||
890 | htonmemcpy(s + 8, ct + 8, MVT_F32, 4); | ||
891 | htonmemcpy(s + 4, ct + 4, MVT_F32, 4); | ||
892 | return(htonmemcpy(s, ct, MVT_F32, 4)); | ||
893 | #else | ||
894 | return(memcpy(s,ct,n)); /* Flawfinder: ignore */ | ||
895 | #endif | ||
896 | |||
897 | case MVT_U16Vec3: | ||
898 | if (n != 6) | ||
899 | { | ||
900 | llerrs << "Size argument passed to htonmemcpy doesn't match swizzle type size" << llendl; | ||
901 | } | ||
902 | #ifdef LL_BIG_ENDIAN | ||
903 | htonmemcpy(s + 4, ct + 4, MVT_U16, 2); | ||
904 | htonmemcpy(s + 2, ct + 2, MVT_U16, 2); | ||
905 | return(htonmemcpy(s, ct, MVT_U16, 2)); | ||
906 | #else | ||
907 | return(memcpy(s,ct,n)); /* Flawfinder: ignore */ | ||
908 | #endif | ||
909 | |||
910 | case MVT_U16Quat: | ||
911 | if (n != 8) | ||
912 | { | ||
913 | llerrs << "Size argument passed to htonmemcpy doesn't match swizzle type size" << llendl; | ||
914 | } | ||
915 | #ifdef LL_BIG_ENDIAN | ||
916 | htonmemcpy(s + 6, ct + 6, MVT_U16, 2); | ||
917 | htonmemcpy(s + 4, ct + 4, MVT_U16, 2); | ||
918 | htonmemcpy(s + 2, ct + 2, MVT_U16, 2); | ||
919 | return(htonmemcpy(s, ct, MVT_U16, 2)); | ||
920 | #else | ||
921 | return(memcpy(s,ct,n)); /* Flawfinder: ignore */ | ||
922 | #endif | ||
923 | |||
924 | case MVT_S16Array: | ||
925 | if (n % 2) | ||
926 | { | ||
927 | llerrs << "Size argument passed to htonmemcpy doesn't match swizzle type size" << llendl; | ||
928 | } | ||
929 | #ifdef LL_BIG_ENDIAN | ||
930 | length = n % 2; | ||
931 | for (i = 1; i < length; i++) | ||
932 | { | ||
933 | htonmemcpy(s + i*2, ct + i*2, MVT_S16, 2); | ||
934 | } | ||
935 | return(htonmemcpy(s, ct, MVT_S16, 2)); | ||
936 | #else | ||
937 | return(memcpy(s,ct,n)); | ||
938 | #endif | ||
939 | |||
940 | default: | ||
941 | return(memcpy(s,ct,n)); /* Flawfinder: ignore */ | ||
942 | } | ||
943 | } | ||
944 | |||
945 | inline void *ntohmemcpy(void *s, const void *ct, EMsgVariableType type, size_t n) | ||
946 | { | ||
947 | return(htonmemcpy(s,ct,type, n)); | ||
948 | } | ||
949 | |||
950 | |||
951 | inline const LLHost& LLMessageSystem::getSender() const | ||
952 | { | ||
953 | return mLastSender; | ||
954 | } | ||
955 | |||
956 | inline U32 LLMessageSystem::getSenderIP() const | ||
957 | { | ||
958 | return mLastSender.getAddress(); | ||
959 | } | ||
960 | |||
961 | inline U32 LLMessageSystem::getSenderPort() const | ||
962 | { | ||
963 | return mLastSender.getPort(); | ||
964 | } | ||
965 | |||
966 | inline void LLMessageSystem::addS8Fast(const char *varname, S8 s) | ||
967 | { | ||
968 | addDataFast(varname, &s, MVT_S8, sizeof(s)); | ||
969 | } | ||
970 | |||
971 | inline void LLMessageSystem::addS8(const char *varname, S8 s) | ||
972 | { | ||
973 | addDataFast(gMessageStringTable.getString(varname), &s, MVT_S8, sizeof(s)); | ||
974 | } | ||
975 | |||
976 | inline void LLMessageSystem::addU8Fast(const char *varname, U8 u) | ||
977 | { | ||
978 | addDataFast(varname, &u, MVT_U8, sizeof(u)); | ||
979 | } | ||
980 | |||
981 | inline void LLMessageSystem::addU8(const char *varname, U8 u) | ||
982 | { | ||
983 | addDataFast(gMessageStringTable.getString(varname), &u, MVT_U8, sizeof(u)); | ||
984 | } | ||
985 | |||
986 | inline void LLMessageSystem::addS16Fast(const char *varname, S16 i) | ||
987 | { | ||
988 | addDataFast(varname, &i, MVT_S16, sizeof(i)); | ||
989 | } | ||
990 | |||
991 | inline void LLMessageSystem::addS16(const char *varname, S16 i) | ||
992 | { | ||
993 | addDataFast(gMessageStringTable.getString(varname), &i, MVT_S16, sizeof(i)); | ||
994 | } | ||
995 | |||
996 | inline void LLMessageSystem::addU16Fast(const char *varname, U16 i) | ||
997 | { | ||
998 | addDataFast(varname, &i, MVT_U16, sizeof(i)); | ||
999 | } | ||
1000 | |||
1001 | inline void LLMessageSystem::addU16(const char *varname, U16 i) | ||
1002 | { | ||
1003 | addDataFast(gMessageStringTable.getString(varname), &i, MVT_U16, sizeof(i)); | ||
1004 | } | ||
1005 | |||
1006 | inline void LLMessageSystem::addF32Fast(const char *varname, F32 f) | ||
1007 | { | ||
1008 | addDataFast(varname, &f, MVT_F32, sizeof(f)); | ||
1009 | } | ||
1010 | |||
1011 | inline void LLMessageSystem::addF32(const char *varname, F32 f) | ||
1012 | { | ||
1013 | addDataFast(gMessageStringTable.getString(varname), &f, MVT_F32, sizeof(f)); | ||
1014 | } | ||
1015 | |||
1016 | inline void LLMessageSystem::addS32Fast(const char *varname, S32 s) | ||
1017 | { | ||
1018 | addDataFast(varname, &s, MVT_S32, sizeof(s)); | ||
1019 | } | ||
1020 | |||
1021 | inline void LLMessageSystem::addS32(const char *varname, S32 s) | ||
1022 | { | ||
1023 | addDataFast(gMessageStringTable.getString(varname), &s, MVT_S32, sizeof(s)); | ||
1024 | } | ||
1025 | |||
1026 | inline void LLMessageSystem::addU32Fast(const char *varname, U32 u) | ||
1027 | { | ||
1028 | addDataFast(varname, &u, MVT_U32, sizeof(u)); | ||
1029 | } | ||
1030 | |||
1031 | inline void LLMessageSystem::addU32(const char *varname, U32 u) | ||
1032 | { | ||
1033 | addDataFast(gMessageStringTable.getString(varname), &u, MVT_U32, sizeof(u)); | ||
1034 | } | ||
1035 | |||
1036 | inline void LLMessageSystem::addU64Fast(const char *varname, U64 lu) | ||
1037 | { | ||
1038 | addDataFast(varname, &lu, MVT_U64, sizeof(lu)); | ||
1039 | } | ||
1040 | |||
1041 | inline void LLMessageSystem::addU64(const char *varname, U64 lu) | ||
1042 | { | ||
1043 | addDataFast(gMessageStringTable.getString(varname), &lu, MVT_U64, sizeof(lu)); | ||
1044 | } | ||
1045 | |||
1046 | inline void LLMessageSystem::addF64Fast(const char *varname, F64 d) | ||
1047 | { | ||
1048 | addDataFast(varname, &d, MVT_F64, sizeof(d)); | ||
1049 | } | ||
1050 | |||
1051 | inline void LLMessageSystem::addF64(const char *varname, F64 d) | ||
1052 | { | ||
1053 | addDataFast(gMessageStringTable.getString(varname), &d, MVT_F64, sizeof(d)); | ||
1054 | } | ||
1055 | |||
1056 | inline void LLMessageSystem::addIPAddrFast(const char *varname, U32 u) | ||
1057 | { | ||
1058 | addDataFast(varname, &u, MVT_IP_ADDR, sizeof(u)); | ||
1059 | } | ||
1060 | |||
1061 | inline void LLMessageSystem::addIPAddr(const char *varname, U32 u) | ||
1062 | { | ||
1063 | addDataFast(gMessageStringTable.getString(varname), &u, MVT_IP_ADDR, sizeof(u)); | ||
1064 | } | ||
1065 | |||
1066 | inline void LLMessageSystem::addIPPortFast(const char *varname, U16 u) | ||
1067 | { | ||
1068 | u = htons(u); | ||
1069 | addDataFast(varname, &u, MVT_IP_PORT, sizeof(u)); | ||
1070 | } | ||
1071 | |||
1072 | inline void LLMessageSystem::addIPPort(const char *varname, U16 u) | ||
1073 | { | ||
1074 | u = htons(u); | ||
1075 | addDataFast(gMessageStringTable.getString(varname), &u, MVT_IP_PORT, sizeof(u)); | ||
1076 | } | ||
1077 | |||
1078 | inline void LLMessageSystem::addBOOLFast(const char* varname, BOOL b) | ||
1079 | { | ||
1080 | // Can't just cast a BOOL (actually a U32) to a U8. | ||
1081 | // In some cases the low order bits will be zero. | ||
1082 | U8 temp = (b != 0); | ||
1083 | addDataFast(varname, &temp, MVT_BOOL, sizeof(temp)); | ||
1084 | } | ||
1085 | |||
1086 | inline void LLMessageSystem::addBOOL(const char* varname, BOOL b) | ||
1087 | { | ||
1088 | // Can't just cast a BOOL (actually a U32) to a U8. | ||
1089 | // In some cases the low order bits will be zero. | ||
1090 | U8 temp = (b != 0); | ||
1091 | addDataFast(gMessageStringTable.getString(varname), &temp, MVT_BOOL, sizeof(temp)); | ||
1092 | } | ||
1093 | |||
1094 | inline void LLMessageSystem::addStringFast(const char* varname, const char* s) | ||
1095 | { | ||
1096 | if (s) | ||
1097 | addDataFast( varname, (void *)s, MVT_VARIABLE, (S32)strlen(s) + 1); /* Flawfinder: ignore */ | ||
1098 | else | ||
1099 | addDataFast( varname, NULL, MVT_VARIABLE, 0); | ||
1100 | } | ||
1101 | |||
1102 | inline void LLMessageSystem::addString(const char* varname, const char* s) | ||
1103 | { | ||
1104 | if (s) | ||
1105 | addDataFast( gMessageStringTable.getString(varname), (void *)s, MVT_VARIABLE, (S32)strlen(s) + 1); /* Flawfinder: ignore */ | ||
1106 | else | ||
1107 | addDataFast( gMessageStringTable.getString(varname), NULL, MVT_VARIABLE, 0); | ||
1108 | } | ||
1109 | |||
1110 | inline void LLMessageSystem::addStringFast(const char* varname, const std::string& s) | ||
1111 | { | ||
1112 | if (s.size()) | ||
1113 | addDataFast( varname, (void *)s.c_str(), MVT_VARIABLE, (S32)(s.size()) + 1); | ||
1114 | else | ||
1115 | addDataFast( varname, NULL, MVT_VARIABLE, 0); | ||
1116 | } | ||
1117 | |||
1118 | inline void LLMessageSystem::addString(const char* varname, const std::string& s) | ||
1119 | { | ||
1120 | if (s.size()) | ||
1121 | addDataFast( gMessageStringTable.getString(varname), (void *)s.c_str(), MVT_VARIABLE, (S32)(s.size()) + 1); | ||
1122 | else | ||
1123 | addDataFast( gMessageStringTable.getString(varname), NULL, MVT_VARIABLE, 0); | ||
1124 | } | ||
1125 | |||
1126 | |||
1127 | //----------------------------------------------------------------------------- | ||
1128 | // Retrieval aliases | ||
1129 | //----------------------------------------------------------------------------- | ||
1130 | inline void LLMessageSystem::getS8Fast(const char *block, const char *var, S8 &u, S32 blocknum) | ||
1131 | { | ||
1132 | getDataFast(block, var, &u, sizeof(S8), blocknum); | ||
1133 | } | ||
1134 | |||
1135 | inline void LLMessageSystem::getS8(const char *block, const char *var, S8 &u, S32 blocknum) | ||
1136 | { | ||
1137 | getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &u, sizeof(S8), blocknum); | ||
1138 | } | ||
1139 | |||
1140 | inline void LLMessageSystem::getU8Fast(const char *block, const char *var, U8 &u, S32 blocknum) | ||
1141 | { | ||
1142 | getDataFast(block, var, &u, sizeof(U8), blocknum); | ||
1143 | } | ||
1144 | |||
1145 | inline void LLMessageSystem::getU8(const char *block, const char *var, U8 &u, S32 blocknum) | ||
1146 | { | ||
1147 | getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &u, sizeof(U8), blocknum); | ||
1148 | } | ||
1149 | |||
1150 | inline void LLMessageSystem::getBOOLFast(const char *block, const char *var, BOOL &b, S32 blocknum ) | ||
1151 | { | ||
1152 | U8 value; | ||
1153 | getDataFast(block, var, &value, sizeof(U8), blocknum); | ||
1154 | b = (BOOL) value; | ||
1155 | } | ||
1156 | |||
1157 | inline void LLMessageSystem::getBOOL(const char *block, const char *var, BOOL &b, S32 blocknum ) | ||
1158 | { | ||
1159 | U8 value; | ||
1160 | getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &value, sizeof(U8), blocknum); | ||
1161 | b = (BOOL) value; | ||
1162 | } | ||
1163 | |||
1164 | inline void LLMessageSystem::getS16Fast(const char *block, const char *var, S16 &d, S32 blocknum) | ||
1165 | { | ||
1166 | getDataFast(block, var, &d, sizeof(S16), blocknum); | ||
1167 | } | ||
1168 | |||
1169 | inline void LLMessageSystem::getS16(const char *block, const char *var, S16 &d, S32 blocknum) | ||
1170 | { | ||
1171 | getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &d, sizeof(S16), blocknum); | ||
1172 | } | ||
1173 | |||
1174 | inline void LLMessageSystem::getU16Fast(const char *block, const char *var, U16 &d, S32 blocknum) | ||
1175 | { | ||
1176 | getDataFast(block, var, &d, sizeof(U16), blocknum); | ||
1177 | } | ||
1178 | |||
1179 | inline void LLMessageSystem::getU16(const char *block, const char *var, U16 &d, S32 blocknum) | ||
1180 | { | ||
1181 | getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &d, sizeof(U16), blocknum); | ||
1182 | } | ||
1183 | |||
1184 | inline void LLMessageSystem::getS32Fast(const char *block, const char *var, S32 &d, S32 blocknum) | ||
1185 | { | ||
1186 | getDataFast(block, var, &d, sizeof(S32), blocknum); | ||
1187 | } | ||
1188 | |||
1189 | inline void LLMessageSystem::getS32(const char *block, const char *var, S32 &d, S32 blocknum) | ||
1190 | { | ||
1191 | getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &d, sizeof(S32), blocknum); | ||
1192 | } | ||
1193 | |||
1194 | inline void LLMessageSystem::getU32Fast(const char *block, const char *var, U32 &d, S32 blocknum) | ||
1195 | { | ||
1196 | getDataFast(block, var, &d, sizeof(U32), blocknum); | ||
1197 | } | ||
1198 | |||
1199 | inline void LLMessageSystem::getU32(const char *block, const char *var, U32 &d, S32 blocknum) | ||
1200 | { | ||
1201 | getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &d, sizeof(U32), blocknum); | ||
1202 | } | ||
1203 | |||
1204 | inline void LLMessageSystem::getU64Fast(const char *block, const char *var, U64 &d, S32 blocknum) | ||
1205 | { | ||
1206 | getDataFast(block, var, &d, sizeof(U64), blocknum); | ||
1207 | } | ||
1208 | |||
1209 | inline void LLMessageSystem::getU64(const char *block, const char *var, U64 &d, S32 blocknum) | ||
1210 | { | ||
1211 | getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &d, sizeof(U64), blocknum); | ||
1212 | } | ||
1213 | |||
1214 | |||
1215 | inline void LLMessageSystem::getIPAddrFast(const char *block, const char *var, U32 &u, S32 blocknum) | ||
1216 | { | ||
1217 | getDataFast(block, var, &u, sizeof(U32), blocknum); | ||
1218 | } | ||
1219 | |||
1220 | inline void LLMessageSystem::getIPAddr(const char *block, const char *var, U32 &u, S32 blocknum) | ||
1221 | { | ||
1222 | getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &u, sizeof(U32), blocknum); | ||
1223 | } | ||
1224 | |||
1225 | inline void LLMessageSystem::getIPPortFast(const char *block, const char *var, U16 &u, S32 blocknum) | ||
1226 | { | ||
1227 | getDataFast(block, var, &u, sizeof(U16), blocknum); | ||
1228 | u = ntohs(u); | ||
1229 | } | ||
1230 | |||
1231 | inline void LLMessageSystem::getIPPort(const char *block, const char *var, U16 &u, S32 blocknum) | ||
1232 | { | ||
1233 | getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), &u, sizeof(U16), blocknum); | ||
1234 | u = ntohs(u); | ||
1235 | } | ||
1236 | |||
1237 | |||
1238 | inline void LLMessageSystem::getStringFast(const char *block, const char *var, S32 buffer_size, char *s, S32 blocknum ) | ||
1239 | { | ||
1240 | s[0] = '\0'; | ||
1241 | getDataFast(block, var, s, 0, blocknum, buffer_size); | ||
1242 | s[buffer_size - 1] = '\0'; | ||
1243 | } | ||
1244 | |||
1245 | inline void LLMessageSystem::getString(const char *block, const char *var, S32 buffer_size, char *s, S32 blocknum ) | ||
1246 | { | ||
1247 | s[0] = '\0'; | ||
1248 | getDataFast(gMessageStringTable.getString(block), gMessageStringTable.getString(var), s, 0, blocknum, buffer_size); | ||
1249 | s[buffer_size - 1] = '\0'; | ||
1250 | } | ||
1251 | |||
1252 | //----------------------------------------------------------------------------- | ||
1253 | // Transmission aliases | ||
1254 | //----------------------------------------------------------------------------- | ||
1255 | //inline S32 LLMessageSystem::sendMessage(U32 ip, U32 port, BOOL zero_code) | ||
1256 | //{ | ||
1257 | // return sendMessage(LLHost(ip, port), zero_code); | ||
1258 | //} | ||
1259 | |||
1260 | //inline S32 LLMessageSystem::sendMessage(const char *ip_str, U32 port, BOOL zero_code) | ||
1261 | //{ | ||
1262 | // return sendMessage(LLHost(ip_str, port), zero_code); | ||
1263 | //} | ||
1264 | |||
1265 | inline S32 LLMessageSystem::sendMessage(const U32 circuit)//, BOOL zero_code) | ||
1266 | { | ||
1267 | return sendMessage(findHost(circuit));//, zero_code); | ||
1268 | } | ||
1269 | |||
1270 | #endif | ||