diff options
Diffstat (limited to 'indra/llmessage/llcircuit.h')
-rw-r--r-- | indra/llmessage/llcircuit.h | 315 |
1 files changed, 315 insertions, 0 deletions
diff --git a/indra/llmessage/llcircuit.h b/indra/llmessage/llcircuit.h new file mode 100644 index 0000000000..003734df29 --- /dev/null +++ b/indra/llmessage/llcircuit.h @@ -0,0 +1,315 @@ +/** + * @file llcircuit.h + * @brief Provides a method for tracking network circuit information + * for the UDP message system + * + * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#ifndef LL_LLCIRCUIT_H +#define LL_LLCIRCUIT_H + +#include <map> +#include <vector> + +#include "llerror.h" +#include "linked_lists.h" + +#include "lltimer.h" +#include "timing.h" +#include "net.h" +#include "llhost.h" +#include "llpacketack.h" +#include "lluuid.h" +#include "llthrottle.h" + +// +// Constants +// +const F32 PING_INTERVAL_MAX = 100.f; +const F32 PING_INTERVAL_ALARM = 50.f; + + +const F32 LL_AVERAGED_PING_ALPHA = 0.2f; // relaxation constant on ping running average +const F32 LL_AVERAGED_PING_MAX = 2000; // msec +const F32 LL_AVERAGED_PING_MIN = 100; // msec // IW: increased to avoid retransmits when a process is slow + +const U32 INITIAL_PING_VALUE_MSEC = 1000; // initial value for the ping delay, or for ping delay for an unknown circuit + +const TPACKETID LL_MAX_OUT_PACKET_ID = 0x01000000; +const U8 LL_PACKET_ID_SIZE = 4; + +const S32 LL_MAX_RESENT_PACKETS_PER_FRAME = 100; +const S32 LL_MAX_ACKED_PACKETS_PER_FRAME = 200; + +// +// Prototypes and Predefines +// +class LLMessageSystem; +class LLEncodedDatagramService; + +// +// Classes +// + + +class LLCircuitData +{ +public: + LLCircuitData(const LLHost &host, TPACKETID in_id); + ~LLCircuitData(); + + S32 resendUnackedPackets(const F64 now); + void clearDuplicateList(TPACKETID oldest_id); + + + void dumpResendCountAndReset(); // Used for tracking how many resends are being done on a circuit. + + + + // Public because stupid message system callbacks uses it. + void pingTimerStart(); + void pingTimerStop(const U8 ping_id); + void ackReliablePacket(TPACKETID packet_num); + + // remote computer information + const LLUUID& getRemoteID() const { return mRemoteID; } + const LLUUID& getRemoteSessionID() const { return mRemoteSessionID; } + void setRemoteID(const LLUUID& id) { mRemoteID = id; } + void setRemoteSessionID(const LLUUID& id) { mRemoteSessionID = id; } + + void setTrusted(BOOL t); + + // The local end point ID is used when establishing a trusted circuit. + // no matching set function for getLocalEndPointID() + // mLocalEndPointID should only ever be setup in the LLCircuitData constructor + const LLUUID& getLocalEndPointID() const { return mLocalEndPointID; } + + U32 getPingDelay() const; + S32 getPingsInTransit() const { return mPingsInTransit; } + + // ACCESSORS + BOOL isAlive() const; + BOOL isBlocked() const; + BOOL getAllowTimeout() const; + F32 getPingDelayAveraged(); + F32 getPingInTransitTime(); + U32 getPacketsIn() const; + S32 getBytesIn() const; + S32 getBytesOut() const; + U32 getPacketsOut() const; + U32 getPacketsLost() const; + TPACKETID getPacketOutID() const; + BOOL getTrusted() const; + F32 getAgeInSeconds() const; + S32 getUnackedPacketCount() const { return mUnackedPacketCount; } + S32 getUnackedPacketBytes() const { return mUnackedPacketBytes; } + F64 getNextPingSendTime() const { return mNextPingSendTime; } + + LLThrottleGroup &getThrottleGroup() { return mThrottles; } + + class less + { + public: + bool operator()(const LLCircuitData* lhs, const LLCircuitData* rhs) const + { + if (lhs->getNextPingSendTime() < rhs->getNextPingSendTime()) + { + return true; + } + else if (lhs->getNextPingSendTime() > rhs->getNextPingSendTime()) + { + return false; + } + else return lhs > rhs; + } + }; + + // + // Debugging stuff (not necessary for operation) + // + void checkPeriodTime(); // Reset per-period counters if necessary. + friend std::ostream& operator<<(std::ostream& s, LLCircuitData &circuit); + const char* getInfoString() const; + + friend class LLCircuit; + friend class LLMessageSystem; + friend class LLEncodedDatagramService; + friend void crash_on_spaceserver_timeout (const LLHost &host, void *); // HACK, so it has access to setAlive() so it can send a final shutdown message. +protected: + TPACKETID nextPacketOutID(); + void setPacketInID(TPACKETID id); + void checkPacketInID(TPACKETID id, BOOL receive_resent); + void setPingDelay(U32 ping); + BOOL checkCircuitTimeout(); // Return FALSE if the circuit is dead and should be cleaned up + + void addBytesIn(S32 bytes); + void addBytesOut(S32 bytes); + + U8 nextPingID() { mLastPingID++; return mLastPingID; } + + BOOL updateWatchDogTimers(LLMessageSystem *msgsys); // Return FALSE if the circuit is dead and should be cleaned up + + void addReliablePacket(S32 mSocket, U8 *buf_ptr, S32 buf_len, LLReliablePacketParams *params); + BOOL isDuplicateResend(TPACKETID packetnum); + // Call this method when a reliable message comes in - this will + // correctly place the packet in the correct list to be acked + // later. RAack = requested ack + BOOL collectRAck(TPACKETID packet_num); + + + void setTimeoutCallback(void (*callback_func)(const LLHost &host, void *user_data), void *user_data); + + + + void setAlive(BOOL b_alive); + void setAllowTimeout(BOOL allow); + +protected: + // Identification for this circuit. + LLHost mHost; + LLUUID mRemoteID; + LLUUID mRemoteSessionID; + + LLThrottleGroup mThrottles; + + TPACKETID mWrapID; + + // Current packet IDs of incoming/outgoing packets + // Used for packet sequencing/packet loss detection. + TPACKETID mPacketsOutID; + TPACKETID mPacketsInID; + TPACKETID mHighestPacketID; + + + // Callback and data to run in the case of a circuit timeout. + // Used primarily to try and reconnect to servers if they crash/die. + void (*mTimeoutCallback)(const LLHost &host, void *user_data); + void *mTimeoutUserData; + + BOOL mTrusted; // Is this circuit trusted? + BOOL mbAllowTimeout; // Machines can "pause" circuits, forcing them not to be dropped + + BOOL mbAlive; // Indicates whether a circuit is "alive", i.e. responded to pings + + BOOL mBlocked; // Blocked is true if the circuit is hosed, i.e. far behind on pings + + // Not sure what the difference between this and mLastPingSendTime is + F64 mPingTime; // Time at which a ping was sent. + + F64 mLastPingSendTime; // Time we last sent a ping + F64 mLastPingReceivedTime; // Time we last received a ping + F64 mNextPingSendTime; // Time to try and send the next ping + S32 mPingsInTransit; // Number of pings in transit + U8 mLastPingID; // ID of the last ping that we sent out + + + // Used for determining the resend time for reliable resends. + U32 mPingDelay; // raw ping delay + F32 mPingDelayAveraged; // averaged ping delay (fast attack/slow decay) + + typedef std::map<TPACKETID, U64> packet_time_map; + + packet_time_map mPotentialLostPackets; + packet_time_map mRecentlyReceivedReliablePackets; + std::vector<TPACKETID> mAcks; + + typedef std::map<TPACKETID, LLReliablePacket *> reliable_map; + typedef reliable_map::iterator reliable_iter; + + reliable_map mUnackedPackets; + reliable_map mFinalRetryPackets; + + S32 mUnackedPacketCount; + S32 mUnackedPacketBytes; + + + LLUUID mLocalEndPointID; + + // + // These variables are being used for statistical and debugging purpose ONLY, + // as far as I can tell. + // + + U32 mPacketsOut; + U32 mPacketsIn; + S32 mPacketsLost; + S32 mBytesIn; + S32 mBytesOut; + + F32 mLastPeriodLength; // seconds + S32 mBytesInLastPeriod; + S32 mBytesOutLastPeriod; + S32 mBytesInThisPeriod; + S32 mBytesOutThisPeriod; + F32 mPeakBPSIn; // bits per second, max of all period bps + F32 mPeakBPSOut; // bits per second, max of all period bps + F64 mPeriodTime; + LLTimer mExistenceTimer; // initialized when circuit created, used to track bandwidth numbers + + S32 mCurrentResendCount; // Number of resent packets since last spam +}; + + +// Actually a singleton class -- the global messagesystem +// has a single LLCircuit member. +class LLCircuit +{ +public: + // CREATORS + LLCircuit(); + ~LLCircuit(); + + // ACCESSORS + LLCircuitData* findCircuit(const LLHost& host) const; + BOOL isCircuitAlive(const LLHost& host) const; + + // MANIPULATORS + LLCircuitData *addCircuitData(const LLHost &host, TPACKETID in_id); + void removeCircuitData(const LLHost &host); + + void updateWatchDogTimers(LLMessageSystem *msgsys); + void resendUnackedPackets(S32& unacked_list_length, S32& unacked_list_size); + + // this method is called during the message system processAcks() + // to send out any acks that did not get sent already. + void sendAcks(); + + friend std::ostream& operator<<(std::ostream& s, LLCircuit &circuit); + const char* getInfoString() const; + + void dumpResends(); + + typedef std::map<LLHost, LLCircuitData*> circuit_data_map; + + /** + * @brief This method gets an iterator range starting after key in + * the circuit data map. + * + * @param key The the host before first. + * @param first[out] The first matching value after key. This + * value will equal end if there are no entries. + * @param end[out] The end of the iteration sequence. + */ + void getCircuitRange( + const LLHost& key, + circuit_data_map::iterator& first, + circuit_data_map::iterator& end); + + // Lists that optimize how many circuits we need to traverse a frame + // HACK - this should become protected eventually, but stupid !@$@# message system/circuit classes are jumbling things up. + circuit_data_map mUnackedCircuitMap; // Map of circuits with unacked data + circuit_data_map mSendAckMap; // Map of circuits which need to send acks +protected: + circuit_data_map mCircuitData; + + typedef std::set<LLCircuitData *, LLCircuitData::less> ping_set_t; // Circuits sorted by next ping time + ping_set_t mPingSet; + + // This variable points to the last circuit data we found to + // optimize the many, many times we call findCircuit. This may be + // set in otherwise const methods, so it is declared mutable. + mutable LLCircuitData* mLastCircuit; +}; +#endif |