summaryrefslogtreecommitdiff
path: root/indra/llmessage/message.cpp
diff options
context:
space:
mode:
authorAnsariel <ansariel.hiller@phoenixviewer.com>2024-05-22 21:25:21 +0200
committerAndrey Lihatskiy <alihatskiy@productengine.com>2024-05-22 22:40:26 +0300
commite2e37cced861b98de8c1a7c9c0d3a50d2d90e433 (patch)
tree1bb897489ce524986f6196201c10ac0d8861aa5f /indra/llmessage/message.cpp
parent069ea06848f766466f1a281144c82a0f2bd79f3a (diff)
Fix line endlings
Diffstat (limited to 'indra/llmessage/message.cpp')
-rw-r--r--indra/llmessage/message.cpp8110
1 files changed, 4055 insertions, 4055 deletions
diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp
index b57f8f4513..e705c36ff8 100644
--- a/indra/llmessage/message.cpp
+++ b/indra/llmessage/message.cpp
@@ -1,4055 +1,4055 @@
-/**
- * @file message.cpp
- * @brief LLMessageSystem class implementation
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "message.h"
-
-// system library includes
-#if !LL_WINDOWS
-// following header files required for inet_addr()
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#endif
-#include <iomanip>
-#include <iterator>
-#include <sstream>
-
-#include "llapr.h"
-#include "apr_portable.h"
-#include "apr_network_io.h"
-#include "apr_poll.h"
-
-// linden library headers
-#include "llapp.h"
-#include "indra_constants.h"
-#include "lldir.h"
-#include "llerror.h"
-#include "llfasttimer.h"
-#include "llhttpnodeadapter.h"
-#include "llmd5.h"
-#include "llmessagebuilder.h"
-#include "llmessageconfig.h"
-#include "lltemplatemessagedispatcher.h"
-#include "llpumpio.h"
-#include "lltemplatemessagebuilder.h"
-#include "lltemplatemessagereader.h"
-#include "lltrustedmessageservice.h"
-#include "llmessagetemplate.h"
-#include "llmessagetemplateparser.h"
-#include "llsd.h"
-#include "llsdmessagebuilder.h"
-#include "llsdmessagereader.h"
-#include "llsdserialize.h"
-#include "llstring.h"
-#include "lltransfermanager.h"
-#include "lluuid.h"
-#include "llxfermanager.h"
-#include "llquaternion.h"
-#include "u64.h"
-#include "v3dmath.h"
-#include "v3math.h"
-#include "v4math.h"
-#include "lltransfertargetvfile.h"
-#include "llcorehttputil.h"
-#include "llpounceable.h"
-
-// Constants
-//const char* MESSAGE_LOG_FILENAME = "message.log";
-static const F32Seconds CIRCUIT_DUMP_TIMEOUT(30.f);
-static const S32 TRUST_TIME_WINDOW = 3;
-
-// *NOTE: This needs to be moved into a seperate file so that it never gets
-// included in the viewer. 30 Sep 2002 mark
-// *NOTE: I don't think it's important that the messgage system tracks
-// this since it must get set externally. 2004.08.25 Phoenix.
-static std::string g_shared_secret;
-std::string get_shared_secret();
-
-class LLMessagePollInfo
-{
-public:
- apr_socket_t *mAPRSocketp;
- apr_pollfd_t mPollFD;
-};
-
-class LLMessageHandlerBridge : public LLHTTPNode
-{
- virtual bool validate(const std::string& name, LLSD& context) const
- { return true; }
-
- virtual void post(LLHTTPNode::ResponsePtr response, const LLSD& context,
- const LLSD& input) const;
-};
-
-//virtual
-void LLMessageHandlerBridge::post(LLHTTPNode::ResponsePtr response,
- const LLSD& context, const LLSD& input) const
-{
- std::string name = context[CONTEXT_REQUEST][CONTEXT_WILDCARD]["message-name"];
- char* namePtr = LLMessageStringTable::getInstance()->getString(name.c_str());
-
- LL_DEBUGS() << "Setting mLastSender " << input["sender"].asString() << LL_ENDL;
- gMessageSystem->mLastSender = LLHost(input["sender"].asString());
- gMessageSystem->mPacketsIn += 1;
- gMessageSystem->mLLSDMessageReader->setMessage(namePtr, input["body"]);
- LockMessageReader rdr(gMessageSystem->mMessageReader, gMessageSystem->mLLSDMessageReader);
-
- if(gMessageSystem->callHandler(namePtr, false, gMessageSystem))
- {
- response->result(LLSD());
- }
- else
- {
- response->notFound();
- }
-}
-
-LLHTTPRegistration<LLMessageHandlerBridge>
- gHTTPRegistrationMessageWildcard("/message/<message-name>");
-
-//virtual
-LLUseCircuitCodeResponder::~LLUseCircuitCodeResponder()
-{
- // even abstract base classes need a concrete destructor
-}
-
-static const char* nullToEmpty(const char* s)
-{
- static char emptyString[] = "";
- return s? s : emptyString;
-}
-
-void LLMessageSystem::init()
-{
- // initialize member variables
- mVerboseLog = false;
-
- mbError = false;
- mErrorCode = 0;
- mSendReliable = false;
-
- mUnackedListDepth = 0;
- mUnackedListSize = 0;
- mDSMaxListDepth = 0;
-
- mNumberHighFreqMessages = 0;
- mNumberMediumFreqMessages = 0;
- mNumberLowFreqMessages = 0;
- mPacketsIn = mPacketsOut = 0;
- mBytesIn = mBytesOut = 0;
- mCompressedPacketsIn = mCompressedPacketsOut = 0;
- mReliablePacketsIn = mReliablePacketsOut = 0;
-
- mCompressedBytesIn = 0;
- mCompressedBytesOut = 0;
- mUncompressedBytesIn = 0;
- mUncompressedBytesOut = 0;
- mTotalBytesIn = 0;
- mTotalBytesOut = 0;
-
- mDroppedPackets = 0; // total dropped packets in
- mResentPackets = 0; // total resent packets out
- mFailedResendPackets = 0; // total resend failure packets out
- mOffCircuitPackets = 0; // total # of off-circuit packets rejected
- mInvalidOnCircuitPackets = 0; // total # of on-circuit packets rejected
-
- mOurCircuitCode = 0;
-
- mIncomingCompressedSize = 0;
- mCurrentRecvPacketID = 0;
-
- mMessageFileVersionNumber = 0.f;
-
- mTimingCallback = NULL;
- mTimingCallbackData = NULL;
-
- mMessageBuilder = NULL;
- LockMessageReader(mMessageReader, NULL);
-}
-
-// Read file and build message templates
-LLMessageSystem::LLMessageSystem(const std::string& filename, U32 port,
- S32 version_major,
- S32 version_minor,
- S32 version_patch,
- bool failure_is_fatal,
- const F32 circuit_heartbeat_interval, const F32 circuit_timeout) :
- mCircuitInfo(F32Seconds(circuit_heartbeat_interval), F32Seconds(circuit_timeout)),
- mLastMessageFromTrustedMessageService(false)
-{
- init();
-
- mSendSize = 0;
-
- mSystemVersionMajor = version_major;
- mSystemVersionMinor = version_minor;
- mSystemVersionPatch = version_patch;
- mSystemVersionServer = 0;
- mVersionFlags = 0x0;
-
- // default to not accepting packets from not alive circuits
- mbProtected = true;
-
- // default to blocking trusted connections on a public interface if one is specified
- mBlockUntrustedInterface = true;
-
- mSendPacketFailureCount = 0;
-
- mCircuitPrintFreq = F32Seconds(60.f);
-
- loadTemplateFile(filename, failure_is_fatal);
-
- mTemplateMessageBuilder = new LLTemplateMessageBuilder(mMessageTemplates);
- mLLSDMessageBuilder = new LLSDMessageBuilder();
- mMessageBuilder = NULL;
-
- mTemplateMessageReader = new LLTemplateMessageReader(mMessageNumbers);
- mLLSDMessageReader = new LLSDMessageReader();
-
- // initialize various bits of net info
- mSocket = 0;
- mPort = port;
-
- S32 error = start_net(mSocket, mPort);
- if (error != 0)
- {
- mbError = true;
- mErrorCode = error;
- }
-// LL_DEBUGS("Messaging") << << "*** port: " << mPort << LL_ENDL;
-
- //
- // Create the data structure that we can poll on
- //
- if (!gAPRPoolp)
- {
- LL_ERRS("Messaging") << "No APR pool before message system initialization!" << LL_ENDL;
- ll_init_apr();
- }
- apr_socket_t *aprSocketp = NULL;
- apr_os_sock_put(&aprSocketp, (apr_os_sock_t*)&mSocket, gAPRPoolp);
-
- mPollInfop = new LLMessagePollInfo;
- mPollInfop->mAPRSocketp = aprSocketp;
- mPollInfop->mPollFD.p = gAPRPoolp;
- mPollInfop->mPollFD.desc_type = APR_POLL_SOCKET;
- mPollInfop->mPollFD.reqevents = APR_POLLIN;
- mPollInfop->mPollFD.rtnevents = 0;
- mPollInfop->mPollFD.desc.s = aprSocketp;
- mPollInfop->mPollFD.client_data = NULL;
-
- F64Seconds mt_sec = getMessageTimeSeconds();
- mResendDumpTime = mt_sec;
- mMessageCountTime = mt_sec;
- mCircuitPrintTime = mt_sec;
- mCurrentMessageTime = F64Seconds(mt_sec);
-
- // Constants for dumping output based on message processing time/count
- mNumMessageCounts = 0;
- mMaxMessageCounts = 200; // >= 0 means dump warnings
- mMaxMessageTime = F32Seconds(1.f);
-
- mTrueReceiveSize = 0;
-
- mReceiveTime = F32Seconds(0.f);
-}
-
-
-
-// Read file and build message templates
-void LLMessageSystem::loadTemplateFile(const std::string& filename, bool failure_is_fatal)
-{
- if(filename.empty())
- {
- LL_ERRS("Messaging") << "No template filename specified" << LL_ENDL;
- mbError = true;
- return;
- }
-
- std::string template_body;
- if(!_read_file_into_string(template_body, filename))
- {
- if (failure_is_fatal) {
- LL_ERRS("Messaging") << "Failed to open template: " << filename << LL_ENDL;
- } else {
- LL_WARNS("Messaging") << "Failed to open template: " << filename << LL_ENDL;
- }
- mbError = true;
- return;
- }
-
- LLTemplateTokenizer tokens(template_body);
- LLTemplateParser parsed(tokens);
- mMessageFileVersionNumber = parsed.getVersion();
- S32 count = 0;
- for(LLTemplateParser::message_iterator iter = parsed.getMessagesBegin();
- iter != parsed.getMessagesEnd();
- iter++)
- {
- addTemplate(*iter);
- count++;
- }
- LL_INFOS("Messaging") << "Read " << count << " messages from " << filename << LL_ENDL;
-}
-
-
-LLMessageSystem::~LLMessageSystem()
-{
- mMessageTemplates.clear(); // don't delete templates.
- for_each(mMessageNumbers.begin(), mMessageNumbers.end(), DeletePairedPointer());
- mMessageNumbers.clear();
-
- if (!mbError)
- {
- end_net(mSocket);
- }
- mSocket = 0;
-
- delete mTemplateMessageReader;
- mTemplateMessageReader = NULL;
-
- delete mTemplateMessageBuilder;
- mTemplateMessageBuilder = NULL;
- mMessageBuilder = NULL;
-
- delete mLLSDMessageReader;
- mLLSDMessageReader = NULL;
-
- delete mLLSDMessageBuilder;
- mLLSDMessageBuilder = NULL;
-
- delete mPollInfop;
- mPollInfop = NULL;
-
- mIncomingCompressedSize = 0;
- mCurrentRecvPacketID = 0;
-}
-
-void LLMessageSystem::clearReceiveState()
-{
- mCurrentRecvPacketID = 0;
- mIncomingCompressedSize = 0;
- mLastSender.invalidate();
- mLastReceivingIF.invalidate();
- mMessageReader->clearMessage();
- mLastMessageFromTrustedMessageService = false;
-}
-
-
-bool LLMessageSystem::poll(F32 seconds)
-{
- S32 num_socks;
- apr_status_t status;
- status = apr_poll(&(mPollInfop->mPollFD), 1, &num_socks,(U64)(seconds*1000000.f));
- if (status != APR_TIMEUP)
- {
- ll_apr_warn_status(status);
- }
- if (num_socks)
- {
- return true;
- }
- else
- {
- return false;
- }
-}
-
-bool LLMessageSystem::isTrustedSender(const LLHost& host) const
-{
- LLCircuitData* cdp = mCircuitInfo.findCircuit(host);
- if(NULL == cdp)
- {
- return false;
- }
- return cdp->getTrusted();
-}
-
-void LLMessageSystem::receivedMessageFromTrustedSender()
-{
- mLastMessageFromTrustedMessageService = true;
-}
-
-bool LLMessageSystem::isTrustedSender() const
-{
- return mLastMessageFromTrustedMessageService ||
- isTrustedSender(getSender());
-}
-
-static LLMessageSystem::message_template_name_map_t::const_iterator
-findTemplate(const LLMessageSystem::message_template_name_map_t& templates,
- std::string name)
-{
- const char* namePrehash = LLMessageStringTable::getInstance()->getString(name.c_str());
- if(NULL == namePrehash) {return templates.end();}
- return templates.find(namePrehash);
-}
-
-bool LLMessageSystem::isTrustedMessage(const std::string& name) const
-{
- message_template_name_map_t::const_iterator iter =
- findTemplate(mMessageTemplates, name);
- if(iter == mMessageTemplates.end()) {return false;}
- return iter->second->getTrust() == MT_TRUST;
-}
-
-bool LLMessageSystem::isUntrustedMessage(const std::string& name) const
-{
- message_template_name_map_t::const_iterator iter =
- findTemplate(mMessageTemplates, name);
- if(iter == mMessageTemplates.end()) {return false;}
- return iter->second->getTrust() == MT_NOTRUST;
-}
-
-LLCircuitData* LLMessageSystem::findCircuit(const LLHost& host,
- bool resetPacketId)
-{
- LLCircuitData* cdp = mCircuitInfo.findCircuit(host);
- if (!cdp)
- {
- // This packet comes from a circuit we don't know about.
-
- // Are we rejecting off-circuit packets?
- if (mbProtected)
- {
- // cdp is already NULL, so we don't need to unset it.
- }
- else
- {
- // nope, open the new circuit
- cdp = mCircuitInfo.addCircuitData(host, mCurrentRecvPacketID);
-
- if(resetPacketId)
- {
- // I added this - I think it's correct - DJS
- // reset packet in ID
- cdp->setPacketInID(mCurrentRecvPacketID);
- }
- // And claim the packet is on the circuit we just added.
- }
- }
- else
- {
- // this is an old circuit. . . is it still alive?
- if (!cdp->isAlive())
- {
- // nope. don't accept if we're protected
- if (mbProtected)
- {
- // don't accept packets from unexpected sources
- cdp = NULL;
- }
- else
- {
- // wake up the circuit
- cdp->setAlive(true);
-
- if(resetPacketId)
- {
- // reset packet in ID
- cdp->setPacketInID(mCurrentRecvPacketID);
- }
- }
- }
- }
- return cdp;
-}
-
-// Returns true if a valid, on-circuit message has been received.
-// Requiring a non-const LockMessageChecker reference ensures that
-// mMessageReader has been set to mTemplateMessageReader.
-bool LLMessageSystem::checkMessages(LockMessageChecker&, S64 frame_count )
-{
- // Pump
- bool valid_packet = false;
-
- LLTransferTargetVFile::updateQueue();
-
- if (!mNumMessageCounts)
- {
- // This is the first message being handled after a resetReceiveCounts,
- // we must be starting the message processing loop. Reset the timers.
- mCurrentMessageTime = totalTime();
- mMessageCountTime = getMessageTimeSeconds();
- }
-
- // loop until either no packets or a valid packet
- // i.e., burn through packets from unregistered circuits
- S32 receive_size = 0;
- do
- {
- clearReceiveState();
-
- bool recv_reliable = false;
- bool recv_resent = false;
- S32 acks = 0;
- S32 true_rcv_size = 0;
-
- U8* buffer = mTrueReceiveBuffer;
-
- mTrueReceiveSize = mPacketRing.receivePacket(mSocket, (char *)mTrueReceiveBuffer);
- // If you want to dump all received packets into SecondLife.log, uncomment this
- //dumpPacketToLog();
-
- receive_size = mTrueReceiveSize;
- mLastSender = mPacketRing.getLastSender();
- mLastReceivingIF = mPacketRing.getLastReceivingInterface();
-
- if (receive_size < (S32) LL_MINIMUM_VALID_PACKET_SIZE)
- {
- // A receive size of zero is OK, that means that there are no more packets available.
- // Ones that are non-zero but below the minimum packet size are worrisome.
- if (receive_size > 0)
- {
- LL_WARNS("Messaging") << "Invalid (too short) packet discarded " << receive_size << LL_ENDL;
- callExceptionFunc(MX_PACKET_TOO_SHORT);
- }
- // no data in packet receive buffer
- valid_packet = false;
- }
- else
- {
- LLHost host;
- LLCircuitData* cdp;
-
- // note if packet acks are appended.
- if(buffer[0] & LL_ACK_FLAG)
- {
- acks += buffer[--receive_size];
- true_rcv_size = receive_size;
- if(receive_size >= ((S32)(acks * sizeof(TPACKETID) + LL_MINIMUM_VALID_PACKET_SIZE)))
- {
- receive_size -= acks * sizeof(TPACKETID);
- }
- else
- {
- // mal-formed packet. ignore it and continue with
- // the next one
- LL_WARNS("Messaging") << "Malformed packet received. Packet size "
- << receive_size << " with invalid no. of acks " << acks
- << LL_ENDL;
- valid_packet = false;
- continue;
- }
- }
-
- // process the message as normal
- mIncomingCompressedSize = zeroCodeExpand(&buffer, &receive_size);
- mCurrentRecvPacketID = ntohl(*((U32*)(&buffer[1])));
- host = getSender();
-
- const bool resetPacketId = true;
- cdp = findCircuit(host, resetPacketId);
-
- // At this point, cdp is now a pointer to the circuit that
- // this message came in on if it's valid, and NULL if the
- // circuit was bogus.
-
- if(cdp && (acks > 0) && ((S32)(acks * sizeof(TPACKETID)) < (true_rcv_size)))
- {
- TPACKETID packet_id;
- U32 mem_id=0;
- for(S32 i = 0; i < acks; ++i)
- {
- true_rcv_size -= sizeof(TPACKETID);
- memcpy(&mem_id, &mTrueReceiveBuffer[true_rcv_size], /* Flawfinder: ignore*/
- sizeof(TPACKETID));
- packet_id = ntohl(mem_id);
- //LL_INFOS("Messaging") << "got ack: " << packet_id << LL_ENDL;
- cdp->ackReliablePacket(packet_id);
- }
- if (!cdp->getUnackedPacketCount())
- {
- // Remove this circuit from the list of circuits with unacked packets
- mCircuitInfo.mUnackedCircuitMap.erase(cdp->mHost);
- }
- }
-
- if (buffer[0] & LL_RELIABLE_FLAG)
- {
- recv_reliable = true;
- }
- if (buffer[0] & LL_RESENT_FLAG)
- {
- recv_resent = true;
- if (cdp && cdp->isDuplicateResend(mCurrentRecvPacketID))
- {
- // We need to ACK here to suppress
- // further resends of packets we've
- // already seen.
- if (recv_reliable)
- {
- //mAckList.addData(new LLPacketAck(host, mCurrentRecvPacketID));
- // ***************************************
- // TESTING CODE
- //if(mCircuitInfo.mCurrentCircuit->mHost != host)
- //{
- // LL_WARNS("Messaging") << "DISCARDED PACKET HOST MISMATCH! HOST: "
- // << host << " CIRCUIT: "
- // << mCircuitInfo.mCurrentCircuit->mHost
- // << LL_ENDL;
- //}
- // ***************************************
- //mCircuitInfo.mCurrentCircuit->mAcks.put(mCurrentRecvPacketID);
- cdp->collectRAck(mCurrentRecvPacketID);
- }
-
- LL_DEBUGS("Messaging") << "Discarding duplicate resend from " << host << LL_ENDL;
- if(mVerboseLog)
- {
- std::ostringstream str;
- str << "MSG: <- " << host;
- std::string tbuf;
- tbuf = llformat( "\t%6d\t%6d\t%6d ", receive_size, (mIncomingCompressedSize ? mIncomingCompressedSize : receive_size), mCurrentRecvPacketID);
- str << tbuf << "(unknown)"
- << (recv_reliable ? " reliable" : "")
- << " resent "
- << ((acks > 0) ? "acks" : "")
- << " DISCARD DUPLICATE";
- LL_INFOS("Messaging") << str.str() << LL_ENDL;
- }
- mPacketsIn++;
- valid_packet = false;
- continue;
- }
- }
-
- // UseCircuitCode can be a valid, off-circuit packet.
- // But we don't want to acknowledge UseCircuitCode until the circuit is
- // available, which is why the acknowledgement test is done above. JC
- bool trusted = cdp && cdp->getTrusted();
- valid_packet = mTemplateMessageReader->validateMessage(
- buffer,
- receive_size,
- host,
- trusted);
- if (!valid_packet)
- {
- clearReceiveState();
- }
-
- // UseCircuitCode is allowed in even from an invalid circuit, so that
- // we can toss circuits around.
- if(
- valid_packet &&
- !cdp &&
- (mTemplateMessageReader->getMessageName() !=
- _PREHASH_UseCircuitCode))
- {
- logMsgFromInvalidCircuit( host, recv_reliable );
- clearReceiveState();
- valid_packet = false;
- }
-
- if(
- valid_packet &&
- cdp &&
- !cdp->getTrusted() &&
- mTemplateMessageReader->isTrusted())
- {
- logTrustedMsgFromUntrustedCircuit( host );
- clearReceiveState();
-
- sendDenyTrustedCircuit(host);
- valid_packet = false;
- }
-
- if( valid_packet )
- {
- logValidMsg(cdp, host, recv_reliable, recv_resent, acks>0 );
- valid_packet = mTemplateMessageReader->readMessage(buffer, host);
- }
-
- // It's possible that the circuit went away, because ANY message can disable the circuit
- // (for example, UseCircuit, CloseCircuit, DisableSimulator). Find it again.
- cdp = mCircuitInfo.findCircuit(host);
-
- if (valid_packet)
- {
- mPacketsIn++;
- mBytesIn += mTrueReceiveSize;
-
- // ACK here for valid packets that we've seen
- // for the first time.
- if (cdp && recv_reliable)
- {
- // Add to the recently received list for duplicate suppression
- cdp->mRecentlyReceivedReliablePackets[mCurrentRecvPacketID] = getMessageTimeUsecs();
-
- // Put it onto the list of packets to be acked
- cdp->collectRAck(mCurrentRecvPacketID);
- mReliablePacketsIn++;
- }
- }
- else
- {
- if (mbProtected && (!cdp))
- {
- LL_WARNS("Messaging") << "Invalid Packet from invalid circuit " << host << LL_ENDL;
- mOffCircuitPackets++;
- }
- else
- {
- mInvalidOnCircuitPackets++;
- }
- }
- }
- } while (!valid_packet && receive_size > 0);
-
- F64Seconds mt_sec = getMessageTimeSeconds();
- // Check to see if we need to print debug info
- if ((mt_sec - mCircuitPrintTime) > mCircuitPrintFreq)
- {
- dumpCircuitInfo();
- mCircuitPrintTime = mt_sec;
- }
-
- if( !valid_packet )
- {
- clearReceiveState();
- }
-
- return valid_packet;
-}
-
-S32 LLMessageSystem::getReceiveBytes() const
-{
- if (getReceiveCompressedSize())
- {
- return getReceiveCompressedSize() * 8;
- }
- else
- {
- return getReceiveSize() * 8;
- }
-}
-
-
-void LLMessageSystem::processAcks(LockMessageChecker&, F32 collect_time)
-{
- F64Seconds mt_sec = getMessageTimeSeconds();
- {
- gTransferManager.updateTransfers();
-
- if (gXferManager)
- {
- gXferManager->retransmitUnackedPackets();
- }
-
- if (gAssetStorage)
- {
- gAssetStorage->checkForTimeouts();
- }
- }
-
- bool dump = false;
- {
- // Check the status of circuits
- mCircuitInfo.updateWatchDogTimers(this);
-
- //resend any necessary packets
- mCircuitInfo.resendUnackedPackets(mUnackedListDepth, mUnackedListSize);
-
- //cycle through ack list for each host we need to send acks to
- mCircuitInfo.sendAcks(collect_time);
-
- if (!mDenyTrustedCircuitSet.empty())
- {
- LL_INFOS("Messaging") << "Sending queued DenyTrustedCircuit messages." << LL_ENDL;
- for (host_set_t::iterator hostit = mDenyTrustedCircuitSet.begin(); hostit != mDenyTrustedCircuitSet.end(); ++hostit)
- {
- reallySendDenyTrustedCircuit(*hostit);
- }
- mDenyTrustedCircuitSet.clear();
- }
-
- if (mMaxMessageCounts >= 0)
- {
- if (mNumMessageCounts >= mMaxMessageCounts)
- {
- dump = true;
- }
- }
-
- if (mMaxMessageTime >= F32Seconds(0.f))
- {
- // This is one of the only places where we're required to get REAL message system time.
- mReceiveTime = getMessageTimeSeconds(true) - mMessageCountTime;
- if (mReceiveTime > mMaxMessageTime)
- {
- dump = true;
- }
- }
- }
-
- if (dump)
- {
- dumpReceiveCounts();
- }
- resetReceiveCounts();
-
- if ((mt_sec - mResendDumpTime) > CIRCUIT_DUMP_TIMEOUT)
- {
- mResendDumpTime = mt_sec;
- mCircuitInfo.dumpResends();
- }
-}
-
-void LLMessageSystem::copyMessageReceivedToSend()
-{
- // NOTE: babbage: switch builder to match reader to avoid
- // converting message format
- if(mMessageReader == mTemplateMessageReader)
- {
- mMessageBuilder = mTemplateMessageBuilder;
- }
- else
- {
- mMessageBuilder = mLLSDMessageBuilder;
- }
- mSendReliable = false;
- mMessageBuilder->newMessage(mMessageReader->getMessageName());
- mMessageReader->copyToBuilder(*mMessageBuilder);
-}
-
-LLSD LLMessageSystem::getReceivedMessageLLSD() const
-{
- LLSDMessageBuilder builder;
- mMessageReader->copyToBuilder(builder);
- return builder.getMessage();
-}
-
-LLSD LLMessageSystem::getBuiltMessageLLSD() const
-{
- LLSD result;
- if (mLLSDMessageBuilder == mMessageBuilder)
- {
- result = mLLSDMessageBuilder->getMessage();
- }
- else
- {
- // TODO: implement as below?
- LL_ERRS() << "Message not built as LLSD." << LL_ENDL;
- }
- return result;
-}
-
-LLSD LLMessageSystem::wrapReceivedTemplateData() const
-{
- if(mMessageReader == mTemplateMessageReader)
- {
- LLTemplateMessageBuilder builder(mMessageTemplates);
- builder.newMessage(mMessageReader->getMessageName());
- mMessageReader->copyToBuilder(builder);
- U8 buffer[MAX_BUFFER_SIZE];
- const U8 offset_to_data = 0;
- U32 size = builder.buildMessage(buffer, MAX_BUFFER_SIZE,
- offset_to_data);
- std::vector<U8> binary_data(buffer, buffer+size);
- LLSD wrapped_data = LLSD::emptyMap();
- wrapped_data["binary-template-data"] = binary_data;
- return wrapped_data;
- }
- else
- {
- return getReceivedMessageLLSD();
- }
-}
-
-LLSD LLMessageSystem::wrapBuiltTemplateData() const
-{
- LLSD result;
- if (mLLSDMessageBuilder == mMessageBuilder)
- {
- result = getBuiltMessageLLSD();
- }
- else
- {
- U8 buffer[MAX_BUFFER_SIZE];
- const U8 offset_to_data = 0;
- U32 size = mTemplateMessageBuilder->buildMessage(
- buffer, MAX_BUFFER_SIZE,
- offset_to_data);
- std::vector<U8> binary_data(buffer, buffer+size);
- LLSD wrapped_data = LLSD::emptyMap();
- wrapped_data["binary-template-data"] = binary_data;
- result = wrapped_data;
- }
- return result;
-}
-
-LLStoredMessagePtr LLMessageSystem::getReceivedMessage() const
-{
- const std::string& name = mMessageReader->getMessageName();
- LLSD message = wrapReceivedTemplateData();
-
- return LLStoredMessagePtr(new LLStoredMessage(name, message));
-}
-
-LLStoredMessagePtr LLMessageSystem::getBuiltMessage() const
-{
- const std::string& name = mMessageBuilder->getMessageName();
- LLSD message = wrapBuiltTemplateData();
-
- return LLStoredMessagePtr(new LLStoredMessage(name, message));
-}
-
-S32 LLMessageSystem::sendMessage(const LLHost &host, LLStoredMessagePtr message)
-{
- return sendMessage(host, message->mName.c_str(), message->mMessage);
-}
-
-
-void LLMessageSystem::clearMessage()
-{
- mSendReliable = false;
- mMessageBuilder->clearMessage();
-}
-
-// set block to add data to within current message
-void LLMessageSystem::nextBlockFast(const char *blockname)
-{
- mMessageBuilder->nextBlock(blockname);
-}
-
-void LLMessageSystem::nextBlock(const char *blockname)
-{
- nextBlockFast(LLMessageStringTable::getInstance()->getString(blockname));
-}
-
-bool LLMessageSystem::isSendFull(const char* blockname)
-{
- char* stringTableName = NULL;
- if(NULL != blockname)
- {
- stringTableName = LLMessageStringTable::getInstance()->getString(blockname);
- }
- return isSendFullFast(stringTableName);
-}
-
-bool LLMessageSystem::isSendFullFast(const char* blockname)
-{
- return mMessageBuilder->isMessageFull(blockname);
-}
-
-
-// blow away the last block of a message, return false if that leaves no blocks or there wasn't a block to remove
-// TODO: Babbage: Remove this horror.
-bool LLMessageSystem::removeLastBlock()
-{
- return mMessageBuilder->removeLastBlock();
-}
-
-S32 LLMessageSystem::sendReliable(const LLHost &host)
-{
- return sendReliable(host, LL_DEFAULT_RELIABLE_RETRIES, true, LL_PING_BASED_TIMEOUT_DUMMY, NULL, NULL);
-}
-
-
-S32 LLMessageSystem::sendSemiReliable(const LLHost &host, void (*callback)(void **,S32), void ** callback_data)
-{
- F32Seconds timeout;
-
- LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
- if (cdp)
- {
- timeout = llmax(LL_MINIMUM_SEMIRELIABLE_TIMEOUT_SECONDS,
- F32Seconds(LL_SEMIRELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged()));
- }
- else
- {
- timeout = LL_SEMIRELIABLE_TIMEOUT_FACTOR * LL_AVERAGED_PING_MAX;
- }
-
- constexpr S32 retries = 0;
- constexpr bool ping_based_timeout = false;
- return sendReliable(host, retries, ping_based_timeout, timeout, callback, callback_data);
-}
-
-// send the message via a UDP packet
-S32 LLMessageSystem::sendReliable( const LLHost &host,
- S32 retries,
- bool ping_based_timeout,
- F32Seconds timeout,
- void (*callback)(void **,S32),
- void ** callback_data)
-{
- if (ping_based_timeout)
- {
- LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
- if (cdp)
- {
- timeout = llmax(LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS, F32Seconds(LL_RELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged()));
- }
- else
- {
- timeout = llmax(LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS, F32Seconds(LL_RELIABLE_TIMEOUT_FACTOR * LL_AVERAGED_PING_MAX));
- }
- }
-
- mSendReliable = true;
- mReliablePacketParams.set(host, retries, ping_based_timeout, timeout,
- callback, callback_data,
- const_cast<char*>(mMessageBuilder->getMessageName()));
- return sendMessage(host);
-}
-
-void LLMessageSystem::forwardMessage(const LLHost &host)
-{
- copyMessageReceivedToSend();
- sendMessage(host);
-}
-
-void LLMessageSystem::forwardReliable(const LLHost &host)
-{
- copyMessageReceivedToSend();
- sendReliable(host);
-}
-
-void LLMessageSystem::forwardReliable(const U32 circuit_code)
-{
- copyMessageReceivedToSend();
- sendReliable(findHost(circuit_code));
-}
-
-S32 LLMessageSystem::forwardReliable( const LLHost &host,
- S32 retries,
- bool ping_based_timeout,
- F32Seconds timeout,
- void (*callback)(void **,S32),
- void ** callback_data)
-{
- copyMessageReceivedToSend();
- return sendReliable(host, retries, ping_based_timeout, timeout, callback, callback_data);
-}
-
-S32 LLMessageSystem::flushSemiReliable(const LLHost &host, void (*callback)(void **,S32), void ** callback_data)
-{
- F32Seconds timeout;
-
- LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
- if (cdp)
- {
- timeout = llmax(LL_MINIMUM_SEMIRELIABLE_TIMEOUT_SECONDS,
- F32Seconds(LL_SEMIRELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged()));
- }
- else
- {
- timeout = LL_SEMIRELIABLE_TIMEOUT_FACTOR * LL_AVERAGED_PING_MAX;
- }
-
- S32 send_bytes = 0;
- if (mMessageBuilder->getMessageSize())
- {
- mSendReliable = true;
- // No need for ping-based retry as not going to retry
- mReliablePacketParams.set(host, 0, false, timeout, callback,
- callback_data,
- const_cast<char*>(mMessageBuilder->getMessageName()));
- send_bytes = sendMessage(host);
- clearMessage();
- }
- else
- {
- delete callback_data;
- }
- return send_bytes;
-}
-
-S32 LLMessageSystem::flushReliable(const LLHost &host)
-{
- S32 send_bytes = 0;
- if (mMessageBuilder->getMessageSize())
- {
- send_bytes = sendReliable(host);
- }
- clearMessage();
- return send_bytes;
-}
-
-// This can be called from signal handlers,
-// so should should not use LL_INFOS().
-S32 LLMessageSystem::sendMessage(const LLHost &host)
-{
- if (! mMessageBuilder->isBuilt())
- {
- mSendSize = mMessageBuilder->buildMessage(
- mSendBuffer,
- MAX_BUFFER_SIZE,
- 0);
- }
-
- if (!(host.isOk())) // if port and ip are zero, don't bother trying to send the message
- {
- return 0;
- }
-
- LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
- if (!cdp)
- {
- // this is a new circuit!
- // are we protected?
- if (mbProtected)
- {
- // yup! don't send packets to an unknown circuit
- if(mVerboseLog)
- {
- LL_INFOS_ONCE("Messaging") << "MSG: -> " << host << "\tUNKNOWN CIRCUIT:\t"
- << mMessageBuilder->getMessageName() << LL_ENDL;
- }
- LL_WARNS_ONCE("Messaging") << "sendMessage - Trying to send "
- << mMessageBuilder->getMessageName() << " on unknown circuit "
- << host << LL_ENDL;
- return 0;
- }
- else
- {
- // nope, open the new circuit
-
- cdp = mCircuitInfo.addCircuitData(host, 0);
- }
- }
- else
- {
- // this is an old circuit. . . is it still alive?
- if (!cdp->isAlive())
- {
- // nope. don't send to dead circuits
- if(mVerboseLog)
- {
- LL_INFOS("Messaging") << "MSG: -> " << host << "\tDEAD CIRCUIT\t\t"
- << mMessageBuilder->getMessageName() << LL_ENDL;
- }
- LL_WARNS("Messaging") << "sendMessage - Trying to send message "
- << mMessageBuilder->getMessageName() << " to dead circuit "
- << host << LL_ENDL;
- return 0;
- }
- }
-
- // NOTE: babbage: LLSD message -> HTTP, template message -> UDP
- if(mMessageBuilder == mLLSDMessageBuilder)
- {
- LLSD message = mLLSDMessageBuilder->getMessage();
-
- UntrustedCallback_t cb = NULL;
- if ((mSendReliable) && (mReliablePacketParams.mCallback))
- {
- cb = boost::bind(mReliablePacketParams.mCallback, mReliablePacketParams.mCallbackData, _1);
- }
-
- LLCoros::instance().launch("LLMessageSystem::sendUntrustedSimulatorMessageCoro",
- boost::bind(&LLMessageSystem::sendUntrustedSimulatorMessageCoro, this,
- host.getUntrustedSimulatorCap(),
- mLLSDMessageBuilder->getMessageName(), message, cb));
-
- mSendReliable = false;
- mReliablePacketParams.clear();
- return 1;
- }
-
- // zero out the flags and packetid. Subtract 1 here so that we do
- // not overwrite the offset if it was set set in buildMessage().
- memset(mSendBuffer, 0, LL_PACKET_ID_SIZE - 1);
-
- // add the send id to the front of the message
- cdp->nextPacketOutID();
-
- // Packet ID size is always 4
- *((S32*)&mSendBuffer[PHL_PACKET_ID]) = htonl(cdp->getPacketOutID());
-
- // Compress the message, which will usually reduce its size.
- U8 * buf_ptr = (U8 *)mSendBuffer;
- U32 buffer_length = mSendSize;
- mMessageBuilder->compressMessage(buf_ptr, buffer_length);
-
- if (buffer_length > 1500)
- {
- if((mMessageBuilder->getMessageName() != _PREHASH_ChildAgentUpdate)
- && (mMessageBuilder->getMessageName() != _PREHASH_SendXferPacket))
- {
- LL_WARNS("Messaging") << "sendMessage - Trying to send "
- << ((buffer_length > 4000) ? "EXTRA " : "")
- << "BIG message " << mMessageBuilder->getMessageName() << " - "
- << buffer_length << LL_ENDL;
- }
- }
- if (mSendReliable)
- {
- buf_ptr[0] |= LL_RELIABLE_FLAG;
-
- if (!cdp->getUnackedPacketCount())
- {
- // We are adding the first packed onto the unacked packet list(s)
- // Add this circuit to the list of circuits with unacked packets
- mCircuitInfo.mUnackedCircuitMap[cdp->mHost] = cdp;
- }
-
- cdp->addReliablePacket(mSocket,buf_ptr,buffer_length, &mReliablePacketParams);
- mReliablePacketsOut++;
- }
-
- // tack packet acks onto the end of this message
- S32 space_left = (MTUBYTES - buffer_length) / sizeof(TPACKETID); // space left for packet ids
- S32 ack_count = (S32)cdp->mAcks.size();
- bool is_ack_appended = false;
- std::vector<TPACKETID> acks;
- if((space_left > 0) && (ack_count > 0) &&
- (mMessageBuilder->getMessageName() != _PREHASH_PacketAck))
- {
- buf_ptr[0] |= LL_ACK_FLAG;
- S32 append_ack_count = llmin(space_left, ack_count);
- const S32 MAX_ACKS = 250;
- append_ack_count = llmin(append_ack_count, MAX_ACKS);
- std::vector<TPACKETID>::iterator iter = cdp->mAcks.begin();
- std::vector<TPACKETID>::iterator last = cdp->mAcks.begin();
- last += append_ack_count;
- TPACKETID packet_id;
- for( ; iter != last ; ++iter)
- {
- // grab the next packet id.
- packet_id = (*iter);
- if(mVerboseLog)
- {
- acks.push_back(packet_id);
- }
-
- // put it on the end of the buffer
- packet_id = htonl(packet_id);
-
- if((S32)(buffer_length + sizeof(TPACKETID)) < MAX_BUFFER_SIZE)
- {
- memcpy(&buf_ptr[buffer_length], &packet_id, sizeof(TPACKETID)); /* Flawfinder: ignore */
- // Do the accounting
- buffer_length += sizeof(TPACKETID);
- }
- else
- {
- // Just reporting error is likely not enough. Need to
- // check how to abort or error out gracefully from
- // this function. XXXTBD
- // *NOTE: Actually hitting this error would indicate
- // the calculation above for space_left, ack_count,
- // append_acout_count is incorrect or that
- // MAX_BUFFER_SIZE has fallen below MTU which is bad
- // and probably programmer error.
- LL_ERRS("Messaging") << "Buffer packing failed due to size.." << LL_ENDL;
- }
- }
-
- // clean up the source
- cdp->mAcks.erase(cdp->mAcks.begin(), last);
-
- // tack the count in the final byte
- U8 count = (U8)append_ack_count;
- buf_ptr[buffer_length++] = count;
- is_ack_appended = true;
- }
-
- bool success;
- success = mPacketRing.sendPacket(mSocket, (char *)buf_ptr, buffer_length, host);
-
- if (!success)
- {
- mSendPacketFailureCount++;
- }
- else
- {
- // mCircuitInfo already points to the correct circuit data
- cdp->addBytesOut( (S32Bytes)buffer_length );
- }
-
- if(mVerboseLog)
- {
- std::ostringstream str;
- str << "MSG: -> " << host;
- std::string buffer;
- buffer = llformat( "\t%6d\t%6d\t%6d ", mSendSize, buffer_length, cdp->getPacketOutID());
- str << buffer
- << mMessageBuilder->getMessageName()
- << (mSendReliable ? " reliable " : "");
- if(is_ack_appended)
- {
- str << "\tACKS:\t";
- std::ostream_iterator<TPACKETID> append(str, " ");
- std::copy(acks.begin(), acks.end(), append);
- }
- LL_INFOS("Messaging") << str.str() << LL_ENDL;
- }
-
-
- mPacketsOut++;
- mTotalBytesOut += buffer_length;
-
- mSendReliable = false;
- mReliablePacketParams.clear();
- return buffer_length;
-}
-
-void LLMessageSystem::logMsgFromInvalidCircuit( const LLHost& host, bool recv_reliable )
-{
- if(mVerboseLog)
- {
- std::ostringstream str;
- str << "MSG: <- " << host;
- std::string buffer;
- buffer = llformat( "\t%6d\t%6d\t%6d ", mMessageReader->getMessageSize(), (mIncomingCompressedSize ? mIncomingCompressedSize: mMessageReader->getMessageSize()), mCurrentRecvPacketID);
- str << buffer
- << nullToEmpty(mMessageReader->getMessageName())
- << (recv_reliable ? " reliable" : "")
- << " REJECTED";
- LL_INFOS("Messaging") << str.str() << LL_ENDL;
- }
- // nope!
- // cout << "Rejecting unexpected message " << mCurrentMessageTemplate->mName << " from " << hex << ip << " , " << dec << port << endl;
-
- // Keep track of rejected messages as well
- if (mNumMessageCounts >= MAX_MESSAGE_COUNT_NUM)
- {
- LL_WARNS("Messaging") << "Got more than " << MAX_MESSAGE_COUNT_NUM << " packets without clearing counts" << LL_ENDL;
- }
- else
- {
- // TODO: babbage: work out if we need these
- // mMessageCountList[mNumMessageCounts].mMessageNum = mCurrentRMessageTemplate->mMessageNumber;
- mMessageCountList[mNumMessageCounts].mMessageBytes = mMessageReader->getMessageSize();
- mMessageCountList[mNumMessageCounts].mInvalid = true;
- mNumMessageCounts++;
- }
-}
-
-S32 LLMessageSystem::sendMessage(
- const LLHost &host,
- const char* name,
- const LLSD& message)
-{
- if (!(host.isOk()))
- {
- LL_WARNS("Messaging") << "trying to send message to invalid host" << LL_ENDL;
- return 0;
- }
-
- UntrustedCallback_t cb = NULL;
- if ((mSendReliable) && (mReliablePacketParams.mCallback))
- {
- cb = boost::bind(mReliablePacketParams.mCallback, mReliablePacketParams.mCallbackData, _1);
- }
-
- LLCoros::instance().launch("LLMessageSystem::sendUntrustedSimulatorMessageCoro",
- boost::bind(&LLMessageSystem::sendUntrustedSimulatorMessageCoro, this,
- host.getUntrustedSimulatorCap(), name, message, cb));
- return 1;
-}
-
-void LLMessageSystem::logTrustedMsgFromUntrustedCircuit( const LLHost& host )
-{
- // RequestTrustedCircuit is how we establish trust, so don't spam
- // if it's received on a trusted circuit. JC
- if (strcmp(mMessageReader->getMessageName(), "RequestTrustedCircuit"))
- {
- LL_WARNS("Messaging") << "Received trusted message on untrusted circuit. "
- << "Will reply with deny. "
- << "Message: " << nullToEmpty(mMessageReader->getMessageName())
- << " Host: " << host << LL_ENDL;
- }
-
- if (mNumMessageCounts >= MAX_MESSAGE_COUNT_NUM)
- {
- LL_WARNS("Messaging") << "got more than " << MAX_MESSAGE_COUNT_NUM
- << " packets without clearing counts"
- << LL_ENDL;
- }
- else
- {
- // TODO: babbage: work out if we need these
- //mMessageCountList[mNumMessageCounts].mMessageNum
- // = mCurrentRMessageTemplate->mMessageNumber;
- mMessageCountList[mNumMessageCounts].mMessageBytes
- = mMessageReader->getMessageSize();
- mMessageCountList[mNumMessageCounts].mInvalid = true;
- mNumMessageCounts++;
- }
-}
-
-void LLMessageSystem::logValidMsg(LLCircuitData *cdp, const LLHost& host, bool recv_reliable, bool recv_resent, bool recv_acks )
-{
- if (mNumMessageCounts >= MAX_MESSAGE_COUNT_NUM)
- {
- LL_WARNS("Messaging") << "Got more than " << MAX_MESSAGE_COUNT_NUM << " packets without clearing counts" << LL_ENDL;
- }
- else
- {
- // TODO: babbage: work out if we need these
- //mMessageCountList[mNumMessageCounts].mMessageNum = mCurrentRMessageTemplate->mMessageNumber;
- mMessageCountList[mNumMessageCounts].mMessageBytes = mMessageReader->getMessageSize();
- mMessageCountList[mNumMessageCounts].mInvalid = false;
- mNumMessageCounts++;
- }
-
- if (cdp)
- {
- // update circuit packet ID tracking (missing/out of order packets)
- cdp->checkPacketInID( mCurrentRecvPacketID, recv_resent );
- cdp->addBytesIn( (S32Bytes)mTrueReceiveSize );
- }
-
- if(mVerboseLog)
- {
- std::ostringstream str;
- str << "MSG: <- " << host;
- std::string buffer;
- buffer = llformat( "\t%6d\t%6d\t%6d ", mMessageReader->getMessageSize(), (mIncomingCompressedSize ? mIncomingCompressedSize : mMessageReader->getMessageSize()), mCurrentRecvPacketID);
- str << buffer
- << nullToEmpty(mMessageReader->getMessageName())
- << (recv_reliable ? " reliable" : "")
- << (recv_resent ? " resent" : "")
- << (recv_acks ? " acks" : "");
- LL_INFOS("Messaging") << str.str() << LL_ENDL;
- }
-}
-
-void LLMessageSystem::sanityCheck()
-{
-// TODO: babbage: reinstate
-
-// if (!mCurrentRMessageData)
-// {
-// LL_ERRS("Messaging") << "mCurrentRMessageData is NULL" << LL_ENDL;
-// }
-
-// if (!mCurrentRMessageTemplate)
-// {
-// LL_ERRS("Messaging") << "mCurrentRMessageTemplate is NULL" << LL_ENDL;
-// }
-
-// if (!mCurrentRTemplateBlock)
-// {
-// LL_ERRS("Messaging") << "mCurrentRTemplateBlock is NULL" << LL_ENDL;
-// }
-
-// if (!mCurrentRDataBlock)
-// {
-// LL_ERRS("Messaging") << "mCurrentRDataBlock is NULL" << LL_ENDL;
-// }
-
-// if (!mCurrentSMessageData)
-// {
-// LL_ERRS("Messaging") << "mCurrentSMessageData is NULL" << LL_ENDL;
-// }
-
-// if (!mCurrentSMessageTemplate)
-// {
-// LL_ERRS("Messaging") << "mCurrentSMessageTemplate is NULL" << LL_ENDL;
-// }
-
-// if (!mCurrentSTemplateBlock)
-// {
-// LL_ERRS("Messaging") << "mCurrentSTemplateBlock is NULL" << LL_ENDL;
-// }
-
-// if (!mCurrentSDataBlock)
-// {
-// LL_ERRS("Messaging") << "mCurrentSDataBlock is NULL" << LL_ENDL;
-// }
-}
-
-void LLMessageSystem::showCircuitInfo()
-{
- LL_INFOS("Messaging") << mCircuitInfo << LL_ENDL;
-}
-
-
-void LLMessageSystem::dumpCircuitInfo()
-{
- LL_DEBUGS("Messaging") << mCircuitInfo << LL_ENDL;
-}
-
-/* virtual */
-U32 LLMessageSystem::getOurCircuitCode()
-{
- return mOurCircuitCode;
-}
-
-void LLMessageSystem::getCircuitInfo(LLSD& info) const
-{
- mCircuitInfo.getInfo(info);
-}
-
-// returns whether the given host is on a trusted circuit
-bool LLMessageSystem::getCircuitTrust(const LLHost &host)
-{
- LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
- if (cdp)
- {
- return cdp->getTrusted();
- }
-
- return false;
-}
-
-// Activate a circuit, and set its trust level (true if trusted,
-// false if not).
-void LLMessageSystem::enableCircuit(const LLHost &host, bool trusted)
-{
- LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
- if (!cdp)
- {
- cdp = mCircuitInfo.addCircuitData(host, 0);
- }
- else
- {
- cdp->setAlive(true);
- }
- cdp->setTrusted(trusted);
-}
-
-void LLMessageSystem::disableCircuit(const LLHost &host)
-{
- LL_INFOS("Messaging") << "LLMessageSystem::disableCircuit for " << host << LL_ENDL;
- U32 code = gMessageSystem->findCircuitCode( host );
-
- // Don't need to do this, as we're removing the circuit info anyway - djs 01/28/03
-
- // don't clean up 0 circuit code entries
- // because many hosts (neighbor sims, etc) can have the 0 circuit
- if (code)
- {
- //if (mCircuitCodes.checkKey(code))
- code_session_map_t::iterator it = mCircuitCodes.find(code);
- if(it != mCircuitCodes.end())
- {
- LL_INFOS("Messaging") << "Circuit " << code << " removed from list" << LL_ENDL;
- //mCircuitCodes.removeData(code);
- mCircuitCodes.erase(it);
- }
-
- U64 ip_port = 0;
- std::map<U32, U64>::iterator iter = gMessageSystem->mCircuitCodeToIPPort.find(code);
- if (iter != gMessageSystem->mCircuitCodeToIPPort.end())
- {
- ip_port = iter->second;
-
- gMessageSystem->mCircuitCodeToIPPort.erase(iter);
-
- U32 old_port = (U32)(ip_port & (U64)0xFFFFFFFF);
- U32 old_ip = (U32)(ip_port >> 32);
-
- LL_INFOS("Messaging") << "Host " << LLHost(old_ip, old_port) << " circuit " << code << " removed from lookup table" << LL_ENDL;
- gMessageSystem->mIPPortToCircuitCode.erase(ip_port);
- }
- mCircuitInfo.removeCircuitData(host);
- }
- else
- {
- // Sigh, since we can open circuits which don't have circuit
- // codes, it's possible for this to happen...
-
- LL_WARNS("Messaging") << "Couldn't find circuit code for " << host << LL_ENDL;
- }
-
-}
-
-
-void LLMessageSystem::setCircuitAllowTimeout(const LLHost &host, bool allow)
-{
- LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
- if (cdp)
- {
- cdp->setAllowTimeout(allow);
- }
-}
-
-void LLMessageSystem::setCircuitTimeoutCallback(const LLHost &host, void (*callback_func)(const LLHost & host, void *user_data), void *user_data)
-{
- LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
- if (cdp)
- {
- cdp->setTimeoutCallback(callback_func, user_data);
- }
-}
-
-
-bool LLMessageSystem::checkCircuitBlocked(const U32 circuit)
-{
- LLHost host = findHost(circuit);
-
- if (!host.isOk())
- {
- LL_DEBUGS("Messaging") << "checkCircuitBlocked: Unknown circuit " << circuit << LL_ENDL;
- return true;
- }
-
- LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
- if (cdp)
- {
- return cdp->isBlocked();
- }
- else
- {
- LL_INFOS("Messaging") << "checkCircuitBlocked(circuit): Unknown host - " << host << LL_ENDL;
- return false;
- }
-}
-
-bool LLMessageSystem::checkCircuitAlive(const U32 circuit)
-{
- LLHost host = findHost(circuit);
-
- if (!host.isOk())
- {
- LL_DEBUGS("Messaging") << "checkCircuitAlive: Unknown circuit " << circuit << LL_ENDL;
- return false;
- }
-
- LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
- if (cdp)
- {
- return cdp->isAlive();
- }
- else
- {
- LL_INFOS("Messaging") << "checkCircuitAlive(circuit): Unknown host - " << host << LL_ENDL;
- return false;
- }
-}
-
-bool LLMessageSystem::checkCircuitAlive(const LLHost &host)
-{
- LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
- if (cdp)
- {
- return cdp->isAlive();
- }
- else
- {
- LL_DEBUGS("Messaging") << "checkCircuitAlive(host): Unknown host - " << host << LL_ENDL;
- return false;
- }
-}
-
-
-void LLMessageSystem::setCircuitProtection(bool b_protect)
-{
- mbProtected = b_protect;
-}
-
-
-U32 LLMessageSystem::findCircuitCode(const LLHost &host)
-{
- U64 ip64 = (U64) host.getAddress();
- U64 port64 = (U64) host.getPort();
- U64 ip_port = (ip64 << 32) | port64;
-
- return get_if_there(mIPPortToCircuitCode, ip_port, U32(0));
-}
-
-LLHost LLMessageSystem::findHost(const U32 circuit_code)
-{
- if (mCircuitCodeToIPPort.count(circuit_code) > 0)
- {
- return LLHost(mCircuitCodeToIPPort[circuit_code]);
- }
- else
- {
- return LLHost();
- }
-}
-
-void LLMessageSystem::setMaxMessageTime(const F32 seconds)
-{
- mMaxMessageTime = F32Seconds(seconds);
-}
-
-void LLMessageSystem::setMaxMessageCounts(const S32 num)
-{
- mMaxMessageCounts = num;
-}
-
-
-std::ostream& operator<<(std::ostream& s, LLMessageSystem &msg)
-{
- U32 i;
- if (msg.mbError)
- {
- s << "Message system not correctly initialized";
- }
- else
- {
- s << "Message system open on port " << msg.mPort << " and socket " << msg.mSocket << "\n";
-// s << "Message template file " << msg.mName << " loaded\n";
-
- s << "\nHigh frequency messages:\n";
-
- for (i = 1; msg.mMessageNumbers[i] && (i < 255); i++)
- {
- s << *(msg.mMessageNumbers[i]);
- }
-
- s << "\nMedium frequency messages:\n";
-
- for (i = (255 << 8) + 1; msg.mMessageNumbers[i] && (i < (255 << 8) + 255); i++)
- {
- s << *msg.mMessageNumbers[i];
- }
-
- s << "\nLow frequency messages:\n";
-
- for (i = (0xFFFF0000) + 1; msg.mMessageNumbers[i] && (i < 0xFFFFFFFF); i++)
- {
- s << *msg.mMessageNumbers[i];
- }
- }
- return s;
-}
-
-// LLPounceable supports callWhenReady(), to permit clients to queue up (e.g.)
-// callback registrations for when gMessageSystem is first assigned
-LLPounceable<LLMessageSystem*, LLPounceableStatic> gMessageSystem;
-
-// update appropriate ping info
-void process_complete_ping_check(LLMessageSystem *msgsystem, void** /*user_data*/)
-{
- U8 ping_id;
- msgsystem->getU8Fast(_PREHASH_PingID, _PREHASH_PingID, ping_id);
-
- LLCircuitData *cdp;
- cdp = msgsystem->mCircuitInfo.findCircuit(msgsystem->getSender());
-
- // stop the appropriate timer
- if (cdp)
- {
- cdp->pingTimerStop(ping_id);
- }
-}
-
-void process_start_ping_check(LLMessageSystem *msgsystem, void** /*user_data*/)
-{
- U8 ping_id;
- msgsystem->getU8Fast(_PREHASH_PingID, _PREHASH_PingID, ping_id);
-
- LLCircuitData *cdp;
- cdp = msgsystem->mCircuitInfo.findCircuit(msgsystem->getSender());
- if (cdp)
- {
- // Grab the packet id of the oldest unacked packet
- U32 packet_id;
- msgsystem->getU32Fast(_PREHASH_PingID, _PREHASH_OldestUnacked, packet_id);
- cdp->clearDuplicateList(packet_id);
- }
-
- // Send off the response
- msgsystem->newMessageFast(_PREHASH_CompletePingCheck);
- msgsystem->nextBlockFast(_PREHASH_PingID);
- msgsystem->addU8(_PREHASH_PingID, ping_id);
- msgsystem->sendMessage(msgsystem->getSender());
-}
-
-
-
-// Note: this is currently unused. --mark
-void open_circuit(LLMessageSystem *msgsystem, void** /*user_data*/)
-{
- U32 ip;
- U16 port;
-
- msgsystem->getIPAddrFast(_PREHASH_CircuitInfo, _PREHASH_IP, ip);
- msgsystem->getIPPortFast(_PREHASH_CircuitInfo, _PREHASH_Port, port);
-
- // By default, OpenCircuit's are untrusted
- msgsystem->enableCircuit(LLHost(ip, port), false);
-}
-
-void close_circuit(LLMessageSystem *msgsystem, void** /*user_data*/)
-{
- msgsystem->disableCircuit(msgsystem->getSender());
-}
-
-// static
-/*
-void LLMessageSystem::processAssignCircuitCode(LLMessageSystem* msg, void**)
-{
- // if we already have a circuit code, we can bail
- if(msg->mOurCircuitCode) return;
- LLUUID session_id;
- msg->getUUIDFast(_PREHASH_CircuitCode, _PREHASH_SessionID, session_id);
- if(session_id != msg->getMySessionID())
- {
- LL_WARNS("Messaging") << "AssignCircuitCode, bad session id. Expecting "
- << msg->getMySessionID() << " but got " << session_id
- << LL_ENDL;
- return;
- }
- U32 code;
- msg->getU32Fast(_PREHASH_CircuitCode, _PREHASH_Code, code);
- if (!code)
- {
- LL_ERRS("Messaging") << "Assigning circuit code of zero!" << LL_ENDL;
- }
-
- msg->mOurCircuitCode = code;
- LL_INFOS("Messaging") << "Circuit code " << code << " assigned." << LL_ENDL;
-}
-*/
-
-// static
-void LLMessageSystem::processAddCircuitCode(LLMessageSystem* msg, void**)
-{
- U32 code;
- msg->getU32Fast(_PREHASH_CircuitCode, _PREHASH_Code, code);
- LLUUID session_id;
- msg->getUUIDFast(_PREHASH_CircuitCode, _PREHASH_SessionID, session_id);
- (void)msg->addCircuitCode(code, session_id);
-
- // Send the ack back
- //msg->newMessageFast(_PREHASH_AckAddCircuitCode);
- //msg->nextBlockFast(_PREHASH_CircuitCode);
- //msg->addU32Fast(_PREHASH_Code, code);
- //msg->sendMessage(msg->getSender());
-}
-
-bool LLMessageSystem::addCircuitCode(U32 code, const LLUUID& session_id)
-{
- if(!code)
- {
- LL_WARNS("Messaging") << "addCircuitCode: zero circuit code" << LL_ENDL;
- return false;
- }
- code_session_map_t::iterator it = mCircuitCodes.find(code);
- if(it == mCircuitCodes.end())
- {
- LL_INFOS("Messaging") << "New circuit code " << code << " added" << LL_ENDL;
- //msg->mCircuitCodes[circuit_code] = circuit_code;
-
- mCircuitCodes.insert(code_session_map_t::value_type(code, session_id));
- }
- else
- {
- LL_INFOS("Messaging") << "Duplicate circuit code " << code << " added" << LL_ENDL;
- }
- return true;
-}
-
-//void ack_add_circuit_code(LLMessageSystem *msgsystem, void** /*user_data*/)
-//{
- // By default, we do nothing. This particular message is only handled by the spaceserver
-//}
-
-// static
-void LLMessageSystem::processUseCircuitCode(LLMessageSystem* msg,
- void** user)
-{
- U32 circuit_code_in;
- msg->getU32Fast(_PREHASH_CircuitCode, _PREHASH_Code, circuit_code_in);
-
- U32 ip = msg->getSenderIP();
- U32 port = msg->getSenderPort();
-
- U64 ip64 = ip;
- U64 port64 = port;
- U64 ip_port_in = (ip64 << 32) | port64;
-
- if (circuit_code_in)
- {
- //if (!msg->mCircuitCodes.checkKey(circuit_code_in))
- code_session_map_t::iterator it;
- it = msg->mCircuitCodes.find(circuit_code_in);
- if(it == msg->mCircuitCodes.end())
- {
- // Whoah, abort! We don't know anything about this circuit code.
- LL_WARNS("Messaging") << "UseCircuitCode for " << circuit_code_in
- << " received without AddCircuitCode message - aborting"
- << LL_ENDL;
- return;
- }
-
- LLUUID id;
- msg->getUUIDFast(_PREHASH_CircuitCode, _PREHASH_ID, id);
- LLUUID session_id;
- msg->getUUIDFast(_PREHASH_CircuitCode, _PREHASH_SessionID, session_id);
- if(session_id != (*it).second)
- {
- LL_WARNS("Messaging") << "UseCircuitCode unmatched session id. Got "
- << session_id << " but expected " << (*it).second
- << LL_ENDL;
- return;
- }
-
- // Clean up previous references to this ip/port or circuit
- U64 ip_port_old = get_if_there(msg->mCircuitCodeToIPPort, circuit_code_in, U64(0));
- U32 circuit_code_old = get_if_there(msg->mIPPortToCircuitCode, ip_port_in, U32(0));
-
- if (ip_port_old)
- {
- if ((ip_port_old == ip_port_in) && (circuit_code_old == circuit_code_in))
- {
- // Current information is the same as incoming info, ignore
- LL_INFOS("Messaging") << "Got duplicate UseCircuitCode for circuit " << circuit_code_in << " to " << msg->getSender() << LL_ENDL;
- return;
- }
-
- // Hmm, got a different IP and port for the same circuit code.
- U32 circut_code_old_ip_port = get_if_there(msg->mIPPortToCircuitCode, ip_port_old, U32(0));
- msg->mCircuitCodeToIPPort.erase(circut_code_old_ip_port);
- msg->mIPPortToCircuitCode.erase(ip_port_old);
- U32 old_port = (U32)(ip_port_old & (U64)0xFFFFFFFF);
- U32 old_ip = (U32)(ip_port_old >> 32);
- LL_INFOS("Messaging") << "Removing derelict lookup entry for circuit " << circuit_code_old << " to " << LLHost(old_ip, old_port) << LL_ENDL;
- }
-
- if (circuit_code_old)
- {
- LLHost cur_host(ip, port);
-
- LL_WARNS("Messaging") << "Disabling existing circuit for " << cur_host << LL_ENDL;
- msg->disableCircuit(cur_host);
- if (circuit_code_old == circuit_code_in)
- {
- LL_WARNS("Messaging") << "Asymmetrical circuit to ip/port lookup!" << LL_ENDL;
- LL_WARNS("Messaging") << "Multiple circuit codes for " << cur_host << " probably!" << LL_ENDL;
- LL_WARNS("Messaging") << "Permanently disabling circuit" << LL_ENDL;
- return;
- }
- else
- {
- LL_WARNS("Messaging") << "Circuit code changed for " << msg->getSender()
- << " from " << circuit_code_old << " to "
- << circuit_code_in << LL_ENDL;
- }
- }
-
- // Since this comes from the viewer, it's untrusted, but it
- // passed the circuit code and session id check, so we will go
- // ahead and persist the ID associated.
- LLCircuitData *cdp = msg->mCircuitInfo.findCircuit(msg->getSender());
- bool had_circuit_already = cdp != nullptr;
-
- msg->enableCircuit(msg->getSender(), false);
- cdp = msg->mCircuitInfo.findCircuit(msg->getSender());
- if(cdp)
- {
- cdp->setRemoteID(id);
- cdp->setRemoteSessionID(session_id);
- }
-
- if (!had_circuit_already)
- {
- //
- // HACK HACK HACK HACK HACK!
- //
- // This would NORMALLY happen inside logValidMsg, but at the point that this happens
- // inside logValidMsg, there's no circuit for this message yet. So the awful thing that
- // we do here is do it inside this message handler immediately AFTER the message is
- // handled.
- //
- // We COULD not do this, but then what happens is that some of the circuit bookkeeping
- // gets broken, especially the packets in count. That causes some later packets to flush
- // the RecentlyReceivedReliable list, resulting in an error in which UseCircuitCode
- // doesn't get properly duplicate suppressed. Not a BIG deal, but it's somewhat confusing
- // (and bad from a state point of view). DJS 9/23/04
- //
- cdp->checkPacketInID(gMessageSystem->mCurrentRecvPacketID, false ); // Since this is the first message on the circuit, by definition it's not resent.
- }
-
- msg->mIPPortToCircuitCode[ip_port_in] = circuit_code_in;
- msg->mCircuitCodeToIPPort[circuit_code_in] = ip_port_in;
-
- LL_INFOS("Messaging") << "Circuit code " << circuit_code_in << " from "
- << msg->getSender() << " for agent " << id << " in session "
- << session_id << LL_ENDL;
-
- const LLUseCircuitCodeResponder* responder =
- (const LLUseCircuitCodeResponder*) user;
- if(responder)
- {
- responder->complete(msg->getSender(), id);
- }
- }
- else
- {
- LL_WARNS("Messaging") << "Got zero circuit code in use_circuit_code" << LL_ENDL;
- }
-}
-
-// static
-void LLMessageSystem::processError(LLMessageSystem* msg, void**)
-{
- S32 error_code = 0;
- msg->getS32("Data", "Code", error_code);
- std::string error_token;
- msg->getString("Data", "Token", error_token);
-
- LLUUID error_id;
- msg->getUUID("Data", "ID", error_id);
- std::string error_system;
- msg->getString("Data", "System", error_system);
-
- std::string error_message;
- msg->getString("Data", "Message", error_message);
-
- LL_WARNS("Messaging") << "Message error from " << msg->getSender() << " - "
- << error_code << " " << error_token << " " << error_id << " \""
- << error_system << "\" \"" << error_message << "\"" << LL_ENDL;
-}
-
-
-static LLHTTPNode& messageRootNode()
-{
- static LLHTTPNode root_node;
- static bool initialized = false;
- if (!initialized) {
- initialized = true;
- LLHTTPRegistrar::buildAllServices(root_node);
- }
-
- return root_node;
-}
-
-//static
-void LLMessageSystem::dispatch(
- const std::string& msg_name,
- const LLSD& message)
-{
- LLPointer<LLSimpleResponse> responsep = LLSimpleResponse::create();
- dispatch(msg_name, message, responsep);
-}
-
-//static
-void LLMessageSystem::dispatch(
- const std::string& msg_name,
- const LLSD& message,
- LLHTTPNode::ResponsePtr responsep)
-{
- if ((gMessageSystem->mMessageTemplates.find
- (LLMessageStringTable::getInstance()->getString(msg_name.c_str())) ==
- gMessageSystem->mMessageTemplates.end()) &&
- !LLMessageConfig::isValidMessage(msg_name))
- {
- LL_WARNS("Messaging") << "Ignoring unknown message " << msg_name << LL_ENDL;
- responsep->notFound("Invalid message name");
- return;
- }
-
- std::string path = "/message/" + msg_name;
- LLSD context;
- const LLHTTPNode* handler = messageRootNode().traverse(path, context);
- if (!handler)
- {
- LL_WARNS("Messaging") << "LLMessageService::dispatch > no handler for "
- << path << LL_ENDL;
- return;
- }
- // enable this for output of message names
- LL_DEBUGS("Messaging") << "< \"" << msg_name << "\"" << LL_ENDL;
- LL_DEBUGS("Messaging") << "context: " << context << LL_ENDL;
- LL_DEBUGS("Messaging") << "message: " << message << LL_ENDL;
-
- handler->post(responsep, context, message);
-}
-
-//static
-void LLMessageSystem::dispatchTemplate(const std::string& msg_name,
- const LLSD& message,
- LLHTTPNode::ResponsePtr responsep)
-{
- LLTemplateMessageDispatcher dispatcher(*(gMessageSystem->mTemplateMessageReader));
- dispatcher.dispatch(msg_name, message, responsep);
-}
-
-static void check_for_unrecognized_messages(
- const char* type,
- const LLSD& map,
- LLMessageSystem::message_template_name_map_t& templates)
-{
- for (LLSD::map_const_iterator iter = map.beginMap(),
- end = map.endMap();
- iter != end; ++iter)
- {
- const char* name = LLMessageStringTable::getInstance()->getString(iter->first.c_str());
-
- if (templates.find(name) == templates.end())
- {
- LL_INFOS("AppInit") << " " << type
- << " ban list contains unrecognized message "
- << name << LL_ENDL;
- }
- }
-}
-
-void LLMessageSystem::setMessageBans(
- const LLSD& trusted, const LLSD& untrusted)
-{
- LL_DEBUGS("AppInit") << "LLMessageSystem::setMessageBans:" << LL_ENDL;
- bool any_set = false;
-
- for (message_template_name_map_t::iterator iter = mMessageTemplates.begin(),
- end = mMessageTemplates.end();
- iter != end; ++iter)
- {
- LLMessageTemplate* mt = iter->second;
-
- std::string name(mt->mName);
- bool ban_from_trusted
- = trusted.has(name) && trusted.get(name).asBoolean();
- bool ban_from_untrusted
- = untrusted.has(name) && untrusted.get(name).asBoolean();
-
- mt->mBanFromTrusted = ban_from_trusted;
- mt->mBanFromUntrusted = ban_from_untrusted;
-
- if (ban_from_trusted || ban_from_untrusted)
- {
- LL_INFOS("AppInit") << " " << name << " banned from "
- << (ban_from_trusted ? "TRUSTED " : " ")
- << (ban_from_untrusted ? "UNTRUSTED " : " ")
- << LL_ENDL;
- any_set = true;
- }
- }
-
- if (!any_set)
- {
- LL_DEBUGS("AppInit") << " no messages banned" << LL_ENDL;
- }
-
- check_for_unrecognized_messages("trusted", trusted, mMessageTemplates);
- check_for_unrecognized_messages("untrusted", untrusted, mMessageTemplates);
-}
-
-S32 LLMessageSystem::sendError(
- const LLHost& host,
- const LLUUID& agent_id,
- S32 code,
- const std::string& token,
- const LLUUID& id,
- const std::string& system,
- const std::string& message,
- const LLSD& data)
-{
- newMessage("Error");
- nextBlockFast(_PREHASH_AgentData);
- addUUIDFast(_PREHASH_AgentID, agent_id);
- nextBlockFast(_PREHASH_Data);
- addS32("Code", code);
- addString("Token", token);
- addUUID("ID", id);
- addString("System", system);
- std::string temp;
- temp = message;
- if(temp.size() > (size_t)MTUBYTES) temp.resize((size_t)MTUBYTES);
- addString("Message", message);
- LLPointer<LLSDBinaryFormatter> formatter = new LLSDBinaryFormatter;
- std::ostringstream ostr;
- formatter->format(data, ostr);
- temp = ostr.str();
- bool pack_data = true;
- static const std::string ERROR_MESSAGE_NAME("Error");
- if (LLMessageConfig::getMessageFlavor(ERROR_MESSAGE_NAME) ==
- LLMessageConfig::TEMPLATE_FLAVOR)
- {
- S32 msg_size = temp.size() + mMessageBuilder->getMessageSize();
- if(msg_size >= ETHERNET_MTU_BYTES)
- {
- pack_data = false;
- }
- }
- if(pack_data)
- {
- addBinaryData("Data", (void*)temp.c_str(), temp.size());
- }
- else
- {
- LL_WARNS("Messaging") << "Data and message were too large -- data removed."
- << LL_ENDL;
- addBinaryData("Data", NULL, 0);
- }
- return sendReliable(host);
-}
-
-void process_packet_ack(LLMessageSystem *msgsystem, void** /*user_data*/)
-{
- TPACKETID packet_id;
-
- LLHost host = msgsystem->getSender();
- LLCircuitData *cdp = msgsystem->mCircuitInfo.findCircuit(host);
- if (cdp)
- {
-
- S32 ack_count = msgsystem->getNumberOfBlocksFast(_PREHASH_Packets);
-
- for (S32 i = 0; i < ack_count; i++)
- {
- msgsystem->getU32Fast(_PREHASH_Packets, _PREHASH_ID, packet_id, i);
-// LL_DEBUGS("Messaging") << "ack recvd' from " << host << " for packet " << (TPACKETID)packet_id << LL_ENDL;
- cdp->ackReliablePacket(packet_id);
- }
- if (!cdp->getUnackedPacketCount())
- {
- // Remove this circuit from the list of circuits with unacked packets
- gMessageSystem->mCircuitInfo.mUnackedCircuitMap.erase(host);
- }
- }
-}
-
-
-/*
-void process_log_messages(LLMessageSystem* msg, void**)
-{
- U8 log_message;
-
- msg->getU8Fast(_PREHASH_Options, _PREHASH_Enable, log_message);
-
- if (log_message)
- {
- LL_INFOS("Messaging") << "Starting logging via message" << LL_ENDL;
- msg->startLogging();
- }
- else
- {
- LL_INFOS("Messaging") << "Stopping logging via message" << LL_ENDL;
- msg->stopLogging();
- }
-}*/
-
-// Make circuit trusted if the MD5 Digest matches, otherwise
-// notify remote end that they are not trusted.
-void process_create_trusted_circuit(LLMessageSystem *msg, void **)
-{
- // don't try to create trust on machines with no shared secret
- std::string shared_secret = get_shared_secret();
- if(shared_secret.empty()) return;
-
- LLUUID remote_id;
- msg->getUUIDFast(_PREHASH_DataBlock, _PREHASH_EndPointID, remote_id);
-
- LLCircuitData *cdp = msg->mCircuitInfo.findCircuit(msg->getSender());
- if (!cdp)
- {
- LL_WARNS("Messaging") << "Attempt to create trusted circuit without circuit data: "
- << msg->getSender() << LL_ENDL;
- return;
- }
-
- LLUUID local_id;
- local_id = cdp->getLocalEndPointID();
- if (remote_id == local_id)
- {
- // Don't respond to requests that use the same end point ID
- return;
- }
-
- U32 untrusted_interface = msg->getUntrustedInterface().getAddress();
- U32 last_interface = msg->getReceivingInterface().getAddress();
- if ( ( untrusted_interface != INVALID_HOST_IP_ADDRESS ) && ( untrusted_interface == last_interface ) )
- {
- if( msg->getBlockUntrustedInterface() )
- {
- LL_WARNS("Messaging") << "Ignoring CreateTrustedCircuit on public interface from host: "
- << msg->getSender() << LL_ENDL;
- return;
- }
- else
- {
- LL_WARNS("Messaging") << "Processing CreateTrustedCircuit on public interface from host: "
- << msg->getSender() << LL_ENDL;
- }
- }
-
- char their_digest[MD5HEX_STR_SIZE]; /* Flawfinder: ignore */
- S32 size = msg->getSizeFast(_PREHASH_DataBlock, _PREHASH_Digest);
- if(size != MD5HEX_STR_BYTES)
- {
- // ignore requests which pack the wrong amount of data.
- return;
- }
- msg->getBinaryDataFast(_PREHASH_DataBlock, _PREHASH_Digest, their_digest, MD5HEX_STR_BYTES);
- their_digest[MD5HEX_STR_SIZE - 1] = '\0';
- if(msg->isMatchingDigestForWindowAndUUIDs(their_digest, TRUST_TIME_WINDOW, local_id, remote_id))
- {
- cdp->setTrusted(true);
- LL_INFOS("Messaging") << "Trusted digest from " << msg->getSender() << LL_ENDL;
- return;
- }
- else if (cdp->getTrusted())
- {
- // The digest is bad, but this circuit is already trusted.
- // This means that this could just be the result of a stale deny sent from a while back, and
- // the message system is being slow. Don't bother sending the deny, as it may continually
- // ping-pong back and forth on a very hosed circuit.
- LL_WARNS("Messaging") << "Ignoring bad digest from known trusted circuit: " << their_digest
- << " host: " << msg->getSender() << LL_ENDL;
- return;
- }
- else
- {
- LL_WARNS("Messaging") << "Bad digest from known circuit: " << their_digest
- << " host: " << msg->getSender() << LL_ENDL;
- msg->sendDenyTrustedCircuit(msg->getSender());
- return;
- }
-}
-
-void process_deny_trusted_circuit(LLMessageSystem *msg, void **)
-{
- // don't try to create trust on machines with no shared secret
- std::string shared_secret = get_shared_secret();
- if(shared_secret.empty()) return;
-
- LLUUID remote_id;
- msg->getUUIDFast(_PREHASH_DataBlock, _PREHASH_EndPointID, remote_id);
-
- LLCircuitData *cdp = msg->mCircuitInfo.findCircuit(msg->getSender());
- if (!cdp)
- {
- return;
- }
-
- LLUUID local_id;
- local_id = cdp->getLocalEndPointID();
- if (remote_id == local_id)
- {
- // Don't respond to requests that use the same end point ID
- return;
- }
-
- U32 untrusted_interface = msg->getUntrustedInterface().getAddress();
- U32 last_interface = msg->getReceivingInterface().getAddress();
- if ( ( untrusted_interface != INVALID_HOST_IP_ADDRESS ) && ( untrusted_interface == last_interface ) )
- {
- if( msg->getBlockUntrustedInterface() )
- {
- LL_WARNS("Messaging") << "Ignoring DenyTrustedCircuit on public interface from host: "
- << msg->getSender() << LL_ENDL;
- return;
- }
- else
- {
- LL_WARNS("Messaging") << "Processing DenyTrustedCircuit on public interface from host: "
- << msg->getSender() << LL_ENDL;
- }
- }
-
-
- // Assume that we require trust to proceed, so resend.
- // This catches the case where a circuit that was trusted
- // times out, and allows us to re-establish it, but does
- // mean that if our shared_secret or clock is wrong, we'll
- // spin.
- // *TODO: probably should keep a count of number of resends
- // per circuit, and stop resending after a while.
- LL_INFOS("Messaging") << "Got DenyTrustedCircuit. Sending CreateTrustedCircuit to "
- << msg->getSender() << LL_ENDL;
- msg->sendCreateTrustedCircuit(msg->getSender(), local_id, remote_id);
-}
-
-
-void dump_prehash_files()
-{
- U32 i;
- std::string filename("../../indra/llmessage/message_prehash.h");
- LLFILE* fp = LLFile::fopen(filename, "w"); /* Flawfinder: ignore */
- if (fp)
- {
- fprintf(
- fp,
- "/**\n"
- " * @file message_prehash.h\n"
- " * @brief header file of externs of prehashed variables plus defines.\n"
- " *\n"
- " * $LicenseInfo:firstyear=2003&license=viewerlgpl$"
- " * $/LicenseInfo$"
- " */\n\n"
- "#ifndef LL_MESSAGE_PREHASH_H\n#define LL_MESSAGE_PREHASH_H\n\n");
- fprintf(
- fp,
- "/**\n"
- " * Generated from message template version number %.3f\n"
- " */\n",
- gMessageSystem->mMessageFileVersionNumber);
- fprintf(fp, "\n\nextern F32 const gPrehashVersionNumber;\n\n");
- for (i = 0; i < MESSAGE_NUMBER_OF_HASH_BUCKETS; i++)
- {
- if (!LLMessageStringTable::getInstance()->mEmpty[i] && LLMessageStringTable::getInstance()->mString[i][0] != '.')
- {
- fprintf(fp, "extern char const* const _PREHASH_%s;\n", LLMessageStringTable::getInstance()->mString[i]);
- }
- }
- fprintf(fp, "\n\n#endif\n");
- fclose(fp);
- }
- filename = std::string("../../indra/llmessage/message_prehash.cpp");
- fp = LLFile::fopen(filename, "w"); /* Flawfinder: ignore */
- if (fp)
- {
- fprintf(
- fp,
- "/**\n"
- " * @file message_prehash.cpp\n"
- " * @brief file of prehashed variables\n"
- " *\n"
- " * $LicenseInfo:firstyear=2003&license=viewerlgpl$"
- " * $/LicenseInfo$"
- " */\n\n"
- "/**\n"
- " * Generated from message template version number %.3f\n"
- " */\n",
- gMessageSystem->mMessageFileVersionNumber);
- fprintf(fp, "#include \"linden_common.h\"\n");
- fprintf(fp, "#include \"message.h\"\n\n");
- fprintf(fp, "\n\nF32 const gPrehashVersionNumber = %.3ff;\n\n", gMessageSystem->mMessageFileVersionNumber);
- for (i = 0; i < MESSAGE_NUMBER_OF_HASH_BUCKETS; i++)
- {
- if (!LLMessageStringTable::getInstance()->mEmpty[i] && LLMessageStringTable::getInstance()->mString[i][0] != '.')
- {
- fprintf(fp, "char const* const _PREHASH_%s = LLMessageStringTable::getInstance()->getString(\"%s\");\n", LLMessageStringTable::getInstance()->mString[i], LLMessageStringTable::getInstance()->mString[i]);
- }
- }
- fclose(fp);
- }
-}
-
-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,
- const LLUseCircuitCodeResponder* responder,
- bool failure_is_fatal,
- const F32 circuit_heartbeat_interval,
- const F32 circuit_timeout)
-{
- gMessageSystem = new LLMessageSystem(
- template_name,
- port,
- version_major,
- version_minor,
- version_patch,
- failure_is_fatal,
- circuit_heartbeat_interval,
- circuit_timeout);
- g_shared_secret.assign(secret);
-
- if (!gMessageSystem)
- {
- LL_ERRS("AppInit") << "Messaging system initialization failed." << LL_ENDL;
- return false;
- }
-
- // bail if system encountered an error.
- if(!gMessageSystem->isOK())
- {
- return false;
- }
-
- if (b_dump_prehash_file)
- {
- dump_prehash_files();
- exit(0);
- }
- else
- {
- if (gMessageSystem->mMessageFileVersionNumber != gPrehashVersionNumber)
- {
- LL_INFOS("AppInit") << "Message template version does not match prehash version number" << LL_ENDL;
- LL_INFOS("AppInit") << "Run simulator with -prehash command line option to rebuild prehash data" << LL_ENDL;
- }
- else
- {
- LL_DEBUGS("AppInit") << "Message template version matches prehash version number" << LL_ENDL;
- }
- }
-
- gMessageSystem->setHandlerFuncFast(_PREHASH_StartPingCheck, process_start_ping_check, NULL);
- gMessageSystem->setHandlerFuncFast(_PREHASH_CompletePingCheck, process_complete_ping_check, NULL);
- gMessageSystem->setHandlerFuncFast(_PREHASH_OpenCircuit, open_circuit, NULL);
- gMessageSystem->setHandlerFuncFast(_PREHASH_CloseCircuit, close_circuit, NULL);
-
- //gMessageSystem->setHandlerFuncFast(_PREHASH_AssignCircuitCode, LLMessageSystem::processAssignCircuitCode);
- gMessageSystem->setHandlerFuncFast(_PREHASH_AddCircuitCode, LLMessageSystem::processAddCircuitCode);
- //gMessageSystem->setHandlerFuncFast(_PREHASH_AckAddCircuitCode, ack_add_circuit_code, NULL);
- gMessageSystem->setHandlerFuncFast(_PREHASH_UseCircuitCode, LLMessageSystem::processUseCircuitCode, (void**)responder);
- gMessageSystem->setHandlerFuncFast(_PREHASH_PacketAck, process_packet_ack, NULL);
- //gMessageSystem->setHandlerFuncFast(_PREHASH_LogMessages, process_log_messages, NULL);
- gMessageSystem->setHandlerFuncFast(_PREHASH_CreateTrustedCircuit,
- process_create_trusted_circuit,
- NULL);
- gMessageSystem->setHandlerFuncFast(_PREHASH_DenyTrustedCircuit,
- process_deny_trusted_circuit,
- NULL);
- gMessageSystem->setHandlerFunc("Error", LLMessageSystem::processError);
-
- // We can hand this to the null_message_callback since it is a
- // trusted message, so it will automatically be denied if it isn't
- // trusted and ignored if it is -- exactly what we want.
- gMessageSystem->setHandlerFunc(
- "RequestTrustedCircuit",
- null_message_callback,
- NULL);
-
- // Initialize the transfer manager
- gTransferManager.init();
-
- return true;
-}
-
-void LLMessageSystem::startLogging()
-{
- mVerboseLog = true;
- std::ostringstream str;
- str << "START MESSAGE LOG" << std::endl;
- str << "Legend:" << std::endl;
- str << "\t<-\tincoming message" <<std::endl;
- str << "\t->\toutgoing message" << std::endl;
- str << " <> host size zero id name";
- LL_INFOS("Messaging") << str.str() << LL_ENDL;
-}
-
-void LLMessageSystem::stopLogging()
-{
- if(mVerboseLog)
- {
- mVerboseLog = false;
- LL_INFOS("Messaging") << "END MESSAGE LOG" << LL_ENDL;
- }
-}
-
-void LLMessageSystem::summarizeLogs(std::ostream& str)
-{
- std::string buffer;
- std::string tmp_str;
- F32 run_time = mMessageSystemTimer.getElapsedTimeF32();
- str << "START MESSAGE LOG SUMMARY" << std::endl;
- buffer = llformat( "Run time: %12.3f seconds", run_time);
-
- // Incoming
- str << buffer << std::endl << "Incoming:" << std::endl;
- tmp_str = U64_to_str(mTotalBytesIn);
- buffer = llformat( "Total bytes received: %20s (%5.2f kbits per second)", tmp_str.c_str(), ((F32)mTotalBytesIn * 0.008f) / run_time);
- str << buffer << std::endl;
- tmp_str = U64_to_str(mPacketsIn);
- buffer = llformat( "Total packets received: %20s (%5.2f packets per second)", tmp_str.c_str(), ((F32) mPacketsIn / run_time));
- str << buffer << std::endl;
- buffer = llformat( "Average packet size: %20.0f bytes", (F32)mTotalBytesIn / (F32)mPacketsIn);
- str << buffer << std::endl;
- tmp_str = U64_to_str(mReliablePacketsIn);
- buffer = llformat( "Total reliable packets: %20s (%5.2f%%)", tmp_str.c_str(), 100.f * ((F32) mReliablePacketsIn)/((F32) mPacketsIn + 1));
- str << buffer << std::endl;
- tmp_str = U64_to_str(mCompressedPacketsIn);
- buffer = llformat( "Total compressed packets: %20s (%5.2f%%)", tmp_str.c_str(), 100.f * ((F32) mCompressedPacketsIn)/((F32) mPacketsIn + 1));
- str << buffer << std::endl;
- S64 savings = mUncompressedBytesIn - mCompressedBytesIn;
- tmp_str = U64_to_str(savings);
- buffer = llformat( "Total compression savings: %20s bytes", tmp_str.c_str());
- str << buffer << std::endl;
- tmp_str = U64_to_str(savings/(mCompressedPacketsIn +1));
- buffer = llformat( "Avg comp packet savings: %20s (%5.2f : 1)", tmp_str.c_str(), ((F32) mUncompressedBytesIn)/((F32) mCompressedBytesIn+1));
- str << buffer << std::endl;
- tmp_str = U64_to_str(savings/(mPacketsIn+1));
- buffer = llformat( "Avg overall comp savings: %20s (%5.2f : 1)", tmp_str.c_str(), ((F32) mTotalBytesIn + (F32) savings)/((F32) mTotalBytesIn + 1.f));
-
- // Outgoing
- str << buffer << std::endl << std::endl << "Outgoing:" << std::endl;
- tmp_str = U64_to_str(mTotalBytesOut);
- buffer = llformat( "Total bytes sent: %20s (%5.2f kbits per second)", tmp_str.c_str(), ((F32)mTotalBytesOut * 0.008f) / run_time );
- str << buffer << std::endl;
- tmp_str = U64_to_str(mPacketsOut);
- buffer = llformat( "Total packets sent: %20s (%5.2f packets per second)", tmp_str.c_str(), ((F32)mPacketsOut / run_time));
- str << buffer << std::endl;
- buffer = llformat( "Average packet size: %20.0f bytes", (F32)mTotalBytesOut / (F32)mPacketsOut);
- str << buffer << std::endl;
- tmp_str = U64_to_str(mReliablePacketsOut);
- buffer = llformat( "Total reliable packets: %20s (%5.2f%%)", tmp_str.c_str(), 100.f * ((F32) mReliablePacketsOut)/((F32) mPacketsOut + 1));
- str << buffer << std::endl;
- tmp_str = U64_to_str(mCompressedPacketsOut);
- buffer = llformat( "Total compressed packets: %20s (%5.2f%%)", tmp_str.c_str(), 100.f * ((F32) mCompressedPacketsOut)/((F32) mPacketsOut + 1));
- str << buffer << std::endl;
- savings = mUncompressedBytesOut - mCompressedBytesOut;
- tmp_str = U64_to_str(savings);
- buffer = llformat( "Total compression savings: %20s bytes", tmp_str.c_str());
- str << buffer << std::endl;
- tmp_str = U64_to_str(savings/(mCompressedPacketsOut +1));
- buffer = llformat( "Avg comp packet savings: %20s (%5.2f : 1)", tmp_str.c_str(), ((F32) mUncompressedBytesOut)/((F32) mCompressedBytesOut+1));
- str << buffer << std::endl;
- tmp_str = U64_to_str(savings/(mPacketsOut+1));
- buffer = llformat( "Avg overall comp savings: %20s (%5.2f : 1)", tmp_str.c_str(), ((F32) mTotalBytesOut + (F32) savings)/((F32) mTotalBytesOut + 1.f));
- str << buffer << std::endl << std::endl;
- buffer = llformat( "SendPacket failures: %20d", mSendPacketFailureCount);
- str << buffer << std::endl;
- buffer = llformat( "Dropped packets: %20d", mDroppedPackets);
- str << buffer << std::endl;
- buffer = llformat( "Resent packets: %20d", mResentPackets);
- str << buffer << std::endl;
- buffer = llformat( "Failed reliable resends: %20d", mFailedResendPackets);
- str << buffer << std::endl;
- buffer = llformat( "Off-circuit rejected packets: %17d", mOffCircuitPackets);
- str << buffer << std::endl;
- buffer = llformat( "On-circuit invalid packets: %17d", mInvalidOnCircuitPackets);
- str << buffer << std::endl << std::endl;
-
- str << "Decoding: " << std::endl;
- buffer = llformat( "%35s%10s%10s%10s%10s", "Message", "Count", "Time", "Max", "Avg");
- str << buffer << std:: endl;
- F32 avg;
- for (message_template_name_map_t::const_iterator iter = mMessageTemplates.begin(),
- end = mMessageTemplates.end();
- iter != end; iter++)
- {
- const LLMessageTemplate* mt = iter->second;
- if(mt->mTotalDecoded > 0)
- {
- avg = mt->mTotalDecodeTime / (F32)mt->mTotalDecoded;
- buffer = llformat( "%35s%10u%10f%10f%10f", mt->mName, mt->mTotalDecoded, mt->mTotalDecodeTime, mt->mMaxDecodeTimePerMsg, avg);
- str << buffer << std::endl;
- }
- }
- str << "END MESSAGE LOG SUMMARY" << std::endl;
-}
-
-void end_messaging_system(bool print_summary)
-{
- gTransferManager.cleanup();
- LLTransferTargetVFile::updateQueue(true); // shutdown LLTransferTargetVFile
- if (gMessageSystem)
- {
- gMessageSystem->stopLogging();
-
- if (print_summary)
- {
- std::ostringstream str;
- gMessageSystem->summarizeLogs(str);
- LL_INFOS("Messaging") << str.str().c_str() << LL_ENDL;
- }
-
- delete static_cast<LLMessageSystem*>(gMessageSystem);
- gMessageSystem = NULL;
- }
-}
-
-void LLMessageSystem::resetReceiveCounts()
-{
- mNumMessageCounts = 0;
-
- for (message_template_name_map_t::iterator iter = mMessageTemplates.begin(),
- end = mMessageTemplates.end();
- iter != end; iter++)
- {
- LLMessageTemplate* mt = iter->second;
- mt->mDecodeTimeThisFrame = 0.f;
- }
-}
-
-
-void LLMessageSystem::dumpReceiveCounts()
-{
- LLMessageTemplate *mt;
-
- for (message_template_name_map_t::iterator iter = mMessageTemplates.begin(),
- end = mMessageTemplates.end();
- iter != end; iter++)
- {
- LLMessageTemplate* mt = iter->second;
- mt->mReceiveCount = 0;
- mt->mReceiveBytes = 0;
- mt->mReceiveInvalid = 0;
- }
-
- S32 i;
- for (i = 0; i < mNumMessageCounts; i++)
- {
- mt = get_ptr_in_map(mMessageNumbers,mMessageCountList[i].mMessageNum);
- if (mt)
- {
- mt->mReceiveCount++;
- mt->mReceiveBytes += mMessageCountList[i].mMessageBytes;
- if (mMessageCountList[i].mInvalid)
- {
- mt->mReceiveInvalid++;
- }
- }
- }
-
- if(mNumMessageCounts > 0)
- {
- LL_DEBUGS("Messaging") << "Dump: " << mNumMessageCounts << " messages processed in " << mReceiveTime << " seconds" << LL_ENDL;
- for (message_template_name_map_t::const_iterator iter = mMessageTemplates.begin(),
- end = mMessageTemplates.end();
- iter != end; iter++)
- {
- const LLMessageTemplate* mt = iter->second;
- if (mt->mReceiveCount > 0)
- {
- LL_INFOS("Messaging") << "Num: " << std::setw(3) << mt->mReceiveCount << " Bytes: " << std::setw(6) << mt->mReceiveBytes
- << " Invalid: " << std::setw(3) << mt->mReceiveInvalid << " " << mt->mName << " " << ll_round(100 * mt->mDecodeTimeThisFrame / mReceiveTime.value()) << "%" << LL_ENDL;
- }
- }
- }
-}
-
-
-
-bool LLMessageSystem::isClear() const
-{
- return mMessageBuilder->isClear();
-}
-
-
-S32 LLMessageSystem::flush(const LLHost &host)
-{
- if (mMessageBuilder->getMessageSize())
- {
- S32 sentbytes = sendMessage(host);
- clearMessage();
- return sentbytes;
- }
- else
- {
- return 0;
- }
-}
-
-U32 LLMessageSystem::getListenPort( void ) const
-{
- return mPort;
-}
-
-// TODO: babbage: remove this horror!
-S32 LLMessageSystem::zeroCodeAdjustCurrentSendTotal()
-{
- if(mMessageBuilder == mLLSDMessageBuilder)
- {
- // babbage: don't compress LLSD messages, so delta is 0
- return 0;
- }
-
- if (! mMessageBuilder->isBuilt())
- {
- mSendSize = mMessageBuilder->buildMessage(
- mSendBuffer,
- MAX_BUFFER_SIZE,
- 0);
- }
- // TODO: babbage: remove this horror
- mMessageBuilder->setBuilt(false);
-
- S32 count = mSendSize;
-
- S32 net_gain = 0;
- U8 num_zeroes = 0;
-
- U8 *inptr = (U8 *)mSendBuffer;
-
-// skip the packet id field
-
- for (U32 ii = 0; ii < LL_PACKET_ID_SIZE; ++ii)
- {
- count--;
- inptr++;
- }
-
-// don't actually build, just test
-
-// sequential zero bytes are encoded as 0 [U8 count]
-// with 0 0 [count] representing wrap (>256 zeroes)
-
- while (count--)
- {
- if (!(*inptr)) // in a zero count
- {
- if (num_zeroes)
- {
- if (++num_zeroes > 254)
- {
- num_zeroes = 0;
- }
- net_gain--; // subseqent zeroes save one
- }
- else
- {
- net_gain++; // starting a zero count adds one
- num_zeroes = 1;
- }
- inptr++;
- }
- else
- {
- if (num_zeroes)
- {
- num_zeroes = 0;
- }
- inptr++;
- }
- }
- if (net_gain < 0)
- {
- return net_gain;
- }
- else
- {
- return 0;
- }
-}
-
-
-
-S32 LLMessageSystem::zeroCodeExpand(U8** data, S32* data_size)
-{
- if ((*data_size ) < LL_MINIMUM_VALID_PACKET_SIZE)
- {
- LL_WARNS("Messaging") << "zeroCodeExpand() called with data_size of " << *data_size
- << LL_ENDL;
- }
-
- mTotalBytesIn += *data_size;
-
- // if we're not zero-coded, simply return.
- if (!(*data[0] & LL_ZERO_CODE_FLAG))
- {
- return 0;
- }
-
- S32 in_size = *data_size;
- mCompressedPacketsIn++;
- mCompressedBytesIn += *data_size;
-
- *data[0] &= (~LL_ZERO_CODE_FLAG);
-
- S32 count = (*data_size);
-
- U8 *inptr = (U8 *)*data;
- U8 *outptr = (U8 *)mEncodedRecvBuffer;
-
-// skip the packet id field
-
- for (U32 ii = 0; ii < LL_PACKET_ID_SIZE; ++ii)
- {
- count--;
- *outptr++ = *inptr++;
- }
-
-// reconstruct encoded packet, keeping track of net size gain
-
-// sequential zero bytes are encoded as 0 [U8 count]
-// with 0 0 [count] representing wrap (>256 zeroes)
-
- while (count--)
- {
- if (outptr > (&mEncodedRecvBuffer[MAX_BUFFER_SIZE-1]))
- {
- LL_WARNS("Messaging") << "attempt to write past reasonable encoded buffer size 1" << LL_ENDL;
- callExceptionFunc(MX_WROTE_PAST_BUFFER_SIZE);
- outptr = mEncodedRecvBuffer;
- break;
- }
- if (!((*outptr++ = *inptr++)))
- {
- while (((count--)) && (!(*inptr)))
- {
- *outptr++ = *inptr++;
- if (outptr > (&mEncodedRecvBuffer[MAX_BUFFER_SIZE-256]))
- {
- LL_WARNS("Messaging") << "attempt to write past reasonable encoded buffer size 2" << LL_ENDL;
- callExceptionFunc(MX_WROTE_PAST_BUFFER_SIZE);
- outptr = mEncodedRecvBuffer;
- count = -1;
- break;
- }
- memset(outptr,0,255);
- outptr += 255;
- }
-
- if (count < 0)
- {
- break;
- }
-
- else
- {
- if (outptr > (&mEncodedRecvBuffer[MAX_BUFFER_SIZE-(*inptr)]))
- {
- LL_WARNS("Messaging") << "attempt to write past reasonable encoded buffer size 3" << LL_ENDL;
- callExceptionFunc(MX_WROTE_PAST_BUFFER_SIZE);
- outptr = mEncodedRecvBuffer;
- }
- memset(outptr,0,(*inptr) - 1);
- outptr += ((*inptr) - 1);
- inptr++;
- }
- }
- }
-
- *data = mEncodedRecvBuffer;
- *data_size = (S32)(outptr - mEncodedRecvBuffer);
- mUncompressedBytesIn += *data_size;
-
- return(in_size);
-}
-
-
-void LLMessageSystem::addTemplate(LLMessageTemplate *templatep)
-{
- if (mMessageTemplates.count(templatep->mName) > 0)
- {
- LL_ERRS("Messaging") << templatep->mName << " already used as a template name!"
- << LL_ENDL;
- }
- mMessageTemplates[templatep->mName] = templatep;
- mMessageNumbers[templatep->mMessageNumber] = templatep;
-}
-
-
-void LLMessageSystem::setHandlerFuncFast(const char *name, void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data)
-{
- LLMessageTemplate* msgtemplate = get_ptr_in_map(mMessageTemplates, name);
- if (msgtemplate)
- {
- msgtemplate->setHandlerFunc(handler_func, user_data);
- }
- else
- {
- LL_ERRS("Messaging") << name << " is not a known message name!" << LL_ENDL;
- }
-}
-
-bool LLMessageSystem::callHandler(const char *name,
- bool trustedSource, LLMessageSystem* msg)
-{
- name = LLMessageStringTable::getInstance()->getString(name);
- message_template_name_map_t::const_iterator iter;
- iter = mMessageTemplates.find(name);
- if(iter == mMessageTemplates.end())
- {
- LL_WARNS("Messaging") << "LLMessageSystem::callHandler: unknown message "
- << name << LL_ENDL;
- return false;
- }
-
- const LLMessageTemplate* msg_template = iter->second;
- if (msg_template->isBanned(trustedSource))
- {
- LL_WARNS("Messaging") << "LLMessageSystem::callHandler: banned message "
- << name
- << " from "
- << (trustedSource ? "trusted " : "untrusted ")
- << "source" << LL_ENDL;
- return false;
- }
-
- return msg_template->callHandlerFunc(msg);
-}
-
-
-void LLMessageSystem::setExceptionFunc(EMessageException e,
- msg_exception_callback func,
- void* data)
-{
- callbacks_t::iterator it = mExceptionCallbacks.find(e);
- if(it != mExceptionCallbacks.end())
- {
- mExceptionCallbacks.erase(it);
- }
- if(func)
- {
- mExceptionCallbacks.insert(callbacks_t::value_type(e, exception_t(func, data)));
- }
-}
-
-bool LLMessageSystem::callExceptionFunc(EMessageException exception)
-{
- callbacks_t::iterator it = mExceptionCallbacks.find(exception);
- if(it == mExceptionCallbacks.end())
- {
- return false;
- }
-
- exception_t& ex = it->second;
- msg_exception_callback ex_cb = ex.first;
-
- if (!ex_cb)
- {
- LL_WARNS("Messaging") << "LLMessageSystem::callExceptionFunc: bad message exception callback." << LL_ENDL;
- return false;
- }
-
- (ex_cb)(this, ex.second, exception);
-
- return true;
-}
-
-void LLMessageSystem::setTimingFunc(msg_timing_callback func, void* data)
-{
- mTimingCallback = func;
- mTimingCallbackData = data;
-}
-
-bool LLMessageSystem::isCircuitCodeKnown(U32 code) const
-{
- if(mCircuitCodes.find(code) == mCircuitCodes.end())
- return false;
- return true;
-}
-
-bool LLMessageSystem::isMessageFast(const char *msg)
-{
- return msg == mMessageReader->getMessageName();
-}
-
-
-char* LLMessageSystem::getMessageName()
-{
- return const_cast<char*>(mMessageReader->getMessageName());
-}
-
-const LLUUID& LLMessageSystem::getSenderID() const
-{
- LLCircuitData *cdp = mCircuitInfo.findCircuit(mLastSender);
- if (cdp)
- {
- return (cdp->mRemoteID);
- }
-
- return LLUUID::null;
-}
-
-const LLUUID& LLMessageSystem::getSenderSessionID() const
-{
- LLCircuitData *cdp = mCircuitInfo.findCircuit(mLastSender);
- if (cdp)
- {
- return (cdp->mRemoteSessionID);
- }
- return LLUUID::null;
-}
-
-bool LLMessageSystem::generateDigestForNumberAndUUIDs(
- char* digest,
- const U32 number,
- const LLUUID& id1,
- const LLUUID& id2) const
-{
- // *NOTE: This method is needlessly inefficient. Instead of
- // calling LLUUID::asString, it should just call
- // LLUUID::toString().
-
- const char *colon = ":";
- char tbuf[16]; /* Flawfinder: ignore */
- LLMD5 d;
- std::string id1string = id1.asString();
- std::string id2string = id2.asString();
- std::string shared_secret = get_shared_secret();
- unsigned char * secret = (unsigned char*)shared_secret.c_str();
- unsigned char * id1str = (unsigned char*)id1string.c_str();
- unsigned char * id2str = (unsigned char*)id2string.c_str();
-
- memset(digest, 0, MD5HEX_STR_SIZE);
-
- if( secret != NULL)
- {
- d.update(secret, (U32)strlen((char *) secret)); /* Flawfinder: ignore */
- }
-
- d.update((const unsigned char *) colon, (U32)strlen(colon)); /* Flawfinder: ignore */
-
- snprintf(tbuf, sizeof(tbuf),"%i", number); /* Flawfinder: ignore */
- d.update((unsigned char *) tbuf, (U32)strlen(tbuf)); /* Flawfinder: ignore */
-
- d.update((const unsigned char *) colon, (U32)strlen(colon)); /* Flawfinder: ignore */
- if( (char*) id1str != NULL)
- {
- d.update(id1str, (U32)strlen((char *) id1str)); /* Flawfinder: ignore */
- }
- d.update((const unsigned char *) colon, (U32)strlen(colon)); /* Flawfinder: ignore */
-
- if( (char*) id2str != NULL)
- {
- d.update(id2str, (U32)strlen((char *) id2str)); /* Flawfinder: ignore */
- }
-
- d.finalize();
- d.hex_digest(digest);
- digest[MD5HEX_STR_SIZE - 1] = '\0';
-
- return true;
-}
-
-bool LLMessageSystem::generateDigestForWindowAndUUIDs(char* digest, const S32 window, const LLUUID &id1, const LLUUID &id2) const
-{
- if(0 == window) return false;
- std::string shared_secret = get_shared_secret();
- if(shared_secret.empty())
- {
- LL_ERRS("Messaging") << "Trying to generate complex digest on a machine without a shared secret!" << LL_ENDL;
- }
-
- U32 now = (U32)time(NULL);
-
- now /= window;
-
- bool result = generateDigestForNumberAndUUIDs(digest, now, id1, id2);
-
- return result;
-}
-
-bool LLMessageSystem::isMatchingDigestForWindowAndUUIDs(const char* digest, const S32 window, const LLUUID &id1, const LLUUID &id2) const
-{
- if(0 == window) return false;
-
- std::string shared_secret = get_shared_secret();
- if(shared_secret.empty())
- {
- LL_ERRS("Messaging") << "Trying to compare complex digests on a machine without a shared secret!" << LL_ENDL;
- }
-
- char our_digest[MD5HEX_STR_SIZE]; /* Flawfinder: ignore */
- U32 now = (U32)time(NULL);
-
- now /= window;
-
- // Check 1 window ago, now, and one window from now to catch edge
- // conditions. Process them as current window, one window ago, and
- // one window in the future to catch the edges.
- const S32 WINDOW_BIN_COUNT = 3;
- U32 window_bin[WINDOW_BIN_COUNT];
- window_bin[0] = now;
- window_bin[1] = now - 1;
- window_bin[2] = now + 1;
- for(S32 i = 0; i < WINDOW_BIN_COUNT; ++i)
- {
- generateDigestForNumberAndUUIDs(our_digest, window_bin[i], id2, id1);
- if(0 == strncmp(digest, our_digest, MD5HEX_STR_BYTES))
- {
- return true;
- }
- }
- return false;
-}
-
-bool LLMessageSystem::generateDigestForNumber(char* digest, const U32 number) const
-{
- memset(digest, 0, MD5HEX_STR_SIZE);
-
- LLMD5 d;
- std::string shared_secret = get_shared_secret();
- d = LLMD5((const unsigned char *)shared_secret.c_str(), number);
- d.hex_digest(digest);
- digest[MD5HEX_STR_SIZE - 1] = '\0';
-
- return true;
-}
-
-bool LLMessageSystem::generateDigestForWindow(char* digest, const S32 window) const
-{
- if(0 == window) return false;
-
- std::string shared_secret = get_shared_secret();
- if(shared_secret.empty())
- {
- LL_ERRS("Messaging") << "Trying to generate simple digest on a machine without a shared secret!" << LL_ENDL;
- }
-
- U32 now = (U32)time(NULL);
-
- now /= window;
-
- bool result = generateDigestForNumber(digest, now);
-
- return result;
-}
-
-bool LLMessageSystem::isMatchingDigestForWindow(const char* digest, S32 const window) const
-{
- if(0 == window) return false;
-
- std::string shared_secret = get_shared_secret();
- if(shared_secret.empty())
- {
- LL_ERRS("Messaging") << "Trying to compare simple digests on a machine without a shared secret!" << LL_ENDL;
- }
-
- char our_digest[MD5HEX_STR_SIZE]; /* Flawfinder: ignore */
- U32 now = (S32)time(NULL);
-
- now /= window;
-
- // Check 1 window ago, now, and one window from now to catch edge
- // conditions. Process them as current window, one window ago, and
- // one window in the future to catch the edges.
- const S32 WINDOW_BIN_COUNT = 3;
- U32 window_bin[WINDOW_BIN_COUNT];
- window_bin[0] = now;
- window_bin[1] = now - 1;
- window_bin[2] = now + 1;
- for(S32 i = 0; i < WINDOW_BIN_COUNT; ++i)
- {
- generateDigestForNumber(our_digest, window_bin[i]);
- if(0 == strncmp(digest, our_digest, MD5HEX_STR_BYTES))
- {
- return true;
- }
- }
- return false;
-}
-
-void LLMessageSystem::sendCreateTrustedCircuit(const LLHost &host, const LLUUID & id1, const LLUUID & id2)
-{
- std::string shared_secret = get_shared_secret();
- if(shared_secret.empty()) return;
- char digest[MD5HEX_STR_SIZE]; /* Flawfinder: ignore */
- if (id1.isNull())
- {
- LL_WARNS("Messaging") << "Can't send CreateTrustedCircuit to " << host << " because we don't have the local end point ID" << LL_ENDL;
- return;
- }
- if (id2.isNull())
- {
- LL_WARNS("Messaging") << "Can't send CreateTrustedCircuit to " << host << " because we don't have the remote end point ID" << LL_ENDL;
- return;
- }
- generateDigestForWindowAndUUIDs(digest, TRUST_TIME_WINDOW, id1, id2);
- newMessageFast(_PREHASH_CreateTrustedCircuit);
- nextBlockFast(_PREHASH_DataBlock);
- addUUIDFast(_PREHASH_EndPointID, id1);
- addBinaryDataFast(_PREHASH_Digest, digest, MD5HEX_STR_BYTES);
- LL_INFOS("Messaging") << "xmitting digest: " << digest << " Host: " << host << LL_ENDL;
- sendMessage(host);
-}
-
-void LLMessageSystem::sendDenyTrustedCircuit(const LLHost &host)
-{
- mDenyTrustedCircuitSet.insert(host);
-}
-
-void LLMessageSystem::reallySendDenyTrustedCircuit(const LLHost &host)
-{
- LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
- if (!cdp)
- {
- LL_WARNS("Messaging") << "Not sending DenyTrustedCircuit to host without a circuit." << LL_ENDL;
- return;
- }
- LL_INFOS("Messaging") << "Sending DenyTrustedCircuit to " << host << LL_ENDL;
- newMessageFast(_PREHASH_DenyTrustedCircuit);
- nextBlockFast(_PREHASH_DataBlock);
- addUUIDFast(_PREHASH_EndPointID, cdp->getLocalEndPointID());
- sendMessage(host);
-}
-
-void null_message_callback(LLMessageSystem *msg, void **data)
-{
- // Nothing should ever go here, but we use this to register messages
- // that we are expecting to see (and spinning on) at startup.
- return;
-}
-
-// Try to establish a bidirectional trust metric by pinging a host until it's
-// up, and then sending auth messages.
-void LLMessageSystem::establishBidirectionalTrust(const LLHost &host, S64 frame_count )
-{
- LockMessageChecker lmc(this);
-
- std::string shared_secret = get_shared_secret();
- if(shared_secret.empty())
- {
- LL_ERRS("Messaging") << "Trying to establish bidirectional trust on a machine without a shared secret!" << LL_ENDL;
- }
- LLTimer timeout;
-
- timeout.setTimerExpirySec(20.0);
- setHandlerFuncFast(_PREHASH_StartPingCheck, null_message_callback, NULL);
- setHandlerFuncFast(_PREHASH_CompletePingCheck, null_message_callback,
- NULL);
-
- while (! timeout.hasExpired())
- {
- newMessageFast(_PREHASH_StartPingCheck);
- nextBlockFast(_PREHASH_PingID);
- addU8Fast(_PREHASH_PingID, 0);
- addU32Fast(_PREHASH_OldestUnacked, 0);
- sendMessage(host);
- if (lmc.checkMessages( frame_count ))
- {
- if (isMessageFast(_PREHASH_CompletePingCheck) &&
- (getSender() == host))
- {
- break;
- }
- }
- lmc.processAcks();
- ms_sleep(1);
- }
-
- // Send a request, a deny, and give the host 2 seconds to complete
- // the trust handshake.
- newMessage("RequestTrustedCircuit");
- sendMessage(host);
- reallySendDenyTrustedCircuit(host);
- setHandlerFuncFast(_PREHASH_StartPingCheck, process_start_ping_check, NULL);
- setHandlerFuncFast(_PREHASH_CompletePingCheck, process_complete_ping_check, NULL);
-
- timeout.setTimerExpirySec(2.0);
- LLCircuitData* cdp = NULL;
- while(!timeout.hasExpired())
- {
- cdp = mCircuitInfo.findCircuit(host);
- if(!cdp) break; // no circuit anymore, no point continuing.
- if(cdp->getTrusted()) break; // circuit is trusted.
- lmc.checkMessages(frame_count);
- lmc.processAcks();
- ms_sleep(1);
- }
-}
-
-
-void LLMessageSystem::dumpPacketToLog()
-{
- LL_WARNS("Messaging") << "Packet Dump from:" << mPacketRing.getLastSender() << LL_ENDL;
- LL_WARNS("Messaging") << "Packet Size:" << mTrueReceiveSize << LL_ENDL;
- char line_buffer[256]; /* Flawfinder: ignore */
- S32 i;
- S32 cur_line_pos = 0;
- S32 cur_line = 0;
-
- for (i = 0; i < mTrueReceiveSize; i++)
- {
- S32 offset = cur_line_pos * 3;
- snprintf(line_buffer + offset, sizeof(line_buffer) - offset,
- "%02x ", mTrueReceiveBuffer[i]); /* Flawfinder: ignore */
- cur_line_pos++;
- if (cur_line_pos >= 16)
- {
- cur_line_pos = 0;
- LL_WARNS("Messaging") << "PD:" << cur_line << "PD:" << line_buffer << LL_ENDL;
- cur_line++;
- }
- }
- if (cur_line_pos)
- {
- LL_WARNS("Messaging") << "PD:" << cur_line << "PD:" << line_buffer << LL_ENDL;
- }
-}
-
-
-//static
-U64Microseconds LLMessageSystem::getMessageTimeUsecs(const bool update)
-{
- if (gMessageSystem)
- {
- if (update)
- {
- gMessageSystem->mCurrentMessageTime = totalTime();
- }
- return gMessageSystem->mCurrentMessageTime;
- }
- else
- {
- return totalTime();
- }
-}
-
-//static
-F64Seconds LLMessageSystem::getMessageTimeSeconds(const bool update)
-{
- if (gMessageSystem)
- {
- if (update)
- {
- gMessageSystem->mCurrentMessageTime = totalTime();
- }
- return gMessageSystem->mCurrentMessageTime;
- }
- else
- {
- return F64Seconds(totalTime());
- }
-}
-
-std::string get_shared_secret()
-{
- static const std::string SHARED_SECRET_KEY("shared_secret");
- if(g_shared_secret.empty())
- {
- LLApp* app = LLApp::instance();
- if(app) return app->getOption(SHARED_SECRET_KEY);
- }
- return g_shared_secret;
-}
-
-typedef std::map<const char*, LLMessageBuilder*> BuilderMap;
-
-void LLMessageSystem::newMessageFast(const char *name)
-{
- //LL_DEBUGS("Messaging") << "creating new message: " << name << LL_ENDL;
- LLMessageConfig::Flavor message_flavor =
- LLMessageConfig::getMessageFlavor(name);
- LLMessageConfig::Flavor server_flavor =
- LLMessageConfig::getServerDefaultFlavor();
-
- if(message_flavor == LLMessageConfig::TEMPLATE_FLAVOR)
- {
- mMessageBuilder = mTemplateMessageBuilder;
- }
- else if (message_flavor == LLMessageConfig::LLSD_FLAVOR)
- {
- mMessageBuilder = mLLSDMessageBuilder;
- }
- // NO_FLAVOR
- else
- {
- if (server_flavor == LLMessageConfig::LLSD_FLAVOR)
- {
- mMessageBuilder = mLLSDMessageBuilder;
- }
- // TEMPLATE_FLAVOR or NO_FLAVOR
- else
- {
- mMessageBuilder = mTemplateMessageBuilder;
- }
- }
- mSendReliable = false;
- mMessageBuilder->newMessage(name);
-}
-
-void LLMessageSystem::newMessage(const char *name)
-{
- newMessageFast(LLMessageStringTable::getInstance()->getString(name));
-}
-
-void LLMessageSystem::addBinaryDataFast(const char *varname, const void *data, S32 size)
-{
- mMessageBuilder->addBinaryData(varname, data, size);
-}
-
-void LLMessageSystem::addBinaryData(const char *varname, const void *data, S32 size)
-{
- mMessageBuilder->addBinaryData(LLMessageStringTable::getInstance()->getString(varname),data, size);
-}
-
-void LLMessageSystem::addS8Fast(const char *varname, S8 v)
-{
- mMessageBuilder->addS8(varname, v);
-}
-
-void LLMessageSystem::addS8(const char *varname, S8 v)
-{
- mMessageBuilder->addS8(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-void LLMessageSystem::addU8Fast(const char *varname, U8 v)
-{
- mMessageBuilder->addU8(varname, v);
-}
-
-void LLMessageSystem::addU8(const char *varname, U8 v)
-{
- mMessageBuilder->addU8(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-void LLMessageSystem::addS16Fast(const char *varname, S16 v)
-{
- mMessageBuilder->addS16(varname, v);
-}
-
-void LLMessageSystem::addS16(const char *varname, S16 v)
-{
- mMessageBuilder->addS16(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-void LLMessageSystem::addU16Fast(const char *varname, U16 v)
-{
- mMessageBuilder->addU16(varname, v);
-}
-
-void LLMessageSystem::addU16(const char *varname, U16 v)
-{
- mMessageBuilder->addU16(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-void LLMessageSystem::addF32Fast(const char *varname, F32 v)
-{
- mMessageBuilder->addF32(varname, v);
-}
-
-void LLMessageSystem::addF32(const char *varname, F32 v)
-{
- mMessageBuilder->addF32(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-void LLMessageSystem::addS32Fast(const char *varname, S32 v)
-{
- mMessageBuilder->addS32(varname, v);
-}
-
-void LLMessageSystem::addS32(const char *varname, S32 v)
-{
- mMessageBuilder->addS32(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-void LLMessageSystem::addU32Fast(const char *varname, U32 v)
-{
- mMessageBuilder->addU32(varname, v);
-}
-
-void LLMessageSystem::addU32(const char *varname, U32 v)
-{
- mMessageBuilder->addU32(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-void LLMessageSystem::addU64Fast(const char *varname, U64 v)
-{
- mMessageBuilder->addU64(varname, v);
-}
-
-void LLMessageSystem::addU64(const char *varname, U64 v)
-{
- mMessageBuilder->addU64(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-void LLMessageSystem::addF64Fast(const char *varname, F64 v)
-{
- mMessageBuilder->addF64(varname, v);
-}
-
-void LLMessageSystem::addF64(const char *varname, F64 v)
-{
- mMessageBuilder->addF64(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-void LLMessageSystem::addIPAddrFast(const char *varname, U32 v)
-{
- mMessageBuilder->addIPAddr(varname, v);
-}
-
-void LLMessageSystem::addIPAddr(const char *varname, U32 v)
-{
- mMessageBuilder->addIPAddr(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-void LLMessageSystem::addIPPortFast(const char *varname, U16 v)
-{
- mMessageBuilder->addIPPort(varname, v);
-}
-
-void LLMessageSystem::addIPPort(const char *varname, U16 v)
-{
- mMessageBuilder->addIPPort(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-void LLMessageSystem::addBOOLFast(const char* varname, bool v)
-{
- mMessageBuilder->addBOOL(varname, v);
-}
-
-void LLMessageSystem::addBOOL(const char* varname, bool v)
-{
- mMessageBuilder->addBOOL(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-void LLMessageSystem::addStringFast(const char* varname, const char* v)
-{
- mMessageBuilder->addString(varname, v);
-}
-
-void LLMessageSystem::addString(const char* varname, const char* v)
-{
- mMessageBuilder->addString(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-void LLMessageSystem::addStringFast(const char* varname, const std::string& v)
-{
- mMessageBuilder->addString(varname, v);
-}
-
-void LLMessageSystem::addString(const char* varname, const std::string& v)
-{
- mMessageBuilder->addString(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-void LLMessageSystem::addVector3Fast(const char *varname, const LLVector3& v)
-{
- mMessageBuilder->addVector3(varname, v);
-}
-
-void LLMessageSystem::addVector3(const char *varname, const LLVector3& v)
-{
- mMessageBuilder->addVector3(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-void LLMessageSystem::addVector4Fast(const char *varname, const LLVector4& v)
-{
- mMessageBuilder->addVector4(varname, v);
-}
-
-void LLMessageSystem::addVector4(const char *varname, const LLVector4& v)
-{
- mMessageBuilder->addVector4(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-void LLMessageSystem::addVector3dFast(const char *varname, const LLVector3d& v)
-{
- mMessageBuilder->addVector3d(varname, v);
-}
-
-void LLMessageSystem::addVector3d(const char *varname, const LLVector3d& v)
-{
- mMessageBuilder->addVector3d(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-void LLMessageSystem::addQuatFast(const char *varname, const LLQuaternion& v)
-{
- mMessageBuilder->addQuat(varname, v);
-}
-
-void LLMessageSystem::addQuat(const char *varname, const LLQuaternion& v)
-{
- mMessageBuilder->addQuat(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-
-void LLMessageSystem::addUUIDFast(const char *varname, const LLUUID& v)
-{
- mMessageBuilder->addUUID(varname, v);
-}
-
-void LLMessageSystem::addUUID(const char *varname, const LLUUID& v)
-{
- mMessageBuilder->addUUID(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-S32 LLMessageSystem::getCurrentSendTotal() const
-{
- return mMessageBuilder->getMessageSize();
-}
-
-void LLMessageSystem::getS8Fast(const char *block, const char *var, S8 &u,
- S32 blocknum)
-{
- mMessageReader->getS8(block, var, u, blocknum);
-}
-
-void LLMessageSystem::getS8(const char *block, const char *var, S8 &u,
- S32 blocknum)
-{
- getS8Fast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), u, blocknum);
-}
-
-void LLMessageSystem::getU8Fast(const char *block, const char *var, U8 &u,
- S32 blocknum)
-{
- mMessageReader->getU8(block, var, u, blocknum);
-}
-
-void LLMessageSystem::getU8(const char *block, const char *var, U8 &u,
- S32 blocknum)
-{
- getU8Fast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), u, blocknum);
-}
-
-void LLMessageSystem::getBOOLFast(const char *block, const char *var, bool &b,
- S32 blocknum)
-{
- mMessageReader->getBOOL(block, var, b, blocknum);
-}
-
-void LLMessageSystem::getBOOL(const char *block, const char *var, bool &b,
- S32 blocknum)
-{
- getBOOLFast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), b, blocknum);
-}
-
-void LLMessageSystem::getS16Fast(const char *block, const char *var, S16 &d,
- S32 blocknum)
-{
- mMessageReader->getS16(block, var, d, blocknum);
-}
-
-void LLMessageSystem::getS16(const char *block, const char *var, S16 &d,
- S32 blocknum)
-{
- getS16Fast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), d, blocknum);
-}
-
-void LLMessageSystem::getU16Fast(const char *block, const char *var, U16 &d,
- S32 blocknum)
-{
- mMessageReader->getU16(block, var, d, blocknum);
-}
-
-void LLMessageSystem::getU16(const char *block, const char *var, U16 &d,
- S32 blocknum)
-{
- getU16Fast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), d, blocknum);
-}
-
-void LLMessageSystem::getS32Fast(const char *block, const char *var, S32 &d,
- S32 blocknum)
-{
- mMessageReader->getS32(block, var, d, blocknum);
-}
-
-void LLMessageSystem::getS32(const char *block, const char *var, S32 &d,
- S32 blocknum)
-{
- getS32Fast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), d, blocknum);
-}
-
-void LLMessageSystem::getU32Fast(const char *block, const char *var, U32 &d,
- S32 blocknum)
-{
- mMessageReader->getU32(block, var, d, blocknum);
-}
-
-void LLMessageSystem::getU32(const char *block, const char *var, U32 &d,
- S32 blocknum)
-{
- getU32Fast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), d, blocknum);
-}
-
-void LLMessageSystem::getU64Fast(const char *block, const char *var, U64 &d,
- S32 blocknum)
-{
- mMessageReader->getU64(block, var, d, blocknum);
-}
-
-void LLMessageSystem::getU64(const char *block, const char *var, U64 &d,
- S32 blocknum)
-{
-
- getU64Fast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), d, blocknum);
-}
-
-void LLMessageSystem::getBinaryDataFast(const char *blockname,
- const char *varname,
- void *datap, S32 size,
- S32 blocknum, S32 max_size)
-{
- mMessageReader->getBinaryData(blockname, varname, datap, size, blocknum,
- max_size);
-}
-
-void LLMessageSystem::getBinaryData(const char *blockname,
- const char *varname,
- void *datap, S32 size,
- S32 blocknum, S32 max_size)
-{
- getBinaryDataFast(LLMessageStringTable::getInstance()->getString(blockname),
- LLMessageStringTable::getInstance()->getString(varname),
- datap, size, blocknum, max_size);
-}
-
-void LLMessageSystem::getF32Fast(const char *block, const char *var, F32 &d,
- S32 blocknum)
-{
- mMessageReader->getF32(block, var, d, blocknum);
-}
-
-void LLMessageSystem::getF32(const char *block, const char *var, F32 &d,
- S32 blocknum)
-{
- getF32Fast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), d, blocknum);
-}
-
-void LLMessageSystem::getF64Fast(const char *block, const char *var, F64 &d,
- S32 blocknum)
-{
- mMessageReader->getF64(block, var, d, blocknum);
-}
-
-void LLMessageSystem::getF64(const char *block, const char *var, F64 &d,
- S32 blocknum)
-{
- getF64Fast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), d, blocknum);
-}
-
-
-void LLMessageSystem::getVector3Fast(const char *block, const char *var,
- LLVector3 &v, S32 blocknum )
-{
- mMessageReader->getVector3(block, var, v, blocknum);
-}
-
-void LLMessageSystem::getVector3(const char *block, const char *var,
- LLVector3 &v, S32 blocknum )
-{
- getVector3Fast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), v, blocknum);
-}
-
-void LLMessageSystem::getVector4Fast(const char *block, const char *var,
- LLVector4 &v, S32 blocknum )
-{
- mMessageReader->getVector4(block, var, v, blocknum);
-}
-
-void LLMessageSystem::getVector4(const char *block, const char *var,
- LLVector4 &v, S32 blocknum )
-{
- getVector4Fast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), v, blocknum);
-}
-
-void LLMessageSystem::getVector3dFast(const char *block, const char *var,
- LLVector3d &v, S32 blocknum )
-{
- mMessageReader->getVector3d(block, var, v, blocknum);
-}
-
-void LLMessageSystem::getVector3d(const char *block, const char *var,
- LLVector3d &v, S32 blocknum )
-{
- getVector3dFast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), v, blocknum);
-}
-
-void LLMessageSystem::getQuatFast(const char *block, const char *var,
- LLQuaternion &q, S32 blocknum )
-{
- mMessageReader->getQuat(block, var, q, blocknum);
-}
-
-void LLMessageSystem::getQuat(const char *block, const char *var,
- LLQuaternion &q, S32 blocknum)
-{
- getQuatFast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), q, blocknum);
-}
-
-void LLMessageSystem::getUUIDFast(const char *block, const char *var,
- LLUUID &u, S32 blocknum )
-{
- mMessageReader->getUUID(block, var, u, blocknum);
-}
-
-void LLMessageSystem::getUUID(const char *block, const char *var, LLUUID &u,
- S32 blocknum )
-{
- getUUIDFast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), u, blocknum);
-}
-
-void LLMessageSystem::getIPAddrFast(const char *block, const char *var,
- U32 &u, S32 blocknum)
-{
- mMessageReader->getIPAddr(block, var, u, blocknum);
-}
-
-void LLMessageSystem::getIPAddr(const char *block, const char *var, U32 &u,
- S32 blocknum)
-{
- getIPAddrFast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), u, blocknum);
-}
-
-void LLMessageSystem::getIPPortFast(const char *block, const char *var,
- U16 &u, S32 blocknum)
-{
- mMessageReader->getIPPort(block, var, u, blocknum);
-}
-
-void LLMessageSystem::getIPPort(const char *block, const char *var, U16 &u,
- S32 blocknum)
-{
- getIPPortFast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), u,
- blocknum);
-}
-
-
-void LLMessageSystem::getStringFast(const char *block, const char *var,
- S32 buffer_size, char *s, S32 blocknum)
-{
- if(buffer_size <= 0)
- {
- LL_WARNS("Messaging") << "buffer_size <= 0" << LL_ENDL;
- }
- mMessageReader->getString(block, var, buffer_size, s, blocknum);
-}
-
-void LLMessageSystem::getString(const char *block, const char *var,
- S32 buffer_size, char *s, S32 blocknum )
-{
- getStringFast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), buffer_size, s,
- blocknum);
-}
-
-void LLMessageSystem::getStringFast(const char *block, const char *var,
- std::string& outstr, S32 blocknum)
-{
- mMessageReader->getString(block, var, outstr, blocknum);
-}
-
-void LLMessageSystem::getString(const char *block, const char *var,
- std::string& outstr, S32 blocknum )
-{
- getStringFast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), outstr,
- blocknum);
-}
-
-bool LLMessageSystem::has(const char *blockname) const
-{
- return getNumberOfBlocks(blockname) > 0;
-}
-
-S32 LLMessageSystem::getNumberOfBlocksFast(const char *blockname) const
-{
- return mMessageReader->getNumberOfBlocks(blockname);
-}
-
-S32 LLMessageSystem::getNumberOfBlocks(const char *blockname) const
-{
- return getNumberOfBlocksFast(LLMessageStringTable::getInstance()->getString(blockname));
-}
-
-S32 LLMessageSystem::getSizeFast(const char *blockname, const char *varname) const
-{
- return mMessageReader->getSize(blockname, varname);
-}
-
-S32 LLMessageSystem::getSize(const char *blockname, const char *varname) const
-{
- return getSizeFast(LLMessageStringTable::getInstance()->getString(blockname),
- LLMessageStringTable::getInstance()->getString(varname));
-}
-
-// size in bytes of variable length data
-S32 LLMessageSystem::getSizeFast(const char *blockname, S32 blocknum,
- const char *varname) const
-{
- return mMessageReader->getSize(blockname, blocknum, varname);
-}
-
-S32 LLMessageSystem::getSize(const char *blockname, S32 blocknum,
- const char *varname) const
-{
- return getSizeFast(LLMessageStringTable::getInstance()->getString(blockname), blocknum,
- LLMessageStringTable::getInstance()->getString(varname));
-}
-
-S32 LLMessageSystem::getReceiveSize() const
-{
- return mMessageReader->getMessageSize();
-}
-
-//static
-void LLMessageSystem::setTimeDecodes( bool b )
-{
- LLMessageReader::setTimeDecodes(b);
-}
-
-//static
-void LLMessageSystem::setTimeDecodesSpamThreshold( F32 seconds )
-{
- LLMessageReader::setTimeDecodesSpamThreshold(seconds);
-}
-
-LockMessageChecker::LockMessageChecker(LLMessageSystem* msgsystem):
- // for the lifespan of this LockMessageChecker instance, use
- // LLTemplateMessageReader as msgsystem's mMessageReader
- LockMessageReader(msgsystem->mMessageReader, msgsystem->mTemplateMessageReader),
- mMessageSystem(msgsystem)
-{}
-
-// HACK! babbage: return true if message rxed via either UDP or HTTP
-// TODO: babbage: move gServicePump in to LLMessageSystem?
-bool LLMessageSystem::checkAllMessages(LockMessageChecker& lmc, S64 frame_count, LLPumpIO* http_pump)
-{
- if(lmc.checkMessages(frame_count))
- {
- return true;
- }
- U32 packetsIn = mPacketsIn;
- http_pump->pump();
- http_pump->callback();
- return (mPacketsIn - packetsIn) > 0;
-}
-
-void LLMessageSystem::banUdpMessage(const std::string& name)
-{
- message_template_name_map_t::iterator itt = mMessageTemplates.find(
- LLMessageStringTable::getInstance()->getString(name.c_str())
- );
- if(itt != mMessageTemplates.end())
- {
- itt->second->banUdp();
- }
- else
- {
- LL_WARNS() << "Attempted to ban an unknown message: " << name << "." << LL_ENDL;
- }
-}
-const LLHost& LLMessageSystem::getSender() const
-{
- return mLastSender;
-}
-
-void LLMessageSystem::sendUntrustedSimulatorMessageCoro(std::string url, std::string message, LLSD body, UntrustedCallback_t callback)
-{
- LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
- LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
- httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("untrustedSimulatorMessage", httpPolicy));
- LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
- LLCore::HttpOptions::ptr_t httpOpts = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions);
-
-
- if (url.empty())
- {
- LL_WARNS() << "sendUntrustedSimulatorMessageCoro called with empty capability!" << LL_ENDL;
- return;
- }
-
- LL_INFOS() << "sendUntrustedSimulatorMessageCoro: message " << message << " to cap " << url << LL_ENDL;
- LLSD postData;
- postData["message"] = message;
- postData["body"] = body;
-
- LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData, httpOpts);
-
- LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
- LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
-
- if ((callback) && (!callback.empty()))
- callback((status) ? LL_ERR_NOERR : LL_ERR_TCP_TIMEOUT);
-}
-
-
-LLHTTPRegistration<LLHTTPNodeAdapter<LLTrustedMessageService> >
- gHTTPRegistrationTrustedMessageWildcard("/trusted-message/<message-name>");
-
+/**
+ * @file message.cpp
+ * @brief LLMessageSystem class implementation
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "message.h"
+
+// system library includes
+#if !LL_WINDOWS
+// following header files required for inet_addr()
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+#include <iomanip>
+#include <iterator>
+#include <sstream>
+
+#include "llapr.h"
+#include "apr_portable.h"
+#include "apr_network_io.h"
+#include "apr_poll.h"
+
+// linden library headers
+#include "llapp.h"
+#include "indra_constants.h"
+#include "lldir.h"
+#include "llerror.h"
+#include "llfasttimer.h"
+#include "llhttpnodeadapter.h"
+#include "llmd5.h"
+#include "llmessagebuilder.h"
+#include "llmessageconfig.h"
+#include "lltemplatemessagedispatcher.h"
+#include "llpumpio.h"
+#include "lltemplatemessagebuilder.h"
+#include "lltemplatemessagereader.h"
+#include "lltrustedmessageservice.h"
+#include "llmessagetemplate.h"
+#include "llmessagetemplateparser.h"
+#include "llsd.h"
+#include "llsdmessagebuilder.h"
+#include "llsdmessagereader.h"
+#include "llsdserialize.h"
+#include "llstring.h"
+#include "lltransfermanager.h"
+#include "lluuid.h"
+#include "llxfermanager.h"
+#include "llquaternion.h"
+#include "u64.h"
+#include "v3dmath.h"
+#include "v3math.h"
+#include "v4math.h"
+#include "lltransfertargetvfile.h"
+#include "llcorehttputil.h"
+#include "llpounceable.h"
+
+// Constants
+//const char* MESSAGE_LOG_FILENAME = "message.log";
+static const F32Seconds CIRCUIT_DUMP_TIMEOUT(30.f);
+static const S32 TRUST_TIME_WINDOW = 3;
+
+// *NOTE: This needs to be moved into a seperate file so that it never gets
+// included in the viewer. 30 Sep 2002 mark
+// *NOTE: I don't think it's important that the messgage system tracks
+// this since it must get set externally. 2004.08.25 Phoenix.
+static std::string g_shared_secret;
+std::string get_shared_secret();
+
+class LLMessagePollInfo
+{
+public:
+ apr_socket_t *mAPRSocketp;
+ apr_pollfd_t mPollFD;
+};
+
+class LLMessageHandlerBridge : public LLHTTPNode
+{
+ virtual bool validate(const std::string& name, LLSD& context) const
+ { return true; }
+
+ virtual void post(LLHTTPNode::ResponsePtr response, const LLSD& context,
+ const LLSD& input) const;
+};
+
+//virtual
+void LLMessageHandlerBridge::post(LLHTTPNode::ResponsePtr response,
+ const LLSD& context, const LLSD& input) const
+{
+ std::string name = context[CONTEXT_REQUEST][CONTEXT_WILDCARD]["message-name"];
+ char* namePtr = LLMessageStringTable::getInstance()->getString(name.c_str());
+
+ LL_DEBUGS() << "Setting mLastSender " << input["sender"].asString() << LL_ENDL;
+ gMessageSystem->mLastSender = LLHost(input["sender"].asString());
+ gMessageSystem->mPacketsIn += 1;
+ gMessageSystem->mLLSDMessageReader->setMessage(namePtr, input["body"]);
+ LockMessageReader rdr(gMessageSystem->mMessageReader, gMessageSystem->mLLSDMessageReader);
+
+ if(gMessageSystem->callHandler(namePtr, false, gMessageSystem))
+ {
+ response->result(LLSD());
+ }
+ else
+ {
+ response->notFound();
+ }
+}
+
+LLHTTPRegistration<LLMessageHandlerBridge>
+ gHTTPRegistrationMessageWildcard("/message/<message-name>");
+
+//virtual
+LLUseCircuitCodeResponder::~LLUseCircuitCodeResponder()
+{
+ // even abstract base classes need a concrete destructor
+}
+
+static const char* nullToEmpty(const char* s)
+{
+ static char emptyString[] = "";
+ return s? s : emptyString;
+}
+
+void LLMessageSystem::init()
+{
+ // initialize member variables
+ mVerboseLog = false;
+
+ mbError = false;
+ mErrorCode = 0;
+ mSendReliable = false;
+
+ mUnackedListDepth = 0;
+ mUnackedListSize = 0;
+ mDSMaxListDepth = 0;
+
+ mNumberHighFreqMessages = 0;
+ mNumberMediumFreqMessages = 0;
+ mNumberLowFreqMessages = 0;
+ mPacketsIn = mPacketsOut = 0;
+ mBytesIn = mBytesOut = 0;
+ mCompressedPacketsIn = mCompressedPacketsOut = 0;
+ mReliablePacketsIn = mReliablePacketsOut = 0;
+
+ mCompressedBytesIn = 0;
+ mCompressedBytesOut = 0;
+ mUncompressedBytesIn = 0;
+ mUncompressedBytesOut = 0;
+ mTotalBytesIn = 0;
+ mTotalBytesOut = 0;
+
+ mDroppedPackets = 0; // total dropped packets in
+ mResentPackets = 0; // total resent packets out
+ mFailedResendPackets = 0; // total resend failure packets out
+ mOffCircuitPackets = 0; // total # of off-circuit packets rejected
+ mInvalidOnCircuitPackets = 0; // total # of on-circuit packets rejected
+
+ mOurCircuitCode = 0;
+
+ mIncomingCompressedSize = 0;
+ mCurrentRecvPacketID = 0;
+
+ mMessageFileVersionNumber = 0.f;
+
+ mTimingCallback = NULL;
+ mTimingCallbackData = NULL;
+
+ mMessageBuilder = NULL;
+ LockMessageReader(mMessageReader, NULL);
+}
+
+// Read file and build message templates
+LLMessageSystem::LLMessageSystem(const std::string& filename, U32 port,
+ S32 version_major,
+ S32 version_minor,
+ S32 version_patch,
+ bool failure_is_fatal,
+ const F32 circuit_heartbeat_interval, const F32 circuit_timeout) :
+ mCircuitInfo(F32Seconds(circuit_heartbeat_interval), F32Seconds(circuit_timeout)),
+ mLastMessageFromTrustedMessageService(false)
+{
+ init();
+
+ mSendSize = 0;
+
+ mSystemVersionMajor = version_major;
+ mSystemVersionMinor = version_minor;
+ mSystemVersionPatch = version_patch;
+ mSystemVersionServer = 0;
+ mVersionFlags = 0x0;
+
+ // default to not accepting packets from not alive circuits
+ mbProtected = true;
+
+ // default to blocking trusted connections on a public interface if one is specified
+ mBlockUntrustedInterface = true;
+
+ mSendPacketFailureCount = 0;
+
+ mCircuitPrintFreq = F32Seconds(60.f);
+
+ loadTemplateFile(filename, failure_is_fatal);
+
+ mTemplateMessageBuilder = new LLTemplateMessageBuilder(mMessageTemplates);
+ mLLSDMessageBuilder = new LLSDMessageBuilder();
+ mMessageBuilder = NULL;
+
+ mTemplateMessageReader = new LLTemplateMessageReader(mMessageNumbers);
+ mLLSDMessageReader = new LLSDMessageReader();
+
+ // initialize various bits of net info
+ mSocket = 0;
+ mPort = port;
+
+ S32 error = start_net(mSocket, mPort);
+ if (error != 0)
+ {
+ mbError = true;
+ mErrorCode = error;
+ }
+// LL_DEBUGS("Messaging") << << "*** port: " << mPort << LL_ENDL;
+
+ //
+ // Create the data structure that we can poll on
+ //
+ if (!gAPRPoolp)
+ {
+ LL_ERRS("Messaging") << "No APR pool before message system initialization!" << LL_ENDL;
+ ll_init_apr();
+ }
+ apr_socket_t *aprSocketp = NULL;
+ apr_os_sock_put(&aprSocketp, (apr_os_sock_t*)&mSocket, gAPRPoolp);
+
+ mPollInfop = new LLMessagePollInfo;
+ mPollInfop->mAPRSocketp = aprSocketp;
+ mPollInfop->mPollFD.p = gAPRPoolp;
+ mPollInfop->mPollFD.desc_type = APR_POLL_SOCKET;
+ mPollInfop->mPollFD.reqevents = APR_POLLIN;
+ mPollInfop->mPollFD.rtnevents = 0;
+ mPollInfop->mPollFD.desc.s = aprSocketp;
+ mPollInfop->mPollFD.client_data = NULL;
+
+ F64Seconds mt_sec = getMessageTimeSeconds();
+ mResendDumpTime = mt_sec;
+ mMessageCountTime = mt_sec;
+ mCircuitPrintTime = mt_sec;
+ mCurrentMessageTime = F64Seconds(mt_sec);
+
+ // Constants for dumping output based on message processing time/count
+ mNumMessageCounts = 0;
+ mMaxMessageCounts = 200; // >= 0 means dump warnings
+ mMaxMessageTime = F32Seconds(1.f);
+
+ mTrueReceiveSize = 0;
+
+ mReceiveTime = F32Seconds(0.f);
+}
+
+
+
+// Read file and build message templates
+void LLMessageSystem::loadTemplateFile(const std::string& filename, bool failure_is_fatal)
+{
+ if(filename.empty())
+ {
+ LL_ERRS("Messaging") << "No template filename specified" << LL_ENDL;
+ mbError = true;
+ return;
+ }
+
+ std::string template_body;
+ if(!_read_file_into_string(template_body, filename))
+ {
+ if (failure_is_fatal) {
+ LL_ERRS("Messaging") << "Failed to open template: " << filename << LL_ENDL;
+ } else {
+ LL_WARNS("Messaging") << "Failed to open template: " << filename << LL_ENDL;
+ }
+ mbError = true;
+ return;
+ }
+
+ LLTemplateTokenizer tokens(template_body);
+ LLTemplateParser parsed(tokens);
+ mMessageFileVersionNumber = parsed.getVersion();
+ S32 count = 0;
+ for(LLTemplateParser::message_iterator iter = parsed.getMessagesBegin();
+ iter != parsed.getMessagesEnd();
+ iter++)
+ {
+ addTemplate(*iter);
+ count++;
+ }
+ LL_INFOS("Messaging") << "Read " << count << " messages from " << filename << LL_ENDL;
+}
+
+
+LLMessageSystem::~LLMessageSystem()
+{
+ mMessageTemplates.clear(); // don't delete templates.
+ for_each(mMessageNumbers.begin(), mMessageNumbers.end(), DeletePairedPointer());
+ mMessageNumbers.clear();
+
+ if (!mbError)
+ {
+ end_net(mSocket);
+ }
+ mSocket = 0;
+
+ delete mTemplateMessageReader;
+ mTemplateMessageReader = NULL;
+
+ delete mTemplateMessageBuilder;
+ mTemplateMessageBuilder = NULL;
+ mMessageBuilder = NULL;
+
+ delete mLLSDMessageReader;
+ mLLSDMessageReader = NULL;
+
+ delete mLLSDMessageBuilder;
+ mLLSDMessageBuilder = NULL;
+
+ delete mPollInfop;
+ mPollInfop = NULL;
+
+ mIncomingCompressedSize = 0;
+ mCurrentRecvPacketID = 0;
+}
+
+void LLMessageSystem::clearReceiveState()
+{
+ mCurrentRecvPacketID = 0;
+ mIncomingCompressedSize = 0;
+ mLastSender.invalidate();
+ mLastReceivingIF.invalidate();
+ mMessageReader->clearMessage();
+ mLastMessageFromTrustedMessageService = false;
+}
+
+
+bool LLMessageSystem::poll(F32 seconds)
+{
+ S32 num_socks;
+ apr_status_t status;
+ status = apr_poll(&(mPollInfop->mPollFD), 1, &num_socks,(U64)(seconds*1000000.f));
+ if (status != APR_TIMEUP)
+ {
+ ll_apr_warn_status(status);
+ }
+ if (num_socks)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+bool LLMessageSystem::isTrustedSender(const LLHost& host) const
+{
+ LLCircuitData* cdp = mCircuitInfo.findCircuit(host);
+ if(NULL == cdp)
+ {
+ return false;
+ }
+ return cdp->getTrusted();
+}
+
+void LLMessageSystem::receivedMessageFromTrustedSender()
+{
+ mLastMessageFromTrustedMessageService = true;
+}
+
+bool LLMessageSystem::isTrustedSender() const
+{
+ return mLastMessageFromTrustedMessageService ||
+ isTrustedSender(getSender());
+}
+
+static LLMessageSystem::message_template_name_map_t::const_iterator
+findTemplate(const LLMessageSystem::message_template_name_map_t& templates,
+ std::string name)
+{
+ const char* namePrehash = LLMessageStringTable::getInstance()->getString(name.c_str());
+ if(NULL == namePrehash) {return templates.end();}
+ return templates.find(namePrehash);
+}
+
+bool LLMessageSystem::isTrustedMessage(const std::string& name) const
+{
+ message_template_name_map_t::const_iterator iter =
+ findTemplate(mMessageTemplates, name);
+ if(iter == mMessageTemplates.end()) {return false;}
+ return iter->second->getTrust() == MT_TRUST;
+}
+
+bool LLMessageSystem::isUntrustedMessage(const std::string& name) const
+{
+ message_template_name_map_t::const_iterator iter =
+ findTemplate(mMessageTemplates, name);
+ if(iter == mMessageTemplates.end()) {return false;}
+ return iter->second->getTrust() == MT_NOTRUST;
+}
+
+LLCircuitData* LLMessageSystem::findCircuit(const LLHost& host,
+ bool resetPacketId)
+{
+ LLCircuitData* cdp = mCircuitInfo.findCircuit(host);
+ if (!cdp)
+ {
+ // This packet comes from a circuit we don't know about.
+
+ // Are we rejecting off-circuit packets?
+ if (mbProtected)
+ {
+ // cdp is already NULL, so we don't need to unset it.
+ }
+ else
+ {
+ // nope, open the new circuit
+ cdp = mCircuitInfo.addCircuitData(host, mCurrentRecvPacketID);
+
+ if(resetPacketId)
+ {
+ // I added this - I think it's correct - DJS
+ // reset packet in ID
+ cdp->setPacketInID(mCurrentRecvPacketID);
+ }
+ // And claim the packet is on the circuit we just added.
+ }
+ }
+ else
+ {
+ // this is an old circuit. . . is it still alive?
+ if (!cdp->isAlive())
+ {
+ // nope. don't accept if we're protected
+ if (mbProtected)
+ {
+ // don't accept packets from unexpected sources
+ cdp = NULL;
+ }
+ else
+ {
+ // wake up the circuit
+ cdp->setAlive(true);
+
+ if(resetPacketId)
+ {
+ // reset packet in ID
+ cdp->setPacketInID(mCurrentRecvPacketID);
+ }
+ }
+ }
+ }
+ return cdp;
+}
+
+// Returns true if a valid, on-circuit message has been received.
+// Requiring a non-const LockMessageChecker reference ensures that
+// mMessageReader has been set to mTemplateMessageReader.
+bool LLMessageSystem::checkMessages(LockMessageChecker&, S64 frame_count )
+{
+ // Pump
+ bool valid_packet = false;
+
+ LLTransferTargetVFile::updateQueue();
+
+ if (!mNumMessageCounts)
+ {
+ // This is the first message being handled after a resetReceiveCounts,
+ // we must be starting the message processing loop. Reset the timers.
+ mCurrentMessageTime = totalTime();
+ mMessageCountTime = getMessageTimeSeconds();
+ }
+
+ // loop until either no packets or a valid packet
+ // i.e., burn through packets from unregistered circuits
+ S32 receive_size = 0;
+ do
+ {
+ clearReceiveState();
+
+ bool recv_reliable = false;
+ bool recv_resent = false;
+ S32 acks = 0;
+ S32 true_rcv_size = 0;
+
+ U8* buffer = mTrueReceiveBuffer;
+
+ mTrueReceiveSize = mPacketRing.receivePacket(mSocket, (char *)mTrueReceiveBuffer);
+ // If you want to dump all received packets into SecondLife.log, uncomment this
+ //dumpPacketToLog();
+
+ receive_size = mTrueReceiveSize;
+ mLastSender = mPacketRing.getLastSender();
+ mLastReceivingIF = mPacketRing.getLastReceivingInterface();
+
+ if (receive_size < (S32) LL_MINIMUM_VALID_PACKET_SIZE)
+ {
+ // A receive size of zero is OK, that means that there are no more packets available.
+ // Ones that are non-zero but below the minimum packet size are worrisome.
+ if (receive_size > 0)
+ {
+ LL_WARNS("Messaging") << "Invalid (too short) packet discarded " << receive_size << LL_ENDL;
+ callExceptionFunc(MX_PACKET_TOO_SHORT);
+ }
+ // no data in packet receive buffer
+ valid_packet = false;
+ }
+ else
+ {
+ LLHost host;
+ LLCircuitData* cdp;
+
+ // note if packet acks are appended.
+ if(buffer[0] & LL_ACK_FLAG)
+ {
+ acks += buffer[--receive_size];
+ true_rcv_size = receive_size;
+ if(receive_size >= ((S32)(acks * sizeof(TPACKETID) + LL_MINIMUM_VALID_PACKET_SIZE)))
+ {
+ receive_size -= acks * sizeof(TPACKETID);
+ }
+ else
+ {
+ // mal-formed packet. ignore it and continue with
+ // the next one
+ LL_WARNS("Messaging") << "Malformed packet received. Packet size "
+ << receive_size << " with invalid no. of acks " << acks
+ << LL_ENDL;
+ valid_packet = false;
+ continue;
+ }
+ }
+
+ // process the message as normal
+ mIncomingCompressedSize = zeroCodeExpand(&buffer, &receive_size);
+ mCurrentRecvPacketID = ntohl(*((U32*)(&buffer[1])));
+ host = getSender();
+
+ const bool resetPacketId = true;
+ cdp = findCircuit(host, resetPacketId);
+
+ // At this point, cdp is now a pointer to the circuit that
+ // this message came in on if it's valid, and NULL if the
+ // circuit was bogus.
+
+ if(cdp && (acks > 0) && ((S32)(acks * sizeof(TPACKETID)) < (true_rcv_size)))
+ {
+ TPACKETID packet_id;
+ U32 mem_id=0;
+ for(S32 i = 0; i < acks; ++i)
+ {
+ true_rcv_size -= sizeof(TPACKETID);
+ memcpy(&mem_id, &mTrueReceiveBuffer[true_rcv_size], /* Flawfinder: ignore*/
+ sizeof(TPACKETID));
+ packet_id = ntohl(mem_id);
+ //LL_INFOS("Messaging") << "got ack: " << packet_id << LL_ENDL;
+ cdp->ackReliablePacket(packet_id);
+ }
+ if (!cdp->getUnackedPacketCount())
+ {
+ // Remove this circuit from the list of circuits with unacked packets
+ mCircuitInfo.mUnackedCircuitMap.erase(cdp->mHost);
+ }
+ }
+
+ if (buffer[0] & LL_RELIABLE_FLAG)
+ {
+ recv_reliable = true;
+ }
+ if (buffer[0] & LL_RESENT_FLAG)
+ {
+ recv_resent = true;
+ if (cdp && cdp->isDuplicateResend(mCurrentRecvPacketID))
+ {
+ // We need to ACK here to suppress
+ // further resends of packets we've
+ // already seen.
+ if (recv_reliable)
+ {
+ //mAckList.addData(new LLPacketAck(host, mCurrentRecvPacketID));
+ // ***************************************
+ // TESTING CODE
+ //if(mCircuitInfo.mCurrentCircuit->mHost != host)
+ //{
+ // LL_WARNS("Messaging") << "DISCARDED PACKET HOST MISMATCH! HOST: "
+ // << host << " CIRCUIT: "
+ // << mCircuitInfo.mCurrentCircuit->mHost
+ // << LL_ENDL;
+ //}
+ // ***************************************
+ //mCircuitInfo.mCurrentCircuit->mAcks.put(mCurrentRecvPacketID);
+ cdp->collectRAck(mCurrentRecvPacketID);
+ }
+
+ LL_DEBUGS("Messaging") << "Discarding duplicate resend from " << host << LL_ENDL;
+ if(mVerboseLog)
+ {
+ std::ostringstream str;
+ str << "MSG: <- " << host;
+ std::string tbuf;
+ tbuf = llformat( "\t%6d\t%6d\t%6d ", receive_size, (mIncomingCompressedSize ? mIncomingCompressedSize : receive_size), mCurrentRecvPacketID);
+ str << tbuf << "(unknown)"
+ << (recv_reliable ? " reliable" : "")
+ << " resent "
+ << ((acks > 0) ? "acks" : "")
+ << " DISCARD DUPLICATE";
+ LL_INFOS("Messaging") << str.str() << LL_ENDL;
+ }
+ mPacketsIn++;
+ valid_packet = false;
+ continue;
+ }
+ }
+
+ // UseCircuitCode can be a valid, off-circuit packet.
+ // But we don't want to acknowledge UseCircuitCode until the circuit is
+ // available, which is why the acknowledgement test is done above. JC
+ bool trusted = cdp && cdp->getTrusted();
+ valid_packet = mTemplateMessageReader->validateMessage(
+ buffer,
+ receive_size,
+ host,
+ trusted);
+ if (!valid_packet)
+ {
+ clearReceiveState();
+ }
+
+ // UseCircuitCode is allowed in even from an invalid circuit, so that
+ // we can toss circuits around.
+ if(
+ valid_packet &&
+ !cdp &&
+ (mTemplateMessageReader->getMessageName() !=
+ _PREHASH_UseCircuitCode))
+ {
+ logMsgFromInvalidCircuit( host, recv_reliable );
+ clearReceiveState();
+ valid_packet = false;
+ }
+
+ if(
+ valid_packet &&
+ cdp &&
+ !cdp->getTrusted() &&
+ mTemplateMessageReader->isTrusted())
+ {
+ logTrustedMsgFromUntrustedCircuit( host );
+ clearReceiveState();
+
+ sendDenyTrustedCircuit(host);
+ valid_packet = false;
+ }
+
+ if( valid_packet )
+ {
+ logValidMsg(cdp, host, recv_reliable, recv_resent, acks>0 );
+ valid_packet = mTemplateMessageReader->readMessage(buffer, host);
+ }
+
+ // It's possible that the circuit went away, because ANY message can disable the circuit
+ // (for example, UseCircuit, CloseCircuit, DisableSimulator). Find it again.
+ cdp = mCircuitInfo.findCircuit(host);
+
+ if (valid_packet)
+ {
+ mPacketsIn++;
+ mBytesIn += mTrueReceiveSize;
+
+ // ACK here for valid packets that we've seen
+ // for the first time.
+ if (cdp && recv_reliable)
+ {
+ // Add to the recently received list for duplicate suppression
+ cdp->mRecentlyReceivedReliablePackets[mCurrentRecvPacketID] = getMessageTimeUsecs();
+
+ // Put it onto the list of packets to be acked
+ cdp->collectRAck(mCurrentRecvPacketID);
+ mReliablePacketsIn++;
+ }
+ }
+ else
+ {
+ if (mbProtected && (!cdp))
+ {
+ LL_WARNS("Messaging") << "Invalid Packet from invalid circuit " << host << LL_ENDL;
+ mOffCircuitPackets++;
+ }
+ else
+ {
+ mInvalidOnCircuitPackets++;
+ }
+ }
+ }
+ } while (!valid_packet && receive_size > 0);
+
+ F64Seconds mt_sec = getMessageTimeSeconds();
+ // Check to see if we need to print debug info
+ if ((mt_sec - mCircuitPrintTime) > mCircuitPrintFreq)
+ {
+ dumpCircuitInfo();
+ mCircuitPrintTime = mt_sec;
+ }
+
+ if( !valid_packet )
+ {
+ clearReceiveState();
+ }
+
+ return valid_packet;
+}
+
+S32 LLMessageSystem::getReceiveBytes() const
+{
+ if (getReceiveCompressedSize())
+ {
+ return getReceiveCompressedSize() * 8;
+ }
+ else
+ {
+ return getReceiveSize() * 8;
+ }
+}
+
+
+void LLMessageSystem::processAcks(LockMessageChecker&, F32 collect_time)
+{
+ F64Seconds mt_sec = getMessageTimeSeconds();
+ {
+ gTransferManager.updateTransfers();
+
+ if (gXferManager)
+ {
+ gXferManager->retransmitUnackedPackets();
+ }
+
+ if (gAssetStorage)
+ {
+ gAssetStorage->checkForTimeouts();
+ }
+ }
+
+ bool dump = false;
+ {
+ // Check the status of circuits
+ mCircuitInfo.updateWatchDogTimers(this);
+
+ //resend any necessary packets
+ mCircuitInfo.resendUnackedPackets(mUnackedListDepth, mUnackedListSize);
+
+ //cycle through ack list for each host we need to send acks to
+ mCircuitInfo.sendAcks(collect_time);
+
+ if (!mDenyTrustedCircuitSet.empty())
+ {
+ LL_INFOS("Messaging") << "Sending queued DenyTrustedCircuit messages." << LL_ENDL;
+ for (host_set_t::iterator hostit = mDenyTrustedCircuitSet.begin(); hostit != mDenyTrustedCircuitSet.end(); ++hostit)
+ {
+ reallySendDenyTrustedCircuit(*hostit);
+ }
+ mDenyTrustedCircuitSet.clear();
+ }
+
+ if (mMaxMessageCounts >= 0)
+ {
+ if (mNumMessageCounts >= mMaxMessageCounts)
+ {
+ dump = true;
+ }
+ }
+
+ if (mMaxMessageTime >= F32Seconds(0.f))
+ {
+ // This is one of the only places where we're required to get REAL message system time.
+ mReceiveTime = getMessageTimeSeconds(true) - mMessageCountTime;
+ if (mReceiveTime > mMaxMessageTime)
+ {
+ dump = true;
+ }
+ }
+ }
+
+ if (dump)
+ {
+ dumpReceiveCounts();
+ }
+ resetReceiveCounts();
+
+ if ((mt_sec - mResendDumpTime) > CIRCUIT_DUMP_TIMEOUT)
+ {
+ mResendDumpTime = mt_sec;
+ mCircuitInfo.dumpResends();
+ }
+}
+
+void LLMessageSystem::copyMessageReceivedToSend()
+{
+ // NOTE: babbage: switch builder to match reader to avoid
+ // converting message format
+ if(mMessageReader == mTemplateMessageReader)
+ {
+ mMessageBuilder = mTemplateMessageBuilder;
+ }
+ else
+ {
+ mMessageBuilder = mLLSDMessageBuilder;
+ }
+ mSendReliable = false;
+ mMessageBuilder->newMessage(mMessageReader->getMessageName());
+ mMessageReader->copyToBuilder(*mMessageBuilder);
+}
+
+LLSD LLMessageSystem::getReceivedMessageLLSD() const
+{
+ LLSDMessageBuilder builder;
+ mMessageReader->copyToBuilder(builder);
+ return builder.getMessage();
+}
+
+LLSD LLMessageSystem::getBuiltMessageLLSD() const
+{
+ LLSD result;
+ if (mLLSDMessageBuilder == mMessageBuilder)
+ {
+ result = mLLSDMessageBuilder->getMessage();
+ }
+ else
+ {
+ // TODO: implement as below?
+ LL_ERRS() << "Message not built as LLSD." << LL_ENDL;
+ }
+ return result;
+}
+
+LLSD LLMessageSystem::wrapReceivedTemplateData() const
+{
+ if(mMessageReader == mTemplateMessageReader)
+ {
+ LLTemplateMessageBuilder builder(mMessageTemplates);
+ builder.newMessage(mMessageReader->getMessageName());
+ mMessageReader->copyToBuilder(builder);
+ U8 buffer[MAX_BUFFER_SIZE];
+ const U8 offset_to_data = 0;
+ U32 size = builder.buildMessage(buffer, MAX_BUFFER_SIZE,
+ offset_to_data);
+ std::vector<U8> binary_data(buffer, buffer+size);
+ LLSD wrapped_data = LLSD::emptyMap();
+ wrapped_data["binary-template-data"] = binary_data;
+ return wrapped_data;
+ }
+ else
+ {
+ return getReceivedMessageLLSD();
+ }
+}
+
+LLSD LLMessageSystem::wrapBuiltTemplateData() const
+{
+ LLSD result;
+ if (mLLSDMessageBuilder == mMessageBuilder)
+ {
+ result = getBuiltMessageLLSD();
+ }
+ else
+ {
+ U8 buffer[MAX_BUFFER_SIZE];
+ const U8 offset_to_data = 0;
+ U32 size = mTemplateMessageBuilder->buildMessage(
+ buffer, MAX_BUFFER_SIZE,
+ offset_to_data);
+ std::vector<U8> binary_data(buffer, buffer+size);
+ LLSD wrapped_data = LLSD::emptyMap();
+ wrapped_data["binary-template-data"] = binary_data;
+ result = wrapped_data;
+ }
+ return result;
+}
+
+LLStoredMessagePtr LLMessageSystem::getReceivedMessage() const
+{
+ const std::string& name = mMessageReader->getMessageName();
+ LLSD message = wrapReceivedTemplateData();
+
+ return LLStoredMessagePtr(new LLStoredMessage(name, message));
+}
+
+LLStoredMessagePtr LLMessageSystem::getBuiltMessage() const
+{
+ const std::string& name = mMessageBuilder->getMessageName();
+ LLSD message = wrapBuiltTemplateData();
+
+ return LLStoredMessagePtr(new LLStoredMessage(name, message));
+}
+
+S32 LLMessageSystem::sendMessage(const LLHost &host, LLStoredMessagePtr message)
+{
+ return sendMessage(host, message->mName.c_str(), message->mMessage);
+}
+
+
+void LLMessageSystem::clearMessage()
+{
+ mSendReliable = false;
+ mMessageBuilder->clearMessage();
+}
+
+// set block to add data to within current message
+void LLMessageSystem::nextBlockFast(const char *blockname)
+{
+ mMessageBuilder->nextBlock(blockname);
+}
+
+void LLMessageSystem::nextBlock(const char *blockname)
+{
+ nextBlockFast(LLMessageStringTable::getInstance()->getString(blockname));
+}
+
+bool LLMessageSystem::isSendFull(const char* blockname)
+{
+ char* stringTableName = NULL;
+ if(NULL != blockname)
+ {
+ stringTableName = LLMessageStringTable::getInstance()->getString(blockname);
+ }
+ return isSendFullFast(stringTableName);
+}
+
+bool LLMessageSystem::isSendFullFast(const char* blockname)
+{
+ return mMessageBuilder->isMessageFull(blockname);
+}
+
+
+// blow away the last block of a message, return false if that leaves no blocks or there wasn't a block to remove
+// TODO: Babbage: Remove this horror.
+bool LLMessageSystem::removeLastBlock()
+{
+ return mMessageBuilder->removeLastBlock();
+}
+
+S32 LLMessageSystem::sendReliable(const LLHost &host)
+{
+ return sendReliable(host, LL_DEFAULT_RELIABLE_RETRIES, true, LL_PING_BASED_TIMEOUT_DUMMY, NULL, NULL);
+}
+
+
+S32 LLMessageSystem::sendSemiReliable(const LLHost &host, void (*callback)(void **,S32), void ** callback_data)
+{
+ F32Seconds timeout;
+
+ LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+ if (cdp)
+ {
+ timeout = llmax(LL_MINIMUM_SEMIRELIABLE_TIMEOUT_SECONDS,
+ F32Seconds(LL_SEMIRELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged()));
+ }
+ else
+ {
+ timeout = LL_SEMIRELIABLE_TIMEOUT_FACTOR * LL_AVERAGED_PING_MAX;
+ }
+
+ constexpr S32 retries = 0;
+ constexpr bool ping_based_timeout = false;
+ return sendReliable(host, retries, ping_based_timeout, timeout, callback, callback_data);
+}
+
+// send the message via a UDP packet
+S32 LLMessageSystem::sendReliable( const LLHost &host,
+ S32 retries,
+ bool ping_based_timeout,
+ F32Seconds timeout,
+ void (*callback)(void **,S32),
+ void ** callback_data)
+{
+ if (ping_based_timeout)
+ {
+ LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+ if (cdp)
+ {
+ timeout = llmax(LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS, F32Seconds(LL_RELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged()));
+ }
+ else
+ {
+ timeout = llmax(LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS, F32Seconds(LL_RELIABLE_TIMEOUT_FACTOR * LL_AVERAGED_PING_MAX));
+ }
+ }
+
+ mSendReliable = true;
+ mReliablePacketParams.set(host, retries, ping_based_timeout, timeout,
+ callback, callback_data,
+ const_cast<char*>(mMessageBuilder->getMessageName()));
+ return sendMessage(host);
+}
+
+void LLMessageSystem::forwardMessage(const LLHost &host)
+{
+ copyMessageReceivedToSend();
+ sendMessage(host);
+}
+
+void LLMessageSystem::forwardReliable(const LLHost &host)
+{
+ copyMessageReceivedToSend();
+ sendReliable(host);
+}
+
+void LLMessageSystem::forwardReliable(const U32 circuit_code)
+{
+ copyMessageReceivedToSend();
+ sendReliable(findHost(circuit_code));
+}
+
+S32 LLMessageSystem::forwardReliable( const LLHost &host,
+ S32 retries,
+ bool ping_based_timeout,
+ F32Seconds timeout,
+ void (*callback)(void **,S32),
+ void ** callback_data)
+{
+ copyMessageReceivedToSend();
+ return sendReliable(host, retries, ping_based_timeout, timeout, callback, callback_data);
+}
+
+S32 LLMessageSystem::flushSemiReliable(const LLHost &host, void (*callback)(void **,S32), void ** callback_data)
+{
+ F32Seconds timeout;
+
+ LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+ if (cdp)
+ {
+ timeout = llmax(LL_MINIMUM_SEMIRELIABLE_TIMEOUT_SECONDS,
+ F32Seconds(LL_SEMIRELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged()));
+ }
+ else
+ {
+ timeout = LL_SEMIRELIABLE_TIMEOUT_FACTOR * LL_AVERAGED_PING_MAX;
+ }
+
+ S32 send_bytes = 0;
+ if (mMessageBuilder->getMessageSize())
+ {
+ mSendReliable = true;
+ // No need for ping-based retry as not going to retry
+ mReliablePacketParams.set(host, 0, false, timeout, callback,
+ callback_data,
+ const_cast<char*>(mMessageBuilder->getMessageName()));
+ send_bytes = sendMessage(host);
+ clearMessage();
+ }
+ else
+ {
+ delete callback_data;
+ }
+ return send_bytes;
+}
+
+S32 LLMessageSystem::flushReliable(const LLHost &host)
+{
+ S32 send_bytes = 0;
+ if (mMessageBuilder->getMessageSize())
+ {
+ send_bytes = sendReliable(host);
+ }
+ clearMessage();
+ return send_bytes;
+}
+
+// This can be called from signal handlers,
+// so should should not use LL_INFOS().
+S32 LLMessageSystem::sendMessage(const LLHost &host)
+{
+ if (! mMessageBuilder->isBuilt())
+ {
+ mSendSize = mMessageBuilder->buildMessage(
+ mSendBuffer,
+ MAX_BUFFER_SIZE,
+ 0);
+ }
+
+ if (!(host.isOk())) // if port and ip are zero, don't bother trying to send the message
+ {
+ return 0;
+ }
+
+ LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+ if (!cdp)
+ {
+ // this is a new circuit!
+ // are we protected?
+ if (mbProtected)
+ {
+ // yup! don't send packets to an unknown circuit
+ if(mVerboseLog)
+ {
+ LL_INFOS_ONCE("Messaging") << "MSG: -> " << host << "\tUNKNOWN CIRCUIT:\t"
+ << mMessageBuilder->getMessageName() << LL_ENDL;
+ }
+ LL_WARNS_ONCE("Messaging") << "sendMessage - Trying to send "
+ << mMessageBuilder->getMessageName() << " on unknown circuit "
+ << host << LL_ENDL;
+ return 0;
+ }
+ else
+ {
+ // nope, open the new circuit
+
+ cdp = mCircuitInfo.addCircuitData(host, 0);
+ }
+ }
+ else
+ {
+ // this is an old circuit. . . is it still alive?
+ if (!cdp->isAlive())
+ {
+ // nope. don't send to dead circuits
+ if(mVerboseLog)
+ {
+ LL_INFOS("Messaging") << "MSG: -> " << host << "\tDEAD CIRCUIT\t\t"
+ << mMessageBuilder->getMessageName() << LL_ENDL;
+ }
+ LL_WARNS("Messaging") << "sendMessage - Trying to send message "
+ << mMessageBuilder->getMessageName() << " to dead circuit "
+ << host << LL_ENDL;
+ return 0;
+ }
+ }
+
+ // NOTE: babbage: LLSD message -> HTTP, template message -> UDP
+ if(mMessageBuilder == mLLSDMessageBuilder)
+ {
+ LLSD message = mLLSDMessageBuilder->getMessage();
+
+ UntrustedCallback_t cb = NULL;
+ if ((mSendReliable) && (mReliablePacketParams.mCallback))
+ {
+ cb = boost::bind(mReliablePacketParams.mCallback, mReliablePacketParams.mCallbackData, _1);
+ }
+
+ LLCoros::instance().launch("LLMessageSystem::sendUntrustedSimulatorMessageCoro",
+ boost::bind(&LLMessageSystem::sendUntrustedSimulatorMessageCoro, this,
+ host.getUntrustedSimulatorCap(),
+ mLLSDMessageBuilder->getMessageName(), message, cb));
+
+ mSendReliable = false;
+ mReliablePacketParams.clear();
+ return 1;
+ }
+
+ // zero out the flags and packetid. Subtract 1 here so that we do
+ // not overwrite the offset if it was set set in buildMessage().
+ memset(mSendBuffer, 0, LL_PACKET_ID_SIZE - 1);
+
+ // add the send id to the front of the message
+ cdp->nextPacketOutID();
+
+ // Packet ID size is always 4
+ *((S32*)&mSendBuffer[PHL_PACKET_ID]) = htonl(cdp->getPacketOutID());
+
+ // Compress the message, which will usually reduce its size.
+ U8 * buf_ptr = (U8 *)mSendBuffer;
+ U32 buffer_length = mSendSize;
+ mMessageBuilder->compressMessage(buf_ptr, buffer_length);
+
+ if (buffer_length > 1500)
+ {
+ if((mMessageBuilder->getMessageName() != _PREHASH_ChildAgentUpdate)
+ && (mMessageBuilder->getMessageName() != _PREHASH_SendXferPacket))
+ {
+ LL_WARNS("Messaging") << "sendMessage - Trying to send "
+ << ((buffer_length > 4000) ? "EXTRA " : "")
+ << "BIG message " << mMessageBuilder->getMessageName() << " - "
+ << buffer_length << LL_ENDL;
+ }
+ }
+ if (mSendReliable)
+ {
+ buf_ptr[0] |= LL_RELIABLE_FLAG;
+
+ if (!cdp->getUnackedPacketCount())
+ {
+ // We are adding the first packed onto the unacked packet list(s)
+ // Add this circuit to the list of circuits with unacked packets
+ mCircuitInfo.mUnackedCircuitMap[cdp->mHost] = cdp;
+ }
+
+ cdp->addReliablePacket(mSocket,buf_ptr,buffer_length, &mReliablePacketParams);
+ mReliablePacketsOut++;
+ }
+
+ // tack packet acks onto the end of this message
+ S32 space_left = (MTUBYTES - buffer_length) / sizeof(TPACKETID); // space left for packet ids
+ S32 ack_count = (S32)cdp->mAcks.size();
+ bool is_ack_appended = false;
+ std::vector<TPACKETID> acks;
+ if((space_left > 0) && (ack_count > 0) &&
+ (mMessageBuilder->getMessageName() != _PREHASH_PacketAck))
+ {
+ buf_ptr[0] |= LL_ACK_FLAG;
+ S32 append_ack_count = llmin(space_left, ack_count);
+ const S32 MAX_ACKS = 250;
+ append_ack_count = llmin(append_ack_count, MAX_ACKS);
+ std::vector<TPACKETID>::iterator iter = cdp->mAcks.begin();
+ std::vector<TPACKETID>::iterator last = cdp->mAcks.begin();
+ last += append_ack_count;
+ TPACKETID packet_id;
+ for( ; iter != last ; ++iter)
+ {
+ // grab the next packet id.
+ packet_id = (*iter);
+ if(mVerboseLog)
+ {
+ acks.push_back(packet_id);
+ }
+
+ // put it on the end of the buffer
+ packet_id = htonl(packet_id);
+
+ if((S32)(buffer_length + sizeof(TPACKETID)) < MAX_BUFFER_SIZE)
+ {
+ memcpy(&buf_ptr[buffer_length], &packet_id, sizeof(TPACKETID)); /* Flawfinder: ignore */
+ // Do the accounting
+ buffer_length += sizeof(TPACKETID);
+ }
+ else
+ {
+ // Just reporting error is likely not enough. Need to
+ // check how to abort or error out gracefully from
+ // this function. XXXTBD
+ // *NOTE: Actually hitting this error would indicate
+ // the calculation above for space_left, ack_count,
+ // append_acout_count is incorrect or that
+ // MAX_BUFFER_SIZE has fallen below MTU which is bad
+ // and probably programmer error.
+ LL_ERRS("Messaging") << "Buffer packing failed due to size.." << LL_ENDL;
+ }
+ }
+
+ // clean up the source
+ cdp->mAcks.erase(cdp->mAcks.begin(), last);
+
+ // tack the count in the final byte
+ U8 count = (U8)append_ack_count;
+ buf_ptr[buffer_length++] = count;
+ is_ack_appended = true;
+ }
+
+ bool success;
+ success = mPacketRing.sendPacket(mSocket, (char *)buf_ptr, buffer_length, host);
+
+ if (!success)
+ {
+ mSendPacketFailureCount++;
+ }
+ else
+ {
+ // mCircuitInfo already points to the correct circuit data
+ cdp->addBytesOut( (S32Bytes)buffer_length );
+ }
+
+ if(mVerboseLog)
+ {
+ std::ostringstream str;
+ str << "MSG: -> " << host;
+ std::string buffer;
+ buffer = llformat( "\t%6d\t%6d\t%6d ", mSendSize, buffer_length, cdp->getPacketOutID());
+ str << buffer
+ << mMessageBuilder->getMessageName()
+ << (mSendReliable ? " reliable " : "");
+ if(is_ack_appended)
+ {
+ str << "\tACKS:\t";
+ std::ostream_iterator<TPACKETID> append(str, " ");
+ std::copy(acks.begin(), acks.end(), append);
+ }
+ LL_INFOS("Messaging") << str.str() << LL_ENDL;
+ }
+
+
+ mPacketsOut++;
+ mTotalBytesOut += buffer_length;
+
+ mSendReliable = false;
+ mReliablePacketParams.clear();
+ return buffer_length;
+}
+
+void LLMessageSystem::logMsgFromInvalidCircuit( const LLHost& host, bool recv_reliable )
+{
+ if(mVerboseLog)
+ {
+ std::ostringstream str;
+ str << "MSG: <- " << host;
+ std::string buffer;
+ buffer = llformat( "\t%6d\t%6d\t%6d ", mMessageReader->getMessageSize(), (mIncomingCompressedSize ? mIncomingCompressedSize: mMessageReader->getMessageSize()), mCurrentRecvPacketID);
+ str << buffer
+ << nullToEmpty(mMessageReader->getMessageName())
+ << (recv_reliable ? " reliable" : "")
+ << " REJECTED";
+ LL_INFOS("Messaging") << str.str() << LL_ENDL;
+ }
+ // nope!
+ // cout << "Rejecting unexpected message " << mCurrentMessageTemplate->mName << " from " << hex << ip << " , " << dec << port << endl;
+
+ // Keep track of rejected messages as well
+ if (mNumMessageCounts >= MAX_MESSAGE_COUNT_NUM)
+ {
+ LL_WARNS("Messaging") << "Got more than " << MAX_MESSAGE_COUNT_NUM << " packets without clearing counts" << LL_ENDL;
+ }
+ else
+ {
+ // TODO: babbage: work out if we need these
+ // mMessageCountList[mNumMessageCounts].mMessageNum = mCurrentRMessageTemplate->mMessageNumber;
+ mMessageCountList[mNumMessageCounts].mMessageBytes = mMessageReader->getMessageSize();
+ mMessageCountList[mNumMessageCounts].mInvalid = true;
+ mNumMessageCounts++;
+ }
+}
+
+S32 LLMessageSystem::sendMessage(
+ const LLHost &host,
+ const char* name,
+ const LLSD& message)
+{
+ if (!(host.isOk()))
+ {
+ LL_WARNS("Messaging") << "trying to send message to invalid host" << LL_ENDL;
+ return 0;
+ }
+
+ UntrustedCallback_t cb = NULL;
+ if ((mSendReliable) && (mReliablePacketParams.mCallback))
+ {
+ cb = boost::bind(mReliablePacketParams.mCallback, mReliablePacketParams.mCallbackData, _1);
+ }
+
+ LLCoros::instance().launch("LLMessageSystem::sendUntrustedSimulatorMessageCoro",
+ boost::bind(&LLMessageSystem::sendUntrustedSimulatorMessageCoro, this,
+ host.getUntrustedSimulatorCap(), name, message, cb));
+ return 1;
+}
+
+void LLMessageSystem::logTrustedMsgFromUntrustedCircuit( const LLHost& host )
+{
+ // RequestTrustedCircuit is how we establish trust, so don't spam
+ // if it's received on a trusted circuit. JC
+ if (strcmp(mMessageReader->getMessageName(), "RequestTrustedCircuit"))
+ {
+ LL_WARNS("Messaging") << "Received trusted message on untrusted circuit. "
+ << "Will reply with deny. "
+ << "Message: " << nullToEmpty(mMessageReader->getMessageName())
+ << " Host: " << host << LL_ENDL;
+ }
+
+ if (mNumMessageCounts >= MAX_MESSAGE_COUNT_NUM)
+ {
+ LL_WARNS("Messaging") << "got more than " << MAX_MESSAGE_COUNT_NUM
+ << " packets without clearing counts"
+ << LL_ENDL;
+ }
+ else
+ {
+ // TODO: babbage: work out if we need these
+ //mMessageCountList[mNumMessageCounts].mMessageNum
+ // = mCurrentRMessageTemplate->mMessageNumber;
+ mMessageCountList[mNumMessageCounts].mMessageBytes
+ = mMessageReader->getMessageSize();
+ mMessageCountList[mNumMessageCounts].mInvalid = true;
+ mNumMessageCounts++;
+ }
+}
+
+void LLMessageSystem::logValidMsg(LLCircuitData *cdp, const LLHost& host, bool recv_reliable, bool recv_resent, bool recv_acks )
+{
+ if (mNumMessageCounts >= MAX_MESSAGE_COUNT_NUM)
+ {
+ LL_WARNS("Messaging") << "Got more than " << MAX_MESSAGE_COUNT_NUM << " packets without clearing counts" << LL_ENDL;
+ }
+ else
+ {
+ // TODO: babbage: work out if we need these
+ //mMessageCountList[mNumMessageCounts].mMessageNum = mCurrentRMessageTemplate->mMessageNumber;
+ mMessageCountList[mNumMessageCounts].mMessageBytes = mMessageReader->getMessageSize();
+ mMessageCountList[mNumMessageCounts].mInvalid = false;
+ mNumMessageCounts++;
+ }
+
+ if (cdp)
+ {
+ // update circuit packet ID tracking (missing/out of order packets)
+ cdp->checkPacketInID( mCurrentRecvPacketID, recv_resent );
+ cdp->addBytesIn( (S32Bytes)mTrueReceiveSize );
+ }
+
+ if(mVerboseLog)
+ {
+ std::ostringstream str;
+ str << "MSG: <- " << host;
+ std::string buffer;
+ buffer = llformat( "\t%6d\t%6d\t%6d ", mMessageReader->getMessageSize(), (mIncomingCompressedSize ? mIncomingCompressedSize : mMessageReader->getMessageSize()), mCurrentRecvPacketID);
+ str << buffer
+ << nullToEmpty(mMessageReader->getMessageName())
+ << (recv_reliable ? " reliable" : "")
+ << (recv_resent ? " resent" : "")
+ << (recv_acks ? " acks" : "");
+ LL_INFOS("Messaging") << str.str() << LL_ENDL;
+ }
+}
+
+void LLMessageSystem::sanityCheck()
+{
+// TODO: babbage: reinstate
+
+// if (!mCurrentRMessageData)
+// {
+// LL_ERRS("Messaging") << "mCurrentRMessageData is NULL" << LL_ENDL;
+// }
+
+// if (!mCurrentRMessageTemplate)
+// {
+// LL_ERRS("Messaging") << "mCurrentRMessageTemplate is NULL" << LL_ENDL;
+// }
+
+// if (!mCurrentRTemplateBlock)
+// {
+// LL_ERRS("Messaging") << "mCurrentRTemplateBlock is NULL" << LL_ENDL;
+// }
+
+// if (!mCurrentRDataBlock)
+// {
+// LL_ERRS("Messaging") << "mCurrentRDataBlock is NULL" << LL_ENDL;
+// }
+
+// if (!mCurrentSMessageData)
+// {
+// LL_ERRS("Messaging") << "mCurrentSMessageData is NULL" << LL_ENDL;
+// }
+
+// if (!mCurrentSMessageTemplate)
+// {
+// LL_ERRS("Messaging") << "mCurrentSMessageTemplate is NULL" << LL_ENDL;
+// }
+
+// if (!mCurrentSTemplateBlock)
+// {
+// LL_ERRS("Messaging") << "mCurrentSTemplateBlock is NULL" << LL_ENDL;
+// }
+
+// if (!mCurrentSDataBlock)
+// {
+// LL_ERRS("Messaging") << "mCurrentSDataBlock is NULL" << LL_ENDL;
+// }
+}
+
+void LLMessageSystem::showCircuitInfo()
+{
+ LL_INFOS("Messaging") << mCircuitInfo << LL_ENDL;
+}
+
+
+void LLMessageSystem::dumpCircuitInfo()
+{
+ LL_DEBUGS("Messaging") << mCircuitInfo << LL_ENDL;
+}
+
+/* virtual */
+U32 LLMessageSystem::getOurCircuitCode()
+{
+ return mOurCircuitCode;
+}
+
+void LLMessageSystem::getCircuitInfo(LLSD& info) const
+{
+ mCircuitInfo.getInfo(info);
+}
+
+// returns whether the given host is on a trusted circuit
+bool LLMessageSystem::getCircuitTrust(const LLHost &host)
+{
+ LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+ if (cdp)
+ {
+ return cdp->getTrusted();
+ }
+
+ return false;
+}
+
+// Activate a circuit, and set its trust level (true if trusted,
+// false if not).
+void LLMessageSystem::enableCircuit(const LLHost &host, bool trusted)
+{
+ LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+ if (!cdp)
+ {
+ cdp = mCircuitInfo.addCircuitData(host, 0);
+ }
+ else
+ {
+ cdp->setAlive(true);
+ }
+ cdp->setTrusted(trusted);
+}
+
+void LLMessageSystem::disableCircuit(const LLHost &host)
+{
+ LL_INFOS("Messaging") << "LLMessageSystem::disableCircuit for " << host << LL_ENDL;
+ U32 code = gMessageSystem->findCircuitCode( host );
+
+ // Don't need to do this, as we're removing the circuit info anyway - djs 01/28/03
+
+ // don't clean up 0 circuit code entries
+ // because many hosts (neighbor sims, etc) can have the 0 circuit
+ if (code)
+ {
+ //if (mCircuitCodes.checkKey(code))
+ code_session_map_t::iterator it = mCircuitCodes.find(code);
+ if(it != mCircuitCodes.end())
+ {
+ LL_INFOS("Messaging") << "Circuit " << code << " removed from list" << LL_ENDL;
+ //mCircuitCodes.removeData(code);
+ mCircuitCodes.erase(it);
+ }
+
+ U64 ip_port = 0;
+ std::map<U32, U64>::iterator iter = gMessageSystem->mCircuitCodeToIPPort.find(code);
+ if (iter != gMessageSystem->mCircuitCodeToIPPort.end())
+ {
+ ip_port = iter->second;
+
+ gMessageSystem->mCircuitCodeToIPPort.erase(iter);
+
+ U32 old_port = (U32)(ip_port & (U64)0xFFFFFFFF);
+ U32 old_ip = (U32)(ip_port >> 32);
+
+ LL_INFOS("Messaging") << "Host " << LLHost(old_ip, old_port) << " circuit " << code << " removed from lookup table" << LL_ENDL;
+ gMessageSystem->mIPPortToCircuitCode.erase(ip_port);
+ }
+ mCircuitInfo.removeCircuitData(host);
+ }
+ else
+ {
+ // Sigh, since we can open circuits which don't have circuit
+ // codes, it's possible for this to happen...
+
+ LL_WARNS("Messaging") << "Couldn't find circuit code for " << host << LL_ENDL;
+ }
+
+}
+
+
+void LLMessageSystem::setCircuitAllowTimeout(const LLHost &host, bool allow)
+{
+ LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+ if (cdp)
+ {
+ cdp->setAllowTimeout(allow);
+ }
+}
+
+void LLMessageSystem::setCircuitTimeoutCallback(const LLHost &host, void (*callback_func)(const LLHost & host, void *user_data), void *user_data)
+{
+ LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+ if (cdp)
+ {
+ cdp->setTimeoutCallback(callback_func, user_data);
+ }
+}
+
+
+bool LLMessageSystem::checkCircuitBlocked(const U32 circuit)
+{
+ LLHost host = findHost(circuit);
+
+ if (!host.isOk())
+ {
+ LL_DEBUGS("Messaging") << "checkCircuitBlocked: Unknown circuit " << circuit << LL_ENDL;
+ return true;
+ }
+
+ LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+ if (cdp)
+ {
+ return cdp->isBlocked();
+ }
+ else
+ {
+ LL_INFOS("Messaging") << "checkCircuitBlocked(circuit): Unknown host - " << host << LL_ENDL;
+ return false;
+ }
+}
+
+bool LLMessageSystem::checkCircuitAlive(const U32 circuit)
+{
+ LLHost host = findHost(circuit);
+
+ if (!host.isOk())
+ {
+ LL_DEBUGS("Messaging") << "checkCircuitAlive: Unknown circuit " << circuit << LL_ENDL;
+ return false;
+ }
+
+ LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+ if (cdp)
+ {
+ return cdp->isAlive();
+ }
+ else
+ {
+ LL_INFOS("Messaging") << "checkCircuitAlive(circuit): Unknown host - " << host << LL_ENDL;
+ return false;
+ }
+}
+
+bool LLMessageSystem::checkCircuitAlive(const LLHost &host)
+{
+ LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+ if (cdp)
+ {
+ return cdp->isAlive();
+ }
+ else
+ {
+ LL_DEBUGS("Messaging") << "checkCircuitAlive(host): Unknown host - " << host << LL_ENDL;
+ return false;
+ }
+}
+
+
+void LLMessageSystem::setCircuitProtection(bool b_protect)
+{
+ mbProtected = b_protect;
+}
+
+
+U32 LLMessageSystem::findCircuitCode(const LLHost &host)
+{
+ U64 ip64 = (U64) host.getAddress();
+ U64 port64 = (U64) host.getPort();
+ U64 ip_port = (ip64 << 32) | port64;
+
+ return get_if_there(mIPPortToCircuitCode, ip_port, U32(0));
+}
+
+LLHost LLMessageSystem::findHost(const U32 circuit_code)
+{
+ if (mCircuitCodeToIPPort.count(circuit_code) > 0)
+ {
+ return LLHost(mCircuitCodeToIPPort[circuit_code]);
+ }
+ else
+ {
+ return LLHost();
+ }
+}
+
+void LLMessageSystem::setMaxMessageTime(const F32 seconds)
+{
+ mMaxMessageTime = F32Seconds(seconds);
+}
+
+void LLMessageSystem::setMaxMessageCounts(const S32 num)
+{
+ mMaxMessageCounts = num;
+}
+
+
+std::ostream& operator<<(std::ostream& s, LLMessageSystem &msg)
+{
+ U32 i;
+ if (msg.mbError)
+ {
+ s << "Message system not correctly initialized";
+ }
+ else
+ {
+ s << "Message system open on port " << msg.mPort << " and socket " << msg.mSocket << "\n";
+// s << "Message template file " << msg.mName << " loaded\n";
+
+ s << "\nHigh frequency messages:\n";
+
+ for (i = 1; msg.mMessageNumbers[i] && (i < 255); i++)
+ {
+ s << *(msg.mMessageNumbers[i]);
+ }
+
+ s << "\nMedium frequency messages:\n";
+
+ for (i = (255 << 8) + 1; msg.mMessageNumbers[i] && (i < (255 << 8) + 255); i++)
+ {
+ s << *msg.mMessageNumbers[i];
+ }
+
+ s << "\nLow frequency messages:\n";
+
+ for (i = (0xFFFF0000) + 1; msg.mMessageNumbers[i] && (i < 0xFFFFFFFF); i++)
+ {
+ s << *msg.mMessageNumbers[i];
+ }
+ }
+ return s;
+}
+
+// LLPounceable supports callWhenReady(), to permit clients to queue up (e.g.)
+// callback registrations for when gMessageSystem is first assigned
+LLPounceable<LLMessageSystem*, LLPounceableStatic> gMessageSystem;
+
+// update appropriate ping info
+void process_complete_ping_check(LLMessageSystem *msgsystem, void** /*user_data*/)
+{
+ U8 ping_id;
+ msgsystem->getU8Fast(_PREHASH_PingID, _PREHASH_PingID, ping_id);
+
+ LLCircuitData *cdp;
+ cdp = msgsystem->mCircuitInfo.findCircuit(msgsystem->getSender());
+
+ // stop the appropriate timer
+ if (cdp)
+ {
+ cdp->pingTimerStop(ping_id);
+ }
+}
+
+void process_start_ping_check(LLMessageSystem *msgsystem, void** /*user_data*/)
+{
+ U8 ping_id;
+ msgsystem->getU8Fast(_PREHASH_PingID, _PREHASH_PingID, ping_id);
+
+ LLCircuitData *cdp;
+ cdp = msgsystem->mCircuitInfo.findCircuit(msgsystem->getSender());
+ if (cdp)
+ {
+ // Grab the packet id of the oldest unacked packet
+ U32 packet_id;
+ msgsystem->getU32Fast(_PREHASH_PingID, _PREHASH_OldestUnacked, packet_id);
+ cdp->clearDuplicateList(packet_id);
+ }
+
+ // Send off the response
+ msgsystem->newMessageFast(_PREHASH_CompletePingCheck);
+ msgsystem->nextBlockFast(_PREHASH_PingID);
+ msgsystem->addU8(_PREHASH_PingID, ping_id);
+ msgsystem->sendMessage(msgsystem->getSender());
+}
+
+
+
+// Note: this is currently unused. --mark
+void open_circuit(LLMessageSystem *msgsystem, void** /*user_data*/)
+{
+ U32 ip;
+ U16 port;
+
+ msgsystem->getIPAddrFast(_PREHASH_CircuitInfo, _PREHASH_IP, ip);
+ msgsystem->getIPPortFast(_PREHASH_CircuitInfo, _PREHASH_Port, port);
+
+ // By default, OpenCircuit's are untrusted
+ msgsystem->enableCircuit(LLHost(ip, port), false);
+}
+
+void close_circuit(LLMessageSystem *msgsystem, void** /*user_data*/)
+{
+ msgsystem->disableCircuit(msgsystem->getSender());
+}
+
+// static
+/*
+void LLMessageSystem::processAssignCircuitCode(LLMessageSystem* msg, void**)
+{
+ // if we already have a circuit code, we can bail
+ if(msg->mOurCircuitCode) return;
+ LLUUID session_id;
+ msg->getUUIDFast(_PREHASH_CircuitCode, _PREHASH_SessionID, session_id);
+ if(session_id != msg->getMySessionID())
+ {
+ LL_WARNS("Messaging") << "AssignCircuitCode, bad session id. Expecting "
+ << msg->getMySessionID() << " but got " << session_id
+ << LL_ENDL;
+ return;
+ }
+ U32 code;
+ msg->getU32Fast(_PREHASH_CircuitCode, _PREHASH_Code, code);
+ if (!code)
+ {
+ LL_ERRS("Messaging") << "Assigning circuit code of zero!" << LL_ENDL;
+ }
+
+ msg->mOurCircuitCode = code;
+ LL_INFOS("Messaging") << "Circuit code " << code << " assigned." << LL_ENDL;
+}
+*/
+
+// static
+void LLMessageSystem::processAddCircuitCode(LLMessageSystem* msg, void**)
+{
+ U32 code;
+ msg->getU32Fast(_PREHASH_CircuitCode, _PREHASH_Code, code);
+ LLUUID session_id;
+ msg->getUUIDFast(_PREHASH_CircuitCode, _PREHASH_SessionID, session_id);
+ (void)msg->addCircuitCode(code, session_id);
+
+ // Send the ack back
+ //msg->newMessageFast(_PREHASH_AckAddCircuitCode);
+ //msg->nextBlockFast(_PREHASH_CircuitCode);
+ //msg->addU32Fast(_PREHASH_Code, code);
+ //msg->sendMessage(msg->getSender());
+}
+
+bool LLMessageSystem::addCircuitCode(U32 code, const LLUUID& session_id)
+{
+ if(!code)
+ {
+ LL_WARNS("Messaging") << "addCircuitCode: zero circuit code" << LL_ENDL;
+ return false;
+ }
+ code_session_map_t::iterator it = mCircuitCodes.find(code);
+ if(it == mCircuitCodes.end())
+ {
+ LL_INFOS("Messaging") << "New circuit code " << code << " added" << LL_ENDL;
+ //msg->mCircuitCodes[circuit_code] = circuit_code;
+
+ mCircuitCodes.insert(code_session_map_t::value_type(code, session_id));
+ }
+ else
+ {
+ LL_INFOS("Messaging") << "Duplicate circuit code " << code << " added" << LL_ENDL;
+ }
+ return true;
+}
+
+//void ack_add_circuit_code(LLMessageSystem *msgsystem, void** /*user_data*/)
+//{
+ // By default, we do nothing. This particular message is only handled by the spaceserver
+//}
+
+// static
+void LLMessageSystem::processUseCircuitCode(LLMessageSystem* msg,
+ void** user)
+{
+ U32 circuit_code_in;
+ msg->getU32Fast(_PREHASH_CircuitCode, _PREHASH_Code, circuit_code_in);
+
+ U32 ip = msg->getSenderIP();
+ U32 port = msg->getSenderPort();
+
+ U64 ip64 = ip;
+ U64 port64 = port;
+ U64 ip_port_in = (ip64 << 32) | port64;
+
+ if (circuit_code_in)
+ {
+ //if (!msg->mCircuitCodes.checkKey(circuit_code_in))
+ code_session_map_t::iterator it;
+ it = msg->mCircuitCodes.find(circuit_code_in);
+ if(it == msg->mCircuitCodes.end())
+ {
+ // Whoah, abort! We don't know anything about this circuit code.
+ LL_WARNS("Messaging") << "UseCircuitCode for " << circuit_code_in
+ << " received without AddCircuitCode message - aborting"
+ << LL_ENDL;
+ return;
+ }
+
+ LLUUID id;
+ msg->getUUIDFast(_PREHASH_CircuitCode, _PREHASH_ID, id);
+ LLUUID session_id;
+ msg->getUUIDFast(_PREHASH_CircuitCode, _PREHASH_SessionID, session_id);
+ if(session_id != (*it).second)
+ {
+ LL_WARNS("Messaging") << "UseCircuitCode unmatched session id. Got "
+ << session_id << " but expected " << (*it).second
+ << LL_ENDL;
+ return;
+ }
+
+ // Clean up previous references to this ip/port or circuit
+ U64 ip_port_old = get_if_there(msg->mCircuitCodeToIPPort, circuit_code_in, U64(0));
+ U32 circuit_code_old = get_if_there(msg->mIPPortToCircuitCode, ip_port_in, U32(0));
+
+ if (ip_port_old)
+ {
+ if ((ip_port_old == ip_port_in) && (circuit_code_old == circuit_code_in))
+ {
+ // Current information is the same as incoming info, ignore
+ LL_INFOS("Messaging") << "Got duplicate UseCircuitCode for circuit " << circuit_code_in << " to " << msg->getSender() << LL_ENDL;
+ return;
+ }
+
+ // Hmm, got a different IP and port for the same circuit code.
+ U32 circut_code_old_ip_port = get_if_there(msg->mIPPortToCircuitCode, ip_port_old, U32(0));
+ msg->mCircuitCodeToIPPort.erase(circut_code_old_ip_port);
+ msg->mIPPortToCircuitCode.erase(ip_port_old);
+ U32 old_port = (U32)(ip_port_old & (U64)0xFFFFFFFF);
+ U32 old_ip = (U32)(ip_port_old >> 32);
+ LL_INFOS("Messaging") << "Removing derelict lookup entry for circuit " << circuit_code_old << " to " << LLHost(old_ip, old_port) << LL_ENDL;
+ }
+
+ if (circuit_code_old)
+ {
+ LLHost cur_host(ip, port);
+
+ LL_WARNS("Messaging") << "Disabling existing circuit for " << cur_host << LL_ENDL;
+ msg->disableCircuit(cur_host);
+ if (circuit_code_old == circuit_code_in)
+ {
+ LL_WARNS("Messaging") << "Asymmetrical circuit to ip/port lookup!" << LL_ENDL;
+ LL_WARNS("Messaging") << "Multiple circuit codes for " << cur_host << " probably!" << LL_ENDL;
+ LL_WARNS("Messaging") << "Permanently disabling circuit" << LL_ENDL;
+ return;
+ }
+ else
+ {
+ LL_WARNS("Messaging") << "Circuit code changed for " << msg->getSender()
+ << " from " << circuit_code_old << " to "
+ << circuit_code_in << LL_ENDL;
+ }
+ }
+
+ // Since this comes from the viewer, it's untrusted, but it
+ // passed the circuit code and session id check, so we will go
+ // ahead and persist the ID associated.
+ LLCircuitData *cdp = msg->mCircuitInfo.findCircuit(msg->getSender());
+ bool had_circuit_already = cdp != nullptr;
+
+ msg->enableCircuit(msg->getSender(), false);
+ cdp = msg->mCircuitInfo.findCircuit(msg->getSender());
+ if(cdp)
+ {
+ cdp->setRemoteID(id);
+ cdp->setRemoteSessionID(session_id);
+ }
+
+ if (!had_circuit_already)
+ {
+ //
+ // HACK HACK HACK HACK HACK!
+ //
+ // This would NORMALLY happen inside logValidMsg, but at the point that this happens
+ // inside logValidMsg, there's no circuit for this message yet. So the awful thing that
+ // we do here is do it inside this message handler immediately AFTER the message is
+ // handled.
+ //
+ // We COULD not do this, but then what happens is that some of the circuit bookkeeping
+ // gets broken, especially the packets in count. That causes some later packets to flush
+ // the RecentlyReceivedReliable list, resulting in an error in which UseCircuitCode
+ // doesn't get properly duplicate suppressed. Not a BIG deal, but it's somewhat confusing
+ // (and bad from a state point of view). DJS 9/23/04
+ //
+ cdp->checkPacketInID(gMessageSystem->mCurrentRecvPacketID, false ); // Since this is the first message on the circuit, by definition it's not resent.
+ }
+
+ msg->mIPPortToCircuitCode[ip_port_in] = circuit_code_in;
+ msg->mCircuitCodeToIPPort[circuit_code_in] = ip_port_in;
+
+ LL_INFOS("Messaging") << "Circuit code " << circuit_code_in << " from "
+ << msg->getSender() << " for agent " << id << " in session "
+ << session_id << LL_ENDL;
+
+ const LLUseCircuitCodeResponder* responder =
+ (const LLUseCircuitCodeResponder*) user;
+ if(responder)
+ {
+ responder->complete(msg->getSender(), id);
+ }
+ }
+ else
+ {
+ LL_WARNS("Messaging") << "Got zero circuit code in use_circuit_code" << LL_ENDL;
+ }
+}
+
+// static
+void LLMessageSystem::processError(LLMessageSystem* msg, void**)
+{
+ S32 error_code = 0;
+ msg->getS32("Data", "Code", error_code);
+ std::string error_token;
+ msg->getString("Data", "Token", error_token);
+
+ LLUUID error_id;
+ msg->getUUID("Data", "ID", error_id);
+ std::string error_system;
+ msg->getString("Data", "System", error_system);
+
+ std::string error_message;
+ msg->getString("Data", "Message", error_message);
+
+ LL_WARNS("Messaging") << "Message error from " << msg->getSender() << " - "
+ << error_code << " " << error_token << " " << error_id << " \""
+ << error_system << "\" \"" << error_message << "\"" << LL_ENDL;
+}
+
+
+static LLHTTPNode& messageRootNode()
+{
+ static LLHTTPNode root_node;
+ static bool initialized = false;
+ if (!initialized) {
+ initialized = true;
+ LLHTTPRegistrar::buildAllServices(root_node);
+ }
+
+ return root_node;
+}
+
+//static
+void LLMessageSystem::dispatch(
+ const std::string& msg_name,
+ const LLSD& message)
+{
+ LLPointer<LLSimpleResponse> responsep = LLSimpleResponse::create();
+ dispatch(msg_name, message, responsep);
+}
+
+//static
+void LLMessageSystem::dispatch(
+ const std::string& msg_name,
+ const LLSD& message,
+ LLHTTPNode::ResponsePtr responsep)
+{
+ if ((gMessageSystem->mMessageTemplates.find
+ (LLMessageStringTable::getInstance()->getString(msg_name.c_str())) ==
+ gMessageSystem->mMessageTemplates.end()) &&
+ !LLMessageConfig::isValidMessage(msg_name))
+ {
+ LL_WARNS("Messaging") << "Ignoring unknown message " << msg_name << LL_ENDL;
+ responsep->notFound("Invalid message name");
+ return;
+ }
+
+ std::string path = "/message/" + msg_name;
+ LLSD context;
+ const LLHTTPNode* handler = messageRootNode().traverse(path, context);
+ if (!handler)
+ {
+ LL_WARNS("Messaging") << "LLMessageService::dispatch > no handler for "
+ << path << LL_ENDL;
+ return;
+ }
+ // enable this for output of message names
+ LL_DEBUGS("Messaging") << "< \"" << msg_name << "\"" << LL_ENDL;
+ LL_DEBUGS("Messaging") << "context: " << context << LL_ENDL;
+ LL_DEBUGS("Messaging") << "message: " << message << LL_ENDL;
+
+ handler->post(responsep, context, message);
+}
+
+//static
+void LLMessageSystem::dispatchTemplate(const std::string& msg_name,
+ const LLSD& message,
+ LLHTTPNode::ResponsePtr responsep)
+{
+ LLTemplateMessageDispatcher dispatcher(*(gMessageSystem->mTemplateMessageReader));
+ dispatcher.dispatch(msg_name, message, responsep);
+}
+
+static void check_for_unrecognized_messages(
+ const char* type,
+ const LLSD& map,
+ LLMessageSystem::message_template_name_map_t& templates)
+{
+ for (LLSD::map_const_iterator iter = map.beginMap(),
+ end = map.endMap();
+ iter != end; ++iter)
+ {
+ const char* name = LLMessageStringTable::getInstance()->getString(iter->first.c_str());
+
+ if (templates.find(name) == templates.end())
+ {
+ LL_INFOS("AppInit") << " " << type
+ << " ban list contains unrecognized message "
+ << name << LL_ENDL;
+ }
+ }
+}
+
+void LLMessageSystem::setMessageBans(
+ const LLSD& trusted, const LLSD& untrusted)
+{
+ LL_DEBUGS("AppInit") << "LLMessageSystem::setMessageBans:" << LL_ENDL;
+ bool any_set = false;
+
+ for (message_template_name_map_t::iterator iter = mMessageTemplates.begin(),
+ end = mMessageTemplates.end();
+ iter != end; ++iter)
+ {
+ LLMessageTemplate* mt = iter->second;
+
+ std::string name(mt->mName);
+ bool ban_from_trusted
+ = trusted.has(name) && trusted.get(name).asBoolean();
+ bool ban_from_untrusted
+ = untrusted.has(name) && untrusted.get(name).asBoolean();
+
+ mt->mBanFromTrusted = ban_from_trusted;
+ mt->mBanFromUntrusted = ban_from_untrusted;
+
+ if (ban_from_trusted || ban_from_untrusted)
+ {
+ LL_INFOS("AppInit") << " " << name << " banned from "
+ << (ban_from_trusted ? "TRUSTED " : " ")
+ << (ban_from_untrusted ? "UNTRUSTED " : " ")
+ << LL_ENDL;
+ any_set = true;
+ }
+ }
+
+ if (!any_set)
+ {
+ LL_DEBUGS("AppInit") << " no messages banned" << LL_ENDL;
+ }
+
+ check_for_unrecognized_messages("trusted", trusted, mMessageTemplates);
+ check_for_unrecognized_messages("untrusted", untrusted, mMessageTemplates);
+}
+
+S32 LLMessageSystem::sendError(
+ const LLHost& host,
+ const LLUUID& agent_id,
+ S32 code,
+ const std::string& token,
+ const LLUUID& id,
+ const std::string& system,
+ const std::string& message,
+ const LLSD& data)
+{
+ newMessage("Error");
+ nextBlockFast(_PREHASH_AgentData);
+ addUUIDFast(_PREHASH_AgentID, agent_id);
+ nextBlockFast(_PREHASH_Data);
+ addS32("Code", code);
+ addString("Token", token);
+ addUUID("ID", id);
+ addString("System", system);
+ std::string temp;
+ temp = message;
+ if(temp.size() > (size_t)MTUBYTES) temp.resize((size_t)MTUBYTES);
+ addString("Message", message);
+ LLPointer<LLSDBinaryFormatter> formatter = new LLSDBinaryFormatter;
+ std::ostringstream ostr;
+ formatter->format(data, ostr);
+ temp = ostr.str();
+ bool pack_data = true;
+ static const std::string ERROR_MESSAGE_NAME("Error");
+ if (LLMessageConfig::getMessageFlavor(ERROR_MESSAGE_NAME) ==
+ LLMessageConfig::TEMPLATE_FLAVOR)
+ {
+ S32 msg_size = temp.size() + mMessageBuilder->getMessageSize();
+ if(msg_size >= ETHERNET_MTU_BYTES)
+ {
+ pack_data = false;
+ }
+ }
+ if(pack_data)
+ {
+ addBinaryData("Data", (void*)temp.c_str(), temp.size());
+ }
+ else
+ {
+ LL_WARNS("Messaging") << "Data and message were too large -- data removed."
+ << LL_ENDL;
+ addBinaryData("Data", NULL, 0);
+ }
+ return sendReliable(host);
+}
+
+void process_packet_ack(LLMessageSystem *msgsystem, void** /*user_data*/)
+{
+ TPACKETID packet_id;
+
+ LLHost host = msgsystem->getSender();
+ LLCircuitData *cdp = msgsystem->mCircuitInfo.findCircuit(host);
+ if (cdp)
+ {
+
+ S32 ack_count = msgsystem->getNumberOfBlocksFast(_PREHASH_Packets);
+
+ for (S32 i = 0; i < ack_count; i++)
+ {
+ msgsystem->getU32Fast(_PREHASH_Packets, _PREHASH_ID, packet_id, i);
+// LL_DEBUGS("Messaging") << "ack recvd' from " << host << " for packet " << (TPACKETID)packet_id << LL_ENDL;
+ cdp->ackReliablePacket(packet_id);
+ }
+ if (!cdp->getUnackedPacketCount())
+ {
+ // Remove this circuit from the list of circuits with unacked packets
+ gMessageSystem->mCircuitInfo.mUnackedCircuitMap.erase(host);
+ }
+ }
+}
+
+
+/*
+void process_log_messages(LLMessageSystem* msg, void**)
+{
+ U8 log_message;
+
+ msg->getU8Fast(_PREHASH_Options, _PREHASH_Enable, log_message);
+
+ if (log_message)
+ {
+ LL_INFOS("Messaging") << "Starting logging via message" << LL_ENDL;
+ msg->startLogging();
+ }
+ else
+ {
+ LL_INFOS("Messaging") << "Stopping logging via message" << LL_ENDL;
+ msg->stopLogging();
+ }
+}*/
+
+// Make circuit trusted if the MD5 Digest matches, otherwise
+// notify remote end that they are not trusted.
+void process_create_trusted_circuit(LLMessageSystem *msg, void **)
+{
+ // don't try to create trust on machines with no shared secret
+ std::string shared_secret = get_shared_secret();
+ if(shared_secret.empty()) return;
+
+ LLUUID remote_id;
+ msg->getUUIDFast(_PREHASH_DataBlock, _PREHASH_EndPointID, remote_id);
+
+ LLCircuitData *cdp = msg->mCircuitInfo.findCircuit(msg->getSender());
+ if (!cdp)
+ {
+ LL_WARNS("Messaging") << "Attempt to create trusted circuit without circuit data: "
+ << msg->getSender() << LL_ENDL;
+ return;
+ }
+
+ LLUUID local_id;
+ local_id = cdp->getLocalEndPointID();
+ if (remote_id == local_id)
+ {
+ // Don't respond to requests that use the same end point ID
+ return;
+ }
+
+ U32 untrusted_interface = msg->getUntrustedInterface().getAddress();
+ U32 last_interface = msg->getReceivingInterface().getAddress();
+ if ( ( untrusted_interface != INVALID_HOST_IP_ADDRESS ) && ( untrusted_interface == last_interface ) )
+ {
+ if( msg->getBlockUntrustedInterface() )
+ {
+ LL_WARNS("Messaging") << "Ignoring CreateTrustedCircuit on public interface from host: "
+ << msg->getSender() << LL_ENDL;
+ return;
+ }
+ else
+ {
+ LL_WARNS("Messaging") << "Processing CreateTrustedCircuit on public interface from host: "
+ << msg->getSender() << LL_ENDL;
+ }
+ }
+
+ char their_digest[MD5HEX_STR_SIZE]; /* Flawfinder: ignore */
+ S32 size = msg->getSizeFast(_PREHASH_DataBlock, _PREHASH_Digest);
+ if(size != MD5HEX_STR_BYTES)
+ {
+ // ignore requests which pack the wrong amount of data.
+ return;
+ }
+ msg->getBinaryDataFast(_PREHASH_DataBlock, _PREHASH_Digest, their_digest, MD5HEX_STR_BYTES);
+ their_digest[MD5HEX_STR_SIZE - 1] = '\0';
+ if(msg->isMatchingDigestForWindowAndUUIDs(their_digest, TRUST_TIME_WINDOW, local_id, remote_id))
+ {
+ cdp->setTrusted(true);
+ LL_INFOS("Messaging") << "Trusted digest from " << msg->getSender() << LL_ENDL;
+ return;
+ }
+ else if (cdp->getTrusted())
+ {
+ // The digest is bad, but this circuit is already trusted.
+ // This means that this could just be the result of a stale deny sent from a while back, and
+ // the message system is being slow. Don't bother sending the deny, as it may continually
+ // ping-pong back and forth on a very hosed circuit.
+ LL_WARNS("Messaging") << "Ignoring bad digest from known trusted circuit: " << their_digest
+ << " host: " << msg->getSender() << LL_ENDL;
+ return;
+ }
+ else
+ {
+ LL_WARNS("Messaging") << "Bad digest from known circuit: " << their_digest
+ << " host: " << msg->getSender() << LL_ENDL;
+ msg->sendDenyTrustedCircuit(msg->getSender());
+ return;
+ }
+}
+
+void process_deny_trusted_circuit(LLMessageSystem *msg, void **)
+{
+ // don't try to create trust on machines with no shared secret
+ std::string shared_secret = get_shared_secret();
+ if(shared_secret.empty()) return;
+
+ LLUUID remote_id;
+ msg->getUUIDFast(_PREHASH_DataBlock, _PREHASH_EndPointID, remote_id);
+
+ LLCircuitData *cdp = msg->mCircuitInfo.findCircuit(msg->getSender());
+ if (!cdp)
+ {
+ return;
+ }
+
+ LLUUID local_id;
+ local_id = cdp->getLocalEndPointID();
+ if (remote_id == local_id)
+ {
+ // Don't respond to requests that use the same end point ID
+ return;
+ }
+
+ U32 untrusted_interface = msg->getUntrustedInterface().getAddress();
+ U32 last_interface = msg->getReceivingInterface().getAddress();
+ if ( ( untrusted_interface != INVALID_HOST_IP_ADDRESS ) && ( untrusted_interface == last_interface ) )
+ {
+ if( msg->getBlockUntrustedInterface() )
+ {
+ LL_WARNS("Messaging") << "Ignoring DenyTrustedCircuit on public interface from host: "
+ << msg->getSender() << LL_ENDL;
+ return;
+ }
+ else
+ {
+ LL_WARNS("Messaging") << "Processing DenyTrustedCircuit on public interface from host: "
+ << msg->getSender() << LL_ENDL;
+ }
+ }
+
+
+ // Assume that we require trust to proceed, so resend.
+ // This catches the case where a circuit that was trusted
+ // times out, and allows us to re-establish it, but does
+ // mean that if our shared_secret or clock is wrong, we'll
+ // spin.
+ // *TODO: probably should keep a count of number of resends
+ // per circuit, and stop resending after a while.
+ LL_INFOS("Messaging") << "Got DenyTrustedCircuit. Sending CreateTrustedCircuit to "
+ << msg->getSender() << LL_ENDL;
+ msg->sendCreateTrustedCircuit(msg->getSender(), local_id, remote_id);
+}
+
+
+void dump_prehash_files()
+{
+ U32 i;
+ std::string filename("../../indra/llmessage/message_prehash.h");
+ LLFILE* fp = LLFile::fopen(filename, "w"); /* Flawfinder: ignore */
+ if (fp)
+ {
+ fprintf(
+ fp,
+ "/**\n"
+ " * @file message_prehash.h\n"
+ " * @brief header file of externs of prehashed variables plus defines.\n"
+ " *\n"
+ " * $LicenseInfo:firstyear=2003&license=viewerlgpl$"
+ " * $/LicenseInfo$"
+ " */\n\n"
+ "#ifndef LL_MESSAGE_PREHASH_H\n#define LL_MESSAGE_PREHASH_H\n\n");
+ fprintf(
+ fp,
+ "/**\n"
+ " * Generated from message template version number %.3f\n"
+ " */\n",
+ gMessageSystem->mMessageFileVersionNumber);
+ fprintf(fp, "\n\nextern F32 const gPrehashVersionNumber;\n\n");
+ for (i = 0; i < MESSAGE_NUMBER_OF_HASH_BUCKETS; i++)
+ {
+ if (!LLMessageStringTable::getInstance()->mEmpty[i] && LLMessageStringTable::getInstance()->mString[i][0] != '.')
+ {
+ fprintf(fp, "extern char const* const _PREHASH_%s;\n", LLMessageStringTable::getInstance()->mString[i]);
+ }
+ }
+ fprintf(fp, "\n\n#endif\n");
+ fclose(fp);
+ }
+ filename = std::string("../../indra/llmessage/message_prehash.cpp");
+ fp = LLFile::fopen(filename, "w"); /* Flawfinder: ignore */
+ if (fp)
+ {
+ fprintf(
+ fp,
+ "/**\n"
+ " * @file message_prehash.cpp\n"
+ " * @brief file of prehashed variables\n"
+ " *\n"
+ " * $LicenseInfo:firstyear=2003&license=viewerlgpl$"
+ " * $/LicenseInfo$"
+ " */\n\n"
+ "/**\n"
+ " * Generated from message template version number %.3f\n"
+ " */\n",
+ gMessageSystem->mMessageFileVersionNumber);
+ fprintf(fp, "#include \"linden_common.h\"\n");
+ fprintf(fp, "#include \"message.h\"\n\n");
+ fprintf(fp, "\n\nF32 const gPrehashVersionNumber = %.3ff;\n\n", gMessageSystem->mMessageFileVersionNumber);
+ for (i = 0; i < MESSAGE_NUMBER_OF_HASH_BUCKETS; i++)
+ {
+ if (!LLMessageStringTable::getInstance()->mEmpty[i] && LLMessageStringTable::getInstance()->mString[i][0] != '.')
+ {
+ fprintf(fp, "char const* const _PREHASH_%s = LLMessageStringTable::getInstance()->getString(\"%s\");\n", LLMessageStringTable::getInstance()->mString[i], LLMessageStringTable::getInstance()->mString[i]);
+ }
+ }
+ fclose(fp);
+ }
+}
+
+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,
+ const LLUseCircuitCodeResponder* responder,
+ bool failure_is_fatal,
+ const F32 circuit_heartbeat_interval,
+ const F32 circuit_timeout)
+{
+ gMessageSystem = new LLMessageSystem(
+ template_name,
+ port,
+ version_major,
+ version_minor,
+ version_patch,
+ failure_is_fatal,
+ circuit_heartbeat_interval,
+ circuit_timeout);
+ g_shared_secret.assign(secret);
+
+ if (!gMessageSystem)
+ {
+ LL_ERRS("AppInit") << "Messaging system initialization failed." << LL_ENDL;
+ return false;
+ }
+
+ // bail if system encountered an error.
+ if(!gMessageSystem->isOK())
+ {
+ return false;
+ }
+
+ if (b_dump_prehash_file)
+ {
+ dump_prehash_files();
+ exit(0);
+ }
+ else
+ {
+ if (gMessageSystem->mMessageFileVersionNumber != gPrehashVersionNumber)
+ {
+ LL_INFOS("AppInit") << "Message template version does not match prehash version number" << LL_ENDL;
+ LL_INFOS("AppInit") << "Run simulator with -prehash command line option to rebuild prehash data" << LL_ENDL;
+ }
+ else
+ {
+ LL_DEBUGS("AppInit") << "Message template version matches prehash version number" << LL_ENDL;
+ }
+ }
+
+ gMessageSystem->setHandlerFuncFast(_PREHASH_StartPingCheck, process_start_ping_check, NULL);
+ gMessageSystem->setHandlerFuncFast(_PREHASH_CompletePingCheck, process_complete_ping_check, NULL);
+ gMessageSystem->setHandlerFuncFast(_PREHASH_OpenCircuit, open_circuit, NULL);
+ gMessageSystem->setHandlerFuncFast(_PREHASH_CloseCircuit, close_circuit, NULL);
+
+ //gMessageSystem->setHandlerFuncFast(_PREHASH_AssignCircuitCode, LLMessageSystem::processAssignCircuitCode);
+ gMessageSystem->setHandlerFuncFast(_PREHASH_AddCircuitCode, LLMessageSystem::processAddCircuitCode);
+ //gMessageSystem->setHandlerFuncFast(_PREHASH_AckAddCircuitCode, ack_add_circuit_code, NULL);
+ gMessageSystem->setHandlerFuncFast(_PREHASH_UseCircuitCode, LLMessageSystem::processUseCircuitCode, (void**)responder);
+ gMessageSystem->setHandlerFuncFast(_PREHASH_PacketAck, process_packet_ack, NULL);
+ //gMessageSystem->setHandlerFuncFast(_PREHASH_LogMessages, process_log_messages, NULL);
+ gMessageSystem->setHandlerFuncFast(_PREHASH_CreateTrustedCircuit,
+ process_create_trusted_circuit,
+ NULL);
+ gMessageSystem->setHandlerFuncFast(_PREHASH_DenyTrustedCircuit,
+ process_deny_trusted_circuit,
+ NULL);
+ gMessageSystem->setHandlerFunc("Error", LLMessageSystem::processError);
+
+ // We can hand this to the null_message_callback since it is a
+ // trusted message, so it will automatically be denied if it isn't
+ // trusted and ignored if it is -- exactly what we want.
+ gMessageSystem->setHandlerFunc(
+ "RequestTrustedCircuit",
+ null_message_callback,
+ NULL);
+
+ // Initialize the transfer manager
+ gTransferManager.init();
+
+ return true;
+}
+
+void LLMessageSystem::startLogging()
+{
+ mVerboseLog = true;
+ std::ostringstream str;
+ str << "START MESSAGE LOG" << std::endl;
+ str << "Legend:" << std::endl;
+ str << "\t<-\tincoming message" <<std::endl;
+ str << "\t->\toutgoing message" << std::endl;
+ str << " <> host size zero id name";
+ LL_INFOS("Messaging") << str.str() << LL_ENDL;
+}
+
+void LLMessageSystem::stopLogging()
+{
+ if(mVerboseLog)
+ {
+ mVerboseLog = false;
+ LL_INFOS("Messaging") << "END MESSAGE LOG" << LL_ENDL;
+ }
+}
+
+void LLMessageSystem::summarizeLogs(std::ostream& str)
+{
+ std::string buffer;
+ std::string tmp_str;
+ F32 run_time = mMessageSystemTimer.getElapsedTimeF32();
+ str << "START MESSAGE LOG SUMMARY" << std::endl;
+ buffer = llformat( "Run time: %12.3f seconds", run_time);
+
+ // Incoming
+ str << buffer << std::endl << "Incoming:" << std::endl;
+ tmp_str = U64_to_str(mTotalBytesIn);
+ buffer = llformat( "Total bytes received: %20s (%5.2f kbits per second)", tmp_str.c_str(), ((F32)mTotalBytesIn * 0.008f) / run_time);
+ str << buffer << std::endl;
+ tmp_str = U64_to_str(mPacketsIn);
+ buffer = llformat( "Total packets received: %20s (%5.2f packets per second)", tmp_str.c_str(), ((F32) mPacketsIn / run_time));
+ str << buffer << std::endl;
+ buffer = llformat( "Average packet size: %20.0f bytes", (F32)mTotalBytesIn / (F32)mPacketsIn);
+ str << buffer << std::endl;
+ tmp_str = U64_to_str(mReliablePacketsIn);
+ buffer = llformat( "Total reliable packets: %20s (%5.2f%%)", tmp_str.c_str(), 100.f * ((F32) mReliablePacketsIn)/((F32) mPacketsIn + 1));
+ str << buffer << std::endl;
+ tmp_str = U64_to_str(mCompressedPacketsIn);
+ buffer = llformat( "Total compressed packets: %20s (%5.2f%%)", tmp_str.c_str(), 100.f * ((F32) mCompressedPacketsIn)/((F32) mPacketsIn + 1));
+ str << buffer << std::endl;
+ S64 savings = mUncompressedBytesIn - mCompressedBytesIn;
+ tmp_str = U64_to_str(savings);
+ buffer = llformat( "Total compression savings: %20s bytes", tmp_str.c_str());
+ str << buffer << std::endl;
+ tmp_str = U64_to_str(savings/(mCompressedPacketsIn +1));
+ buffer = llformat( "Avg comp packet savings: %20s (%5.2f : 1)", tmp_str.c_str(), ((F32) mUncompressedBytesIn)/((F32) mCompressedBytesIn+1));
+ str << buffer << std::endl;
+ tmp_str = U64_to_str(savings/(mPacketsIn+1));
+ buffer = llformat( "Avg overall comp savings: %20s (%5.2f : 1)", tmp_str.c_str(), ((F32) mTotalBytesIn + (F32) savings)/((F32) mTotalBytesIn + 1.f));
+
+ // Outgoing
+ str << buffer << std::endl << std::endl << "Outgoing:" << std::endl;
+ tmp_str = U64_to_str(mTotalBytesOut);
+ buffer = llformat( "Total bytes sent: %20s (%5.2f kbits per second)", tmp_str.c_str(), ((F32)mTotalBytesOut * 0.008f) / run_time );
+ str << buffer << std::endl;
+ tmp_str = U64_to_str(mPacketsOut);
+ buffer = llformat( "Total packets sent: %20s (%5.2f packets per second)", tmp_str.c_str(), ((F32)mPacketsOut / run_time));
+ str << buffer << std::endl;
+ buffer = llformat( "Average packet size: %20.0f bytes", (F32)mTotalBytesOut / (F32)mPacketsOut);
+ str << buffer << std::endl;
+ tmp_str = U64_to_str(mReliablePacketsOut);
+ buffer = llformat( "Total reliable packets: %20s (%5.2f%%)", tmp_str.c_str(), 100.f * ((F32) mReliablePacketsOut)/((F32) mPacketsOut + 1));
+ str << buffer << std::endl;
+ tmp_str = U64_to_str(mCompressedPacketsOut);
+ buffer = llformat( "Total compressed packets: %20s (%5.2f%%)", tmp_str.c_str(), 100.f * ((F32) mCompressedPacketsOut)/((F32) mPacketsOut + 1));
+ str << buffer << std::endl;
+ savings = mUncompressedBytesOut - mCompressedBytesOut;
+ tmp_str = U64_to_str(savings);
+ buffer = llformat( "Total compression savings: %20s bytes", tmp_str.c_str());
+ str << buffer << std::endl;
+ tmp_str = U64_to_str(savings/(mCompressedPacketsOut +1));
+ buffer = llformat( "Avg comp packet savings: %20s (%5.2f : 1)", tmp_str.c_str(), ((F32) mUncompressedBytesOut)/((F32) mCompressedBytesOut+1));
+ str << buffer << std::endl;
+ tmp_str = U64_to_str(savings/(mPacketsOut+1));
+ buffer = llformat( "Avg overall comp savings: %20s (%5.2f : 1)", tmp_str.c_str(), ((F32) mTotalBytesOut + (F32) savings)/((F32) mTotalBytesOut + 1.f));
+ str << buffer << std::endl << std::endl;
+ buffer = llformat( "SendPacket failures: %20d", mSendPacketFailureCount);
+ str << buffer << std::endl;
+ buffer = llformat( "Dropped packets: %20d", mDroppedPackets);
+ str << buffer << std::endl;
+ buffer = llformat( "Resent packets: %20d", mResentPackets);
+ str << buffer << std::endl;
+ buffer = llformat( "Failed reliable resends: %20d", mFailedResendPackets);
+ str << buffer << std::endl;
+ buffer = llformat( "Off-circuit rejected packets: %17d", mOffCircuitPackets);
+ str << buffer << std::endl;
+ buffer = llformat( "On-circuit invalid packets: %17d", mInvalidOnCircuitPackets);
+ str << buffer << std::endl << std::endl;
+
+ str << "Decoding: " << std::endl;
+ buffer = llformat( "%35s%10s%10s%10s%10s", "Message", "Count", "Time", "Max", "Avg");
+ str << buffer << std:: endl;
+ F32 avg;
+ for (message_template_name_map_t::const_iterator iter = mMessageTemplates.begin(),
+ end = mMessageTemplates.end();
+ iter != end; iter++)
+ {
+ const LLMessageTemplate* mt = iter->second;
+ if(mt->mTotalDecoded > 0)
+ {
+ avg = mt->mTotalDecodeTime / (F32)mt->mTotalDecoded;
+ buffer = llformat( "%35s%10u%10f%10f%10f", mt->mName, mt->mTotalDecoded, mt->mTotalDecodeTime, mt->mMaxDecodeTimePerMsg, avg);
+ str << buffer << std::endl;
+ }
+ }
+ str << "END MESSAGE LOG SUMMARY" << std::endl;
+}
+
+void end_messaging_system(bool print_summary)
+{
+ gTransferManager.cleanup();
+ LLTransferTargetVFile::updateQueue(true); // shutdown LLTransferTargetVFile
+ if (gMessageSystem)
+ {
+ gMessageSystem->stopLogging();
+
+ if (print_summary)
+ {
+ std::ostringstream str;
+ gMessageSystem->summarizeLogs(str);
+ LL_INFOS("Messaging") << str.str().c_str() << LL_ENDL;
+ }
+
+ delete static_cast<LLMessageSystem*>(gMessageSystem);
+ gMessageSystem = NULL;
+ }
+}
+
+void LLMessageSystem::resetReceiveCounts()
+{
+ mNumMessageCounts = 0;
+
+ for (message_template_name_map_t::iterator iter = mMessageTemplates.begin(),
+ end = mMessageTemplates.end();
+ iter != end; iter++)
+ {
+ LLMessageTemplate* mt = iter->second;
+ mt->mDecodeTimeThisFrame = 0.f;
+ }
+}
+
+
+void LLMessageSystem::dumpReceiveCounts()
+{
+ LLMessageTemplate *mt;
+
+ for (message_template_name_map_t::iterator iter = mMessageTemplates.begin(),
+ end = mMessageTemplates.end();
+ iter != end; iter++)
+ {
+ LLMessageTemplate* mt = iter->second;
+ mt->mReceiveCount = 0;
+ mt->mReceiveBytes = 0;
+ mt->mReceiveInvalid = 0;
+ }
+
+ S32 i;
+ for (i = 0; i < mNumMessageCounts; i++)
+ {
+ mt = get_ptr_in_map(mMessageNumbers,mMessageCountList[i].mMessageNum);
+ if (mt)
+ {
+ mt->mReceiveCount++;
+ mt->mReceiveBytes += mMessageCountList[i].mMessageBytes;
+ if (mMessageCountList[i].mInvalid)
+ {
+ mt->mReceiveInvalid++;
+ }
+ }
+ }
+
+ if(mNumMessageCounts > 0)
+ {
+ LL_DEBUGS("Messaging") << "Dump: " << mNumMessageCounts << " messages processed in " << mReceiveTime << " seconds" << LL_ENDL;
+ for (message_template_name_map_t::const_iterator iter = mMessageTemplates.begin(),
+ end = mMessageTemplates.end();
+ iter != end; iter++)
+ {
+ const LLMessageTemplate* mt = iter->second;
+ if (mt->mReceiveCount > 0)
+ {
+ LL_INFOS("Messaging") << "Num: " << std::setw(3) << mt->mReceiveCount << " Bytes: " << std::setw(6) << mt->mReceiveBytes
+ << " Invalid: " << std::setw(3) << mt->mReceiveInvalid << " " << mt->mName << " " << ll_round(100 * mt->mDecodeTimeThisFrame / mReceiveTime.value()) << "%" << LL_ENDL;
+ }
+ }
+ }
+}
+
+
+
+bool LLMessageSystem::isClear() const
+{
+ return mMessageBuilder->isClear();
+}
+
+
+S32 LLMessageSystem::flush(const LLHost &host)
+{
+ if (mMessageBuilder->getMessageSize())
+ {
+ S32 sentbytes = sendMessage(host);
+ clearMessage();
+ return sentbytes;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+U32 LLMessageSystem::getListenPort( void ) const
+{
+ return mPort;
+}
+
+// TODO: babbage: remove this horror!
+S32 LLMessageSystem::zeroCodeAdjustCurrentSendTotal()
+{
+ if(mMessageBuilder == mLLSDMessageBuilder)
+ {
+ // babbage: don't compress LLSD messages, so delta is 0
+ return 0;
+ }
+
+ if (! mMessageBuilder->isBuilt())
+ {
+ mSendSize = mMessageBuilder->buildMessage(
+ mSendBuffer,
+ MAX_BUFFER_SIZE,
+ 0);
+ }
+ // TODO: babbage: remove this horror
+ mMessageBuilder->setBuilt(false);
+
+ S32 count = mSendSize;
+
+ S32 net_gain = 0;
+ U8 num_zeroes = 0;
+
+ U8 *inptr = (U8 *)mSendBuffer;
+
+// skip the packet id field
+
+ for (U32 ii = 0; ii < LL_PACKET_ID_SIZE; ++ii)
+ {
+ count--;
+ inptr++;
+ }
+
+// don't actually build, just test
+
+// sequential zero bytes are encoded as 0 [U8 count]
+// with 0 0 [count] representing wrap (>256 zeroes)
+
+ while (count--)
+ {
+ if (!(*inptr)) // in a zero count
+ {
+ if (num_zeroes)
+ {
+ if (++num_zeroes > 254)
+ {
+ num_zeroes = 0;
+ }
+ net_gain--; // subseqent zeroes save one
+ }
+ else
+ {
+ net_gain++; // starting a zero count adds one
+ num_zeroes = 1;
+ }
+ inptr++;
+ }
+ else
+ {
+ if (num_zeroes)
+ {
+ num_zeroes = 0;
+ }
+ inptr++;
+ }
+ }
+ if (net_gain < 0)
+ {
+ return net_gain;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+
+
+S32 LLMessageSystem::zeroCodeExpand(U8** data, S32* data_size)
+{
+ if ((*data_size ) < LL_MINIMUM_VALID_PACKET_SIZE)
+ {
+ LL_WARNS("Messaging") << "zeroCodeExpand() called with data_size of " << *data_size
+ << LL_ENDL;
+ }
+
+ mTotalBytesIn += *data_size;
+
+ // if we're not zero-coded, simply return.
+ if (!(*data[0] & LL_ZERO_CODE_FLAG))
+ {
+ return 0;
+ }
+
+ S32 in_size = *data_size;
+ mCompressedPacketsIn++;
+ mCompressedBytesIn += *data_size;
+
+ *data[0] &= (~LL_ZERO_CODE_FLAG);
+
+ S32 count = (*data_size);
+
+ U8 *inptr = (U8 *)*data;
+ U8 *outptr = (U8 *)mEncodedRecvBuffer;
+
+// skip the packet id field
+
+ for (U32 ii = 0; ii < LL_PACKET_ID_SIZE; ++ii)
+ {
+ count--;
+ *outptr++ = *inptr++;
+ }
+
+// reconstruct encoded packet, keeping track of net size gain
+
+// sequential zero bytes are encoded as 0 [U8 count]
+// with 0 0 [count] representing wrap (>256 zeroes)
+
+ while (count--)
+ {
+ if (outptr > (&mEncodedRecvBuffer[MAX_BUFFER_SIZE-1]))
+ {
+ LL_WARNS("Messaging") << "attempt to write past reasonable encoded buffer size 1" << LL_ENDL;
+ callExceptionFunc(MX_WROTE_PAST_BUFFER_SIZE);
+ outptr = mEncodedRecvBuffer;
+ break;
+ }
+ if (!((*outptr++ = *inptr++)))
+ {
+ while (((count--)) && (!(*inptr)))
+ {
+ *outptr++ = *inptr++;
+ if (outptr > (&mEncodedRecvBuffer[MAX_BUFFER_SIZE-256]))
+ {
+ LL_WARNS("Messaging") << "attempt to write past reasonable encoded buffer size 2" << LL_ENDL;
+ callExceptionFunc(MX_WROTE_PAST_BUFFER_SIZE);
+ outptr = mEncodedRecvBuffer;
+ count = -1;
+ break;
+ }
+ memset(outptr,0,255);
+ outptr += 255;
+ }
+
+ if (count < 0)
+ {
+ break;
+ }
+
+ else
+ {
+ if (outptr > (&mEncodedRecvBuffer[MAX_BUFFER_SIZE-(*inptr)]))
+ {
+ LL_WARNS("Messaging") << "attempt to write past reasonable encoded buffer size 3" << LL_ENDL;
+ callExceptionFunc(MX_WROTE_PAST_BUFFER_SIZE);
+ outptr = mEncodedRecvBuffer;
+ }
+ memset(outptr,0,(*inptr) - 1);
+ outptr += ((*inptr) - 1);
+ inptr++;
+ }
+ }
+ }
+
+ *data = mEncodedRecvBuffer;
+ *data_size = (S32)(outptr - mEncodedRecvBuffer);
+ mUncompressedBytesIn += *data_size;
+
+ return(in_size);
+}
+
+
+void LLMessageSystem::addTemplate(LLMessageTemplate *templatep)
+{
+ if (mMessageTemplates.count(templatep->mName) > 0)
+ {
+ LL_ERRS("Messaging") << templatep->mName << " already used as a template name!"
+ << LL_ENDL;
+ }
+ mMessageTemplates[templatep->mName] = templatep;
+ mMessageNumbers[templatep->mMessageNumber] = templatep;
+}
+
+
+void LLMessageSystem::setHandlerFuncFast(const char *name, void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data)
+{
+ LLMessageTemplate* msgtemplate = get_ptr_in_map(mMessageTemplates, name);
+ if (msgtemplate)
+ {
+ msgtemplate->setHandlerFunc(handler_func, user_data);
+ }
+ else
+ {
+ LL_ERRS("Messaging") << name << " is not a known message name!" << LL_ENDL;
+ }
+}
+
+bool LLMessageSystem::callHandler(const char *name,
+ bool trustedSource, LLMessageSystem* msg)
+{
+ name = LLMessageStringTable::getInstance()->getString(name);
+ message_template_name_map_t::const_iterator iter;
+ iter = mMessageTemplates.find(name);
+ if(iter == mMessageTemplates.end())
+ {
+ LL_WARNS("Messaging") << "LLMessageSystem::callHandler: unknown message "
+ << name << LL_ENDL;
+ return false;
+ }
+
+ const LLMessageTemplate* msg_template = iter->second;
+ if (msg_template->isBanned(trustedSource))
+ {
+ LL_WARNS("Messaging") << "LLMessageSystem::callHandler: banned message "
+ << name
+ << " from "
+ << (trustedSource ? "trusted " : "untrusted ")
+ << "source" << LL_ENDL;
+ return false;
+ }
+
+ return msg_template->callHandlerFunc(msg);
+}
+
+
+void LLMessageSystem::setExceptionFunc(EMessageException e,
+ msg_exception_callback func,
+ void* data)
+{
+ callbacks_t::iterator it = mExceptionCallbacks.find(e);
+ if(it != mExceptionCallbacks.end())
+ {
+ mExceptionCallbacks.erase(it);
+ }
+ if(func)
+ {
+ mExceptionCallbacks.insert(callbacks_t::value_type(e, exception_t(func, data)));
+ }
+}
+
+bool LLMessageSystem::callExceptionFunc(EMessageException exception)
+{
+ callbacks_t::iterator it = mExceptionCallbacks.find(exception);
+ if(it == mExceptionCallbacks.end())
+ {
+ return false;
+ }
+
+ exception_t& ex = it->second;
+ msg_exception_callback ex_cb = ex.first;
+
+ if (!ex_cb)
+ {
+ LL_WARNS("Messaging") << "LLMessageSystem::callExceptionFunc: bad message exception callback." << LL_ENDL;
+ return false;
+ }
+
+ (ex_cb)(this, ex.second, exception);
+
+ return true;
+}
+
+void LLMessageSystem::setTimingFunc(msg_timing_callback func, void* data)
+{
+ mTimingCallback = func;
+ mTimingCallbackData = data;
+}
+
+bool LLMessageSystem::isCircuitCodeKnown(U32 code) const
+{
+ if(mCircuitCodes.find(code) == mCircuitCodes.end())
+ return false;
+ return true;
+}
+
+bool LLMessageSystem::isMessageFast(const char *msg)
+{
+ return msg == mMessageReader->getMessageName();
+}
+
+
+char* LLMessageSystem::getMessageName()
+{
+ return const_cast<char*>(mMessageReader->getMessageName());
+}
+
+const LLUUID& LLMessageSystem::getSenderID() const
+{
+ LLCircuitData *cdp = mCircuitInfo.findCircuit(mLastSender);
+ if (cdp)
+ {
+ return (cdp->mRemoteID);
+ }
+
+ return LLUUID::null;
+}
+
+const LLUUID& LLMessageSystem::getSenderSessionID() const
+{
+ LLCircuitData *cdp = mCircuitInfo.findCircuit(mLastSender);
+ if (cdp)
+ {
+ return (cdp->mRemoteSessionID);
+ }
+ return LLUUID::null;
+}
+
+bool LLMessageSystem::generateDigestForNumberAndUUIDs(
+ char* digest,
+ const U32 number,
+ const LLUUID& id1,
+ const LLUUID& id2) const
+{
+ // *NOTE: This method is needlessly inefficient. Instead of
+ // calling LLUUID::asString, it should just call
+ // LLUUID::toString().
+
+ const char *colon = ":";
+ char tbuf[16]; /* Flawfinder: ignore */
+ LLMD5 d;
+ std::string id1string = id1.asString();
+ std::string id2string = id2.asString();
+ std::string shared_secret = get_shared_secret();
+ unsigned char * secret = (unsigned char*)shared_secret.c_str();
+ unsigned char * id1str = (unsigned char*)id1string.c_str();
+ unsigned char * id2str = (unsigned char*)id2string.c_str();
+
+ memset(digest, 0, MD5HEX_STR_SIZE);
+
+ if( secret != NULL)
+ {
+ d.update(secret, (U32)strlen((char *) secret)); /* Flawfinder: ignore */
+ }
+
+ d.update((const unsigned char *) colon, (U32)strlen(colon)); /* Flawfinder: ignore */
+
+ snprintf(tbuf, sizeof(tbuf),"%i", number); /* Flawfinder: ignore */
+ d.update((unsigned char *) tbuf, (U32)strlen(tbuf)); /* Flawfinder: ignore */
+
+ d.update((const unsigned char *) colon, (U32)strlen(colon)); /* Flawfinder: ignore */
+ if( (char*) id1str != NULL)
+ {
+ d.update(id1str, (U32)strlen((char *) id1str)); /* Flawfinder: ignore */
+ }
+ d.update((const unsigned char *) colon, (U32)strlen(colon)); /* Flawfinder: ignore */
+
+ if( (char*) id2str != NULL)
+ {
+ d.update(id2str, (U32)strlen((char *) id2str)); /* Flawfinder: ignore */
+ }
+
+ d.finalize();
+ d.hex_digest(digest);
+ digest[MD5HEX_STR_SIZE - 1] = '\0';
+
+ return true;
+}
+
+bool LLMessageSystem::generateDigestForWindowAndUUIDs(char* digest, const S32 window, const LLUUID &id1, const LLUUID &id2) const
+{
+ if(0 == window) return false;
+ std::string shared_secret = get_shared_secret();
+ if(shared_secret.empty())
+ {
+ LL_ERRS("Messaging") << "Trying to generate complex digest on a machine without a shared secret!" << LL_ENDL;
+ }
+
+ U32 now = (U32)time(NULL);
+
+ now /= window;
+
+ bool result = generateDigestForNumberAndUUIDs(digest, now, id1, id2);
+
+ return result;
+}
+
+bool LLMessageSystem::isMatchingDigestForWindowAndUUIDs(const char* digest, const S32 window, const LLUUID &id1, const LLUUID &id2) const
+{
+ if(0 == window) return false;
+
+ std::string shared_secret = get_shared_secret();
+ if(shared_secret.empty())
+ {
+ LL_ERRS("Messaging") << "Trying to compare complex digests on a machine without a shared secret!" << LL_ENDL;
+ }
+
+ char our_digest[MD5HEX_STR_SIZE]; /* Flawfinder: ignore */
+ U32 now = (U32)time(NULL);
+
+ now /= window;
+
+ // Check 1 window ago, now, and one window from now to catch edge
+ // conditions. Process them as current window, one window ago, and
+ // one window in the future to catch the edges.
+ const S32 WINDOW_BIN_COUNT = 3;
+ U32 window_bin[WINDOW_BIN_COUNT];
+ window_bin[0] = now;
+ window_bin[1] = now - 1;
+ window_bin[2] = now + 1;
+ for(S32 i = 0; i < WINDOW_BIN_COUNT; ++i)
+ {
+ generateDigestForNumberAndUUIDs(our_digest, window_bin[i], id2, id1);
+ if(0 == strncmp(digest, our_digest, MD5HEX_STR_BYTES))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool LLMessageSystem::generateDigestForNumber(char* digest, const U32 number) const
+{
+ memset(digest, 0, MD5HEX_STR_SIZE);
+
+ LLMD5 d;
+ std::string shared_secret = get_shared_secret();
+ d = LLMD5((const unsigned char *)shared_secret.c_str(), number);
+ d.hex_digest(digest);
+ digest[MD5HEX_STR_SIZE - 1] = '\0';
+
+ return true;
+}
+
+bool LLMessageSystem::generateDigestForWindow(char* digest, const S32 window) const
+{
+ if(0 == window) return false;
+
+ std::string shared_secret = get_shared_secret();
+ if(shared_secret.empty())
+ {
+ LL_ERRS("Messaging") << "Trying to generate simple digest on a machine without a shared secret!" << LL_ENDL;
+ }
+
+ U32 now = (U32)time(NULL);
+
+ now /= window;
+
+ bool result = generateDigestForNumber(digest, now);
+
+ return result;
+}
+
+bool LLMessageSystem::isMatchingDigestForWindow(const char* digest, S32 const window) const
+{
+ if(0 == window) return false;
+
+ std::string shared_secret = get_shared_secret();
+ if(shared_secret.empty())
+ {
+ LL_ERRS("Messaging") << "Trying to compare simple digests on a machine without a shared secret!" << LL_ENDL;
+ }
+
+ char our_digest[MD5HEX_STR_SIZE]; /* Flawfinder: ignore */
+ U32 now = (S32)time(NULL);
+
+ now /= window;
+
+ // Check 1 window ago, now, and one window from now to catch edge
+ // conditions. Process them as current window, one window ago, and
+ // one window in the future to catch the edges.
+ const S32 WINDOW_BIN_COUNT = 3;
+ U32 window_bin[WINDOW_BIN_COUNT];
+ window_bin[0] = now;
+ window_bin[1] = now - 1;
+ window_bin[2] = now + 1;
+ for(S32 i = 0; i < WINDOW_BIN_COUNT; ++i)
+ {
+ generateDigestForNumber(our_digest, window_bin[i]);
+ if(0 == strncmp(digest, our_digest, MD5HEX_STR_BYTES))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+void LLMessageSystem::sendCreateTrustedCircuit(const LLHost &host, const LLUUID & id1, const LLUUID & id2)
+{
+ std::string shared_secret = get_shared_secret();
+ if(shared_secret.empty()) return;
+ char digest[MD5HEX_STR_SIZE]; /* Flawfinder: ignore */
+ if (id1.isNull())
+ {
+ LL_WARNS("Messaging") << "Can't send CreateTrustedCircuit to " << host << " because we don't have the local end point ID" << LL_ENDL;
+ return;
+ }
+ if (id2.isNull())
+ {
+ LL_WARNS("Messaging") << "Can't send CreateTrustedCircuit to " << host << " because we don't have the remote end point ID" << LL_ENDL;
+ return;
+ }
+ generateDigestForWindowAndUUIDs(digest, TRUST_TIME_WINDOW, id1, id2);
+ newMessageFast(_PREHASH_CreateTrustedCircuit);
+ nextBlockFast(_PREHASH_DataBlock);
+ addUUIDFast(_PREHASH_EndPointID, id1);
+ addBinaryDataFast(_PREHASH_Digest, digest, MD5HEX_STR_BYTES);
+ LL_INFOS("Messaging") << "xmitting digest: " << digest << " Host: " << host << LL_ENDL;
+ sendMessage(host);
+}
+
+void LLMessageSystem::sendDenyTrustedCircuit(const LLHost &host)
+{
+ mDenyTrustedCircuitSet.insert(host);
+}
+
+void LLMessageSystem::reallySendDenyTrustedCircuit(const LLHost &host)
+{
+ LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+ if (!cdp)
+ {
+ LL_WARNS("Messaging") << "Not sending DenyTrustedCircuit to host without a circuit." << LL_ENDL;
+ return;
+ }
+ LL_INFOS("Messaging") << "Sending DenyTrustedCircuit to " << host << LL_ENDL;
+ newMessageFast(_PREHASH_DenyTrustedCircuit);
+ nextBlockFast(_PREHASH_DataBlock);
+ addUUIDFast(_PREHASH_EndPointID, cdp->getLocalEndPointID());
+ sendMessage(host);
+}
+
+void null_message_callback(LLMessageSystem *msg, void **data)
+{
+ // Nothing should ever go here, but we use this to register messages
+ // that we are expecting to see (and spinning on) at startup.
+ return;
+}
+
+// Try to establish a bidirectional trust metric by pinging a host until it's
+// up, and then sending auth messages.
+void LLMessageSystem::establishBidirectionalTrust(const LLHost &host, S64 frame_count )
+{
+ LockMessageChecker lmc(this);
+
+ std::string shared_secret = get_shared_secret();
+ if(shared_secret.empty())
+ {
+ LL_ERRS("Messaging") << "Trying to establish bidirectional trust on a machine without a shared secret!" << LL_ENDL;
+ }
+ LLTimer timeout;
+
+ timeout.setTimerExpirySec(20.0);
+ setHandlerFuncFast(_PREHASH_StartPingCheck, null_message_callback, NULL);
+ setHandlerFuncFast(_PREHASH_CompletePingCheck, null_message_callback,
+ NULL);
+
+ while (! timeout.hasExpired())
+ {
+ newMessageFast(_PREHASH_StartPingCheck);
+ nextBlockFast(_PREHASH_PingID);
+ addU8Fast(_PREHASH_PingID, 0);
+ addU32Fast(_PREHASH_OldestUnacked, 0);
+ sendMessage(host);
+ if (lmc.checkMessages( frame_count ))
+ {
+ if (isMessageFast(_PREHASH_CompletePingCheck) &&
+ (getSender() == host))
+ {
+ break;
+ }
+ }
+ lmc.processAcks();
+ ms_sleep(1);
+ }
+
+ // Send a request, a deny, and give the host 2 seconds to complete
+ // the trust handshake.
+ newMessage("RequestTrustedCircuit");
+ sendMessage(host);
+ reallySendDenyTrustedCircuit(host);
+ setHandlerFuncFast(_PREHASH_StartPingCheck, process_start_ping_check, NULL);
+ setHandlerFuncFast(_PREHASH_CompletePingCheck, process_complete_ping_check, NULL);
+
+ timeout.setTimerExpirySec(2.0);
+ LLCircuitData* cdp = NULL;
+ while(!timeout.hasExpired())
+ {
+ cdp = mCircuitInfo.findCircuit(host);
+ if(!cdp) break; // no circuit anymore, no point continuing.
+ if(cdp->getTrusted()) break; // circuit is trusted.
+ lmc.checkMessages(frame_count);
+ lmc.processAcks();
+ ms_sleep(1);
+ }
+}
+
+
+void LLMessageSystem::dumpPacketToLog()
+{
+ LL_WARNS("Messaging") << "Packet Dump from:" << mPacketRing.getLastSender() << LL_ENDL;
+ LL_WARNS("Messaging") << "Packet Size:" << mTrueReceiveSize << LL_ENDL;
+ char line_buffer[256]; /* Flawfinder: ignore */
+ S32 i;
+ S32 cur_line_pos = 0;
+ S32 cur_line = 0;
+
+ for (i = 0; i < mTrueReceiveSize; i++)
+ {
+ S32 offset = cur_line_pos * 3;
+ snprintf(line_buffer + offset, sizeof(line_buffer) - offset,
+ "%02x ", mTrueReceiveBuffer[i]); /* Flawfinder: ignore */
+ cur_line_pos++;
+ if (cur_line_pos >= 16)
+ {
+ cur_line_pos = 0;
+ LL_WARNS("Messaging") << "PD:" << cur_line << "PD:" << line_buffer << LL_ENDL;
+ cur_line++;
+ }
+ }
+ if (cur_line_pos)
+ {
+ LL_WARNS("Messaging") << "PD:" << cur_line << "PD:" << line_buffer << LL_ENDL;
+ }
+}
+
+
+//static
+U64Microseconds LLMessageSystem::getMessageTimeUsecs(const bool update)
+{
+ if (gMessageSystem)
+ {
+ if (update)
+ {
+ gMessageSystem->mCurrentMessageTime = totalTime();
+ }
+ return gMessageSystem->mCurrentMessageTime;
+ }
+ else
+ {
+ return totalTime();
+ }
+}
+
+//static
+F64Seconds LLMessageSystem::getMessageTimeSeconds(const bool update)
+{
+ if (gMessageSystem)
+ {
+ if (update)
+ {
+ gMessageSystem->mCurrentMessageTime = totalTime();
+ }
+ return gMessageSystem->mCurrentMessageTime;
+ }
+ else
+ {
+ return F64Seconds(totalTime());
+ }
+}
+
+std::string get_shared_secret()
+{
+ static const std::string SHARED_SECRET_KEY("shared_secret");
+ if(g_shared_secret.empty())
+ {
+ LLApp* app = LLApp::instance();
+ if(app) return app->getOption(SHARED_SECRET_KEY);
+ }
+ return g_shared_secret;
+}
+
+typedef std::map<const char*, LLMessageBuilder*> BuilderMap;
+
+void LLMessageSystem::newMessageFast(const char *name)
+{
+ //LL_DEBUGS("Messaging") << "creating new message: " << name << LL_ENDL;
+ LLMessageConfig::Flavor message_flavor =
+ LLMessageConfig::getMessageFlavor(name);
+ LLMessageConfig::Flavor server_flavor =
+ LLMessageConfig::getServerDefaultFlavor();
+
+ if(message_flavor == LLMessageConfig::TEMPLATE_FLAVOR)
+ {
+ mMessageBuilder = mTemplateMessageBuilder;
+ }
+ else if (message_flavor == LLMessageConfig::LLSD_FLAVOR)
+ {
+ mMessageBuilder = mLLSDMessageBuilder;
+ }
+ // NO_FLAVOR
+ else
+ {
+ if (server_flavor == LLMessageConfig::LLSD_FLAVOR)
+ {
+ mMessageBuilder = mLLSDMessageBuilder;
+ }
+ // TEMPLATE_FLAVOR or NO_FLAVOR
+ else
+ {
+ mMessageBuilder = mTemplateMessageBuilder;
+ }
+ }
+ mSendReliable = false;
+ mMessageBuilder->newMessage(name);
+}
+
+void LLMessageSystem::newMessage(const char *name)
+{
+ newMessageFast(LLMessageStringTable::getInstance()->getString(name));
+}
+
+void LLMessageSystem::addBinaryDataFast(const char *varname, const void *data, S32 size)
+{
+ mMessageBuilder->addBinaryData(varname, data, size);
+}
+
+void LLMessageSystem::addBinaryData(const char *varname, const void *data, S32 size)
+{
+ mMessageBuilder->addBinaryData(LLMessageStringTable::getInstance()->getString(varname),data, size);
+}
+
+void LLMessageSystem::addS8Fast(const char *varname, S8 v)
+{
+ mMessageBuilder->addS8(varname, v);
+}
+
+void LLMessageSystem::addS8(const char *varname, S8 v)
+{
+ mMessageBuilder->addS8(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+void LLMessageSystem::addU8Fast(const char *varname, U8 v)
+{
+ mMessageBuilder->addU8(varname, v);
+}
+
+void LLMessageSystem::addU8(const char *varname, U8 v)
+{
+ mMessageBuilder->addU8(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+void LLMessageSystem::addS16Fast(const char *varname, S16 v)
+{
+ mMessageBuilder->addS16(varname, v);
+}
+
+void LLMessageSystem::addS16(const char *varname, S16 v)
+{
+ mMessageBuilder->addS16(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+void LLMessageSystem::addU16Fast(const char *varname, U16 v)
+{
+ mMessageBuilder->addU16(varname, v);
+}
+
+void LLMessageSystem::addU16(const char *varname, U16 v)
+{
+ mMessageBuilder->addU16(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+void LLMessageSystem::addF32Fast(const char *varname, F32 v)
+{
+ mMessageBuilder->addF32(varname, v);
+}
+
+void LLMessageSystem::addF32(const char *varname, F32 v)
+{
+ mMessageBuilder->addF32(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+void LLMessageSystem::addS32Fast(const char *varname, S32 v)
+{
+ mMessageBuilder->addS32(varname, v);
+}
+
+void LLMessageSystem::addS32(const char *varname, S32 v)
+{
+ mMessageBuilder->addS32(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+void LLMessageSystem::addU32Fast(const char *varname, U32 v)
+{
+ mMessageBuilder->addU32(varname, v);
+}
+
+void LLMessageSystem::addU32(const char *varname, U32 v)
+{
+ mMessageBuilder->addU32(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+void LLMessageSystem::addU64Fast(const char *varname, U64 v)
+{
+ mMessageBuilder->addU64(varname, v);
+}
+
+void LLMessageSystem::addU64(const char *varname, U64 v)
+{
+ mMessageBuilder->addU64(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+void LLMessageSystem::addF64Fast(const char *varname, F64 v)
+{
+ mMessageBuilder->addF64(varname, v);
+}
+
+void LLMessageSystem::addF64(const char *varname, F64 v)
+{
+ mMessageBuilder->addF64(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+void LLMessageSystem::addIPAddrFast(const char *varname, U32 v)
+{
+ mMessageBuilder->addIPAddr(varname, v);
+}
+
+void LLMessageSystem::addIPAddr(const char *varname, U32 v)
+{
+ mMessageBuilder->addIPAddr(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+void LLMessageSystem::addIPPortFast(const char *varname, U16 v)
+{
+ mMessageBuilder->addIPPort(varname, v);
+}
+
+void LLMessageSystem::addIPPort(const char *varname, U16 v)
+{
+ mMessageBuilder->addIPPort(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+void LLMessageSystem::addBOOLFast(const char* varname, bool v)
+{
+ mMessageBuilder->addBOOL(varname, v);
+}
+
+void LLMessageSystem::addBOOL(const char* varname, bool v)
+{
+ mMessageBuilder->addBOOL(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+void LLMessageSystem::addStringFast(const char* varname, const char* v)
+{
+ mMessageBuilder->addString(varname, v);
+}
+
+void LLMessageSystem::addString(const char* varname, const char* v)
+{
+ mMessageBuilder->addString(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+void LLMessageSystem::addStringFast(const char* varname, const std::string& v)
+{
+ mMessageBuilder->addString(varname, v);
+}
+
+void LLMessageSystem::addString(const char* varname, const std::string& v)
+{
+ mMessageBuilder->addString(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+void LLMessageSystem::addVector3Fast(const char *varname, const LLVector3& v)
+{
+ mMessageBuilder->addVector3(varname, v);
+}
+
+void LLMessageSystem::addVector3(const char *varname, const LLVector3& v)
+{
+ mMessageBuilder->addVector3(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+void LLMessageSystem::addVector4Fast(const char *varname, const LLVector4& v)
+{
+ mMessageBuilder->addVector4(varname, v);
+}
+
+void LLMessageSystem::addVector4(const char *varname, const LLVector4& v)
+{
+ mMessageBuilder->addVector4(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+void LLMessageSystem::addVector3dFast(const char *varname, const LLVector3d& v)
+{
+ mMessageBuilder->addVector3d(varname, v);
+}
+
+void LLMessageSystem::addVector3d(const char *varname, const LLVector3d& v)
+{
+ mMessageBuilder->addVector3d(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+void LLMessageSystem::addQuatFast(const char *varname, const LLQuaternion& v)
+{
+ mMessageBuilder->addQuat(varname, v);
+}
+
+void LLMessageSystem::addQuat(const char *varname, const LLQuaternion& v)
+{
+ mMessageBuilder->addQuat(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+
+void LLMessageSystem::addUUIDFast(const char *varname, const LLUUID& v)
+{
+ mMessageBuilder->addUUID(varname, v);
+}
+
+void LLMessageSystem::addUUID(const char *varname, const LLUUID& v)
+{
+ mMessageBuilder->addUUID(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+S32 LLMessageSystem::getCurrentSendTotal() const
+{
+ return mMessageBuilder->getMessageSize();
+}
+
+void LLMessageSystem::getS8Fast(const char *block, const char *var, S8 &u,
+ S32 blocknum)
+{
+ mMessageReader->getS8(block, var, u, blocknum);
+}
+
+void LLMessageSystem::getS8(const char *block, const char *var, S8 &u,
+ S32 blocknum)
+{
+ getS8Fast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), u, blocknum);
+}
+
+void LLMessageSystem::getU8Fast(const char *block, const char *var, U8 &u,
+ S32 blocknum)
+{
+ mMessageReader->getU8(block, var, u, blocknum);
+}
+
+void LLMessageSystem::getU8(const char *block, const char *var, U8 &u,
+ S32 blocknum)
+{
+ getU8Fast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), u, blocknum);
+}
+
+void LLMessageSystem::getBOOLFast(const char *block, const char *var, bool &b,
+ S32 blocknum)
+{
+ mMessageReader->getBOOL(block, var, b, blocknum);
+}
+
+void LLMessageSystem::getBOOL(const char *block, const char *var, bool &b,
+ S32 blocknum)
+{
+ getBOOLFast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), b, blocknum);
+}
+
+void LLMessageSystem::getS16Fast(const char *block, const char *var, S16 &d,
+ S32 blocknum)
+{
+ mMessageReader->getS16(block, var, d, blocknum);
+}
+
+void LLMessageSystem::getS16(const char *block, const char *var, S16 &d,
+ S32 blocknum)
+{
+ getS16Fast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), d, blocknum);
+}
+
+void LLMessageSystem::getU16Fast(const char *block, const char *var, U16 &d,
+ S32 blocknum)
+{
+ mMessageReader->getU16(block, var, d, blocknum);
+}
+
+void LLMessageSystem::getU16(const char *block, const char *var, U16 &d,
+ S32 blocknum)
+{
+ getU16Fast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), d, blocknum);
+}
+
+void LLMessageSystem::getS32Fast(const char *block, const char *var, S32 &d,
+ S32 blocknum)
+{
+ mMessageReader->getS32(block, var, d, blocknum);
+}
+
+void LLMessageSystem::getS32(const char *block, const char *var, S32 &d,
+ S32 blocknum)
+{
+ getS32Fast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), d, blocknum);
+}
+
+void LLMessageSystem::getU32Fast(const char *block, const char *var, U32 &d,
+ S32 blocknum)
+{
+ mMessageReader->getU32(block, var, d, blocknum);
+}
+
+void LLMessageSystem::getU32(const char *block, const char *var, U32 &d,
+ S32 blocknum)
+{
+ getU32Fast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), d, blocknum);
+}
+
+void LLMessageSystem::getU64Fast(const char *block, const char *var, U64 &d,
+ S32 blocknum)
+{
+ mMessageReader->getU64(block, var, d, blocknum);
+}
+
+void LLMessageSystem::getU64(const char *block, const char *var, U64 &d,
+ S32 blocknum)
+{
+
+ getU64Fast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), d, blocknum);
+}
+
+void LLMessageSystem::getBinaryDataFast(const char *blockname,
+ const char *varname,
+ void *datap, S32 size,
+ S32 blocknum, S32 max_size)
+{
+ mMessageReader->getBinaryData(blockname, varname, datap, size, blocknum,
+ max_size);
+}
+
+void LLMessageSystem::getBinaryData(const char *blockname,
+ const char *varname,
+ void *datap, S32 size,
+ S32 blocknum, S32 max_size)
+{
+ getBinaryDataFast(LLMessageStringTable::getInstance()->getString(blockname),
+ LLMessageStringTable::getInstance()->getString(varname),
+ datap, size, blocknum, max_size);
+}
+
+void LLMessageSystem::getF32Fast(const char *block, const char *var, F32 &d,
+ S32 blocknum)
+{
+ mMessageReader->getF32(block, var, d, blocknum);
+}
+
+void LLMessageSystem::getF32(const char *block, const char *var, F32 &d,
+ S32 blocknum)
+{
+ getF32Fast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), d, blocknum);
+}
+
+void LLMessageSystem::getF64Fast(const char *block, const char *var, F64 &d,
+ S32 blocknum)
+{
+ mMessageReader->getF64(block, var, d, blocknum);
+}
+
+void LLMessageSystem::getF64(const char *block, const char *var, F64 &d,
+ S32 blocknum)
+{
+ getF64Fast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), d, blocknum);
+}
+
+
+void LLMessageSystem::getVector3Fast(const char *block, const char *var,
+ LLVector3 &v, S32 blocknum )
+{
+ mMessageReader->getVector3(block, var, v, blocknum);
+}
+
+void LLMessageSystem::getVector3(const char *block, const char *var,
+ LLVector3 &v, S32 blocknum )
+{
+ getVector3Fast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), v, blocknum);
+}
+
+void LLMessageSystem::getVector4Fast(const char *block, const char *var,
+ LLVector4 &v, S32 blocknum )
+{
+ mMessageReader->getVector4(block, var, v, blocknum);
+}
+
+void LLMessageSystem::getVector4(const char *block, const char *var,
+ LLVector4 &v, S32 blocknum )
+{
+ getVector4Fast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), v, blocknum);
+}
+
+void LLMessageSystem::getVector3dFast(const char *block, const char *var,
+ LLVector3d &v, S32 blocknum )
+{
+ mMessageReader->getVector3d(block, var, v, blocknum);
+}
+
+void LLMessageSystem::getVector3d(const char *block, const char *var,
+ LLVector3d &v, S32 blocknum )
+{
+ getVector3dFast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), v, blocknum);
+}
+
+void LLMessageSystem::getQuatFast(const char *block, const char *var,
+ LLQuaternion &q, S32 blocknum )
+{
+ mMessageReader->getQuat(block, var, q, blocknum);
+}
+
+void LLMessageSystem::getQuat(const char *block, const char *var,
+ LLQuaternion &q, S32 blocknum)
+{
+ getQuatFast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), q, blocknum);
+}
+
+void LLMessageSystem::getUUIDFast(const char *block, const char *var,
+ LLUUID &u, S32 blocknum )
+{
+ mMessageReader->getUUID(block, var, u, blocknum);
+}
+
+void LLMessageSystem::getUUID(const char *block, const char *var, LLUUID &u,
+ S32 blocknum )
+{
+ getUUIDFast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), u, blocknum);
+}
+
+void LLMessageSystem::getIPAddrFast(const char *block, const char *var,
+ U32 &u, S32 blocknum)
+{
+ mMessageReader->getIPAddr(block, var, u, blocknum);
+}
+
+void LLMessageSystem::getIPAddr(const char *block, const char *var, U32 &u,
+ S32 blocknum)
+{
+ getIPAddrFast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), u, blocknum);
+}
+
+void LLMessageSystem::getIPPortFast(const char *block, const char *var,
+ U16 &u, S32 blocknum)
+{
+ mMessageReader->getIPPort(block, var, u, blocknum);
+}
+
+void LLMessageSystem::getIPPort(const char *block, const char *var, U16 &u,
+ S32 blocknum)
+{
+ getIPPortFast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), u,
+ blocknum);
+}
+
+
+void LLMessageSystem::getStringFast(const char *block, const char *var,
+ S32 buffer_size, char *s, S32 blocknum)
+{
+ if(buffer_size <= 0)
+ {
+ LL_WARNS("Messaging") << "buffer_size <= 0" << LL_ENDL;
+ }
+ mMessageReader->getString(block, var, buffer_size, s, blocknum);
+}
+
+void LLMessageSystem::getString(const char *block, const char *var,
+ S32 buffer_size, char *s, S32 blocknum )
+{
+ getStringFast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), buffer_size, s,
+ blocknum);
+}
+
+void LLMessageSystem::getStringFast(const char *block, const char *var,
+ std::string& outstr, S32 blocknum)
+{
+ mMessageReader->getString(block, var, outstr, blocknum);
+}
+
+void LLMessageSystem::getString(const char *block, const char *var,
+ std::string& outstr, S32 blocknum )
+{
+ getStringFast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), outstr,
+ blocknum);
+}
+
+bool LLMessageSystem::has(const char *blockname) const
+{
+ return getNumberOfBlocks(blockname) > 0;
+}
+
+S32 LLMessageSystem::getNumberOfBlocksFast(const char *blockname) const
+{
+ return mMessageReader->getNumberOfBlocks(blockname);
+}
+
+S32 LLMessageSystem::getNumberOfBlocks(const char *blockname) const
+{
+ return getNumberOfBlocksFast(LLMessageStringTable::getInstance()->getString(blockname));
+}
+
+S32 LLMessageSystem::getSizeFast(const char *blockname, const char *varname) const
+{
+ return mMessageReader->getSize(blockname, varname);
+}
+
+S32 LLMessageSystem::getSize(const char *blockname, const char *varname) const
+{
+ return getSizeFast(LLMessageStringTable::getInstance()->getString(blockname),
+ LLMessageStringTable::getInstance()->getString(varname));
+}
+
+// size in bytes of variable length data
+S32 LLMessageSystem::getSizeFast(const char *blockname, S32 blocknum,
+ const char *varname) const
+{
+ return mMessageReader->getSize(blockname, blocknum, varname);
+}
+
+S32 LLMessageSystem::getSize(const char *blockname, S32 blocknum,
+ const char *varname) const
+{
+ return getSizeFast(LLMessageStringTable::getInstance()->getString(blockname), blocknum,
+ LLMessageStringTable::getInstance()->getString(varname));
+}
+
+S32 LLMessageSystem::getReceiveSize() const
+{
+ return mMessageReader->getMessageSize();
+}
+
+//static
+void LLMessageSystem::setTimeDecodes( bool b )
+{
+ LLMessageReader::setTimeDecodes(b);
+}
+
+//static
+void LLMessageSystem::setTimeDecodesSpamThreshold( F32 seconds )
+{
+ LLMessageReader::setTimeDecodesSpamThreshold(seconds);
+}
+
+LockMessageChecker::LockMessageChecker(LLMessageSystem* msgsystem):
+ // for the lifespan of this LockMessageChecker instance, use
+ // LLTemplateMessageReader as msgsystem's mMessageReader
+ LockMessageReader(msgsystem->mMessageReader, msgsystem->mTemplateMessageReader),
+ mMessageSystem(msgsystem)
+{}
+
+// HACK! babbage: return true if message rxed via either UDP or HTTP
+// TODO: babbage: move gServicePump in to LLMessageSystem?
+bool LLMessageSystem::checkAllMessages(LockMessageChecker& lmc, S64 frame_count, LLPumpIO* http_pump)
+{
+ if(lmc.checkMessages(frame_count))
+ {
+ return true;
+ }
+ U32 packetsIn = mPacketsIn;
+ http_pump->pump();
+ http_pump->callback();
+ return (mPacketsIn - packetsIn) > 0;
+}
+
+void LLMessageSystem::banUdpMessage(const std::string& name)
+{
+ message_template_name_map_t::iterator itt = mMessageTemplates.find(
+ LLMessageStringTable::getInstance()->getString(name.c_str())
+ );
+ if(itt != mMessageTemplates.end())
+ {
+ itt->second->banUdp();
+ }
+ else
+ {
+ LL_WARNS() << "Attempted to ban an unknown message: " << name << "." << LL_ENDL;
+ }
+}
+const LLHost& LLMessageSystem::getSender() const
+{
+ return mLastSender;
+}
+
+void LLMessageSystem::sendUntrustedSimulatorMessageCoro(std::string url, std::string message, LLSD body, UntrustedCallback_t callback)
+{
+ LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+ httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("untrustedSimulatorMessage", httpPolicy));
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+ LLCore::HttpOptions::ptr_t httpOpts = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions);
+
+
+ if (url.empty())
+ {
+ LL_WARNS() << "sendUntrustedSimulatorMessageCoro called with empty capability!" << LL_ENDL;
+ return;
+ }
+
+ LL_INFOS() << "sendUntrustedSimulatorMessageCoro: message " << message << " to cap " << url << LL_ENDL;
+ LLSD postData;
+ postData["message"] = message;
+ postData["body"] = body;
+
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData, httpOpts);
+
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+ if ((callback) && (!callback.empty()))
+ callback((status) ? LL_ERR_NOERR : LL_ERR_TCP_TIMEOUT);
+}
+
+
+LLHTTPRegistration<LLHTTPNodeAdapter<LLTrustedMessageService> >
+ gHTTPRegistrationTrustedMessageWildcard("/trusted-message/<message-name>");
+