/indra/llmessage/message.cpp
C++ | 2414 lines | 1773 code | 315 blank | 326 comment | 219 complexity | 8400c111b21e6920cc8d92b43a44cd55 MD5 | raw file
Possible License(s): LGPL-2.1
Large files files are truncated, but you can click here to view the full file
- /**
- * @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 "indra_constants.h"
- #include "lldarray.h"
- #include "lldir.h"
- #include "llerror.h"
- #include "llerrorlegacy.h"
- #include "llfasttimer.h"
- #include "llhttpclient.h"
- #include "llhttpnodeadapter.h"
- #include "llhttpsender.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 "timing.h"
- #include "llquaternion.h"
- #include "u64.h"
- #include "v3dmath.h"
- #include "v3math.h"
- #include "v4math.h"
- #include "lltransfertargetvfile.h"
- #include "llmemtype.h"
- // Constants
- //const char* MESSAGE_LOG_FILENAME = "message.log";
- static const F32 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;
- };
- namespace
- {
- class LLFnPtrResponder : public LLHTTPClient::Responder
- {
- LOG_CLASS(LLFnPtrResponder);
- public:
- LLFnPtrResponder(void (*callback)(void **,S32), void **callbackData, const std::string& name) :
- mCallback(callback),
- mCallbackData(callbackData),
- mMessageName(name)
- {
- }
- virtual void error(U32 status, const std::string& reason)
- {
- // don't spam when agent communication disconnected already
- if (status != 410)
- {
- LL_WARNS("Messaging") << "error status " << status
- << " for message " << mMessageName
- << " reason " << reason << llendl;
- }
- // TODO: Map status in to useful error code.
- if(NULL != mCallback) mCallback(mCallbackData, LL_ERR_TCP_TIMEOUT);
- }
-
- virtual void result(const LLSD& content)
- {
- if(NULL != mCallback) mCallback(mCallbackData, LL_ERR_NOERR);
- }
- private:
- void (*mCallback)(void **,S32);
- void **mCallbackData;
- std::string mMessageName;
- };
- }
- 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["request"]["wildcard"]["message-name"];
- char* namePtr = LLMessageStringTable::getInstance()->getString(name.c_str());
-
- lldebugs << "Setting mLastSender " << input["sender"].asString() << llendl;
- gMessageSystem->mLastSender = LLHost(input["sender"].asString());
- gMessageSystem->mPacketsIn += 1;
- gMessageSystem->mLLSDMessageReader->setMessage(namePtr, input["body"]);
- 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;
- 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(circuit_heartbeat_interval, 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 = 60.f; // seconds
- loadTemplateFile(filename, failure_is_fatal);
- mTemplateMessageBuilder = new LLTemplateMessageBuilder(mMessageTemplates);
- mLLSDMessageBuilder = new LLSDMessageBuilder();
- mMessageBuilder = NULL;
- mTemplateMessageReader = new LLTemplateMessageReader(mMessageNumbers);
- mLLSDMessageReader = new LLSDMessageReader();
- mMessageReader = NULL;
- // 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 << llendl;
- //
- // Create the data structure that we can poll on
- //
- if (!gAPRPoolp)
- {
- LL_ERRS("Messaging") << "No APR pool before message system initialization!" << llendl;
- 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;
- F64 mt_sec = getMessageTimeSeconds();
- mResendDumpTime = mt_sec;
- mMessageCountTime = mt_sec;
- mCircuitPrintTime = mt_sec;
- mCurrentMessageTimeSeconds = mt_sec;
- // Constants for dumping output based on message processing time/count
- mNumMessageCounts = 0;
- mMaxMessageCounts = 200; // >= 0 means dump warnings
- mMaxMessageTime = 1.f;
- mTrueReceiveSize = 0;
- mReceiveTime = 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" << llendl;
- 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 << llendl;
- } else {
- LL_WARNS("Messaging") << "Failed to open template: " << filename << llendl;
- }
- mbError = TRUE;
- return;
- }
-
- LLTemplateTokenizer tokens(template_body);
- LLTemplateParser parsed(tokens);
- mMessageFileVersionNumber = parsed.getVersion();
- for(LLTemplateParser::message_iterator iter = parsed.getMessagesBegin();
- iter != parsed.getMessagesEnd();
- iter++)
- {
- addTemplate(*iter);
- }
- }
- 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;
- mMessageReader = 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.
- BOOL LLMessageSystem::checkMessages( S64 frame_count )
- {
- // Pump
- BOOL valid_packet = FALSE;
- mMessageReader = mTemplateMessageReader;
- 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.
- mCurrentMessageTimeSeconds = totalTime() * SEC_PER_USEC;
- 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 << llendl;
- 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
- << llendl;
- 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 << llendl;
- 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
- // << llendl;
- //}
- // ***************************************
- //mCircuitInfo.mCurrentCircuit->mAcks.put(mCurrentRecvPacketID);
- cdp->collectRAck(mCurrentRecvPacketID);
- }
-
- LL_DEBUGS("Messaging") << "Discarding duplicate resend from " << host << llendl;
- 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() << llendl;
- }
- 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, (BOOL)(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 << llendl;
- mOffCircuitPackets++;
- }
- else
- {
- mInvalidOnCircuitPackets++;
- }
- }
- }
- } while (!valid_packet && receive_size > 0);
- F64 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()
- {
- LLMemType mt_pa(LLMemType::MTYPE_MESSAGE_PROCESS_ACKS);
- F64 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();
- if (!mDenyTrustedCircuitSet.empty())
- {
- LL_INFOS("Messaging") << "Sending queued DenyTrustedCircuit messages." << llendl;
- 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 >= 0.f)
- {
- // This is one of the only places where we're required to get REAL message system time.
- mReceiveTime = (F32)(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?
- llerrs << "Message not built as LLSD." << llendl;
- }
- 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)
- {
- F32 timeout;
- LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
- if (cdp)
- {
- timeout = llmax(LL_MINIMUM_SEMIRELIABLE_TIMEOUT_SECONDS,
- LL_SEMIRELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged());
- }
- else
- {
- timeout = LL_SEMIRELIABLE_TIMEOUT_FACTOR * LL_AVERAGED_PING_MAX;
- }
- const S32 retries = 0;
- const 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,
- F32 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, LL_RELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged());
- }
- else
- {
- timeout = llmax(LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS, 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,
- F32 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)
- {
- F32 timeout;
- LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
- if (cdp)
- {
- timeout = llmax(LL_MINIMUM_SEMIRELIABLE_TIMEOUT_SECONDS,
- 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;
- }
- LLHTTPClient::ResponderPtr LLMessageSystem::createResponder(const std::string& name)
- {
- if(mSendReliable)
- {
- return new LLFnPtrResponder(
- mReliablePacketParams.mCallback,
- mReliablePacketParams.mCallbackData,
- name);
- }
- else
- {
- // These messages aren't really unreliable, they just weren't
- // explicitly sent as reliable, so they don't have a callback
- // LL_WARNS("Messaging") << "LLMessageSystem::sendMessage: Sending unreliable "
- // << mMessageBuilder->getMessageName() << " message via HTTP"
- // << llendl;
- return new LLFnPtrResponder(
- NULL,
- NULL,
- name);
- }
- }
- // This can be called from signal handlers,
- // so should should not use llinfos.
- 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() << llendl;
- }
- LL_WARNS_ONCE("Messaging") << "sendMessage - Trying to send "
- << mMessageBuilder->getMessageName() << " on unknown circuit "
- << host << llendl;
- 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() << llendl;
- }
- LL_WARNS("Messaging") << "sendMessage - Trying to send message "
- << mMessageBuilder->getMessageName() << " to dead circuit "
- << host << llendl;
- return 0;
- }
- }
- // NOTE: babbage: LLSD message -> HTTP, template message -> UDP
- if(mMessageBuilder == mLLSDMessageBuilder)
- {
- LLSD message = mLLSDMessageBuilder->getMessage();
-
- const LLHTTPSender& sender = LLHTTPSender::getSender(host);
- sender.send(
- host,
- mLLSDMessageBuilder->getMessageName(),
- message,
- createResponder(mLLSDMessageBuilder->getMessageName()));
- 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 << llendl;
- }
- }
- 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.." << llendl;
- }
- }
- // 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( 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() << llendl;
- }
- mPacketsOut++;
- mBytesOut += 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() << llendl;
- }
- // 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" << llendl;
- }
- 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" << llendl;
- return 0;
- }
- const LLHTTPSender& sender = LLHTTPSender::getSender(host);
- sender.send(host, name, message, createResponder(name));
- 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 << llendl;
- }
- if (mNumMessageCounts >= MAX_MESSAGE_COUNT_NUM)
- {
- LL_WARNS("Messaging") << "got more than " << MAX_MESSAGE_COUNT_NUM
- << " packets without clearing counts"
- << llendl;
- }
- 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" << llendl;
- }
- 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( 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() << llendl;
- }
- }
- void LLMessageSystem::sanityCheck()
- {
- // TODO: babbage: reinstate
- // if (!mCurrentRMessageData)
- // {
- // LL_ERRS("Messaging") << "mCurrentRMessageData is NULL" << llendl;
- // }
- // if (!mCurrentRMessageTemplate)
- // {
- // LL_ERRS("Messaging") << "mCurrentRMessageTemplate is NULL" << llendl;
- // }
- // if (!mCurrentRTemplateBlock)
- // {
- // LL_ERRS("Messaging") << "mCurrentRTemplateBlock is NULL" << llendl;
- // }
- // if (!mCurrentRDataBlock)
- // {
- // LL_ERRS("Messaging") << "mCurrentRDataBlock is NULL" << llendl;
- // }
- // if (!mCurrentSMessageData)
- // {
- // LL_ERRS("Messaging") << "mCurrentSMessageData is NULL" << llendl;
- // }
- // if (!mCurrentSMessageTemplate)
- // {
- // LL_ERRS("Messaging") << "mCurrentSMessageTemplate is NULL" << llendl;
- // }
- // if (!mCurrentSTemplateBlock)
- // {
- // LL_ERRS("Messaging") << "mCurrentSTemplateBlock is NULL" << llendl;
- // }
- // if (!mCurrentSDataBlock)
- // {
- // LL_ERRS("Messaging") << "mCurrentSDataBlock is NULL" << llendl;
- // }
- }
- void LLMessageSystem::showCircuitInfo()
- {
- LL_INFOS("Messaging") << mCircuitInfo << llendl;
- }
- void LLMessageSystem::dumpCircuitInfo()
- {
- lldebugst(LLERR_CIRCUIT_INFO) << mCircuitInfo << llendl;
- }
- /* 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 << llendl;
- 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" << llendl;
- //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" << llendl;
- 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 << llendl;
- }
- }
- 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 << llendl;
- return TRUE;
- }
- LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
- if (cdp)
- {
- return cdp->isBlocked();
- }
- else
- {
- LL_INFOS("Messaging") << "checkCircuitBlocked(circuit): Unknown host - " << host << llendl;
- return FALSE;
- }
- }
- BOOL LLMessageSystem::checkCircuitAlive(const U32 circuit)
- {
- LLHost host = findHost(circuit);
- if (!host.isOk())
- {
- LL_DEBUGS("Messaging") << "checkCircuitAlive: Unknown circuit " << circuit << llendl;
- return FALSE;
- }
- LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
- if (cdp)
- {
- return cdp->isAlive();
- }
- else
- {
- LL_INFOS("Messaging") << "checkCircuitAlive(circuit): Unknown host - " << host << llendl;
- 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 << llendl;
- 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::invalid;
- }
- }
- void LLMessageSystem::setMaxMessageTime(const F32 seconds)
- {
- mMaxMessageTime = 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;
- }
- LLMessageSystem *gMessageSystem = NULL;
- // 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
- << llendl;
- return;
- }
- U32 code;
- msg->getU32Fast(_PREHASH_CircuitCode, _PREHASH_Code, code);
- if (!code)
- {
- LL_ERRS("Messaging") << "Assigning circuit code of zero!" << llendl;
- }
-
- msg->mOurCircuitCode = code;
- LL_INFOS("Messaging") << "Circuit code " << code << " assigned." << llendl;
- }
- */
- // 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" << llendl;
- return false;
- }
- code_session_map_t::iterator it = mCircuitCodes.find(code);
- if(it == mCircuitCodes.end())
- {
- LL_INFOS("Messaging") << "New circuit code " << code << " added" << llendl;
- //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" << llendl;
- }
- return true;
- }
- //void ack_add_circuit_code(LLMessageSystem *msgsystem, void** /*user_data*…
Large files files are truncated, but you can click here to view the full file