PageRenderTime 56ms CodeModel.GetById 10ms app.highlight 39ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llmessage/llcircuit.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 350 lines | 192 code | 76 blank | 82 comment | 4 complexity | 6f121f39bc1ff5102b7d9c012ba03f1d MD5 | raw file
  1/** 
  2 * @file llcircuit.h
  3 * @brief Provides a method for tracking network circuit information
  4 * for the UDP message system
  5 *
  6 * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  7 * Second Life Viewer Source Code
  8 * Copyright (C) 2010, Linden Research, Inc.
  9 * 
 10 * This library is free software; you can redistribute it and/or
 11 * modify it under the terms of the GNU Lesser General Public
 12 * License as published by the Free Software Foundation;
 13 * version 2.1 of the License only.
 14 * 
 15 * This library is distributed in the hope that it will be useful,
 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 18 * Lesser General Public License for more details.
 19 * 
 20 * You should have received a copy of the GNU Lesser General Public
 21 * License along with this library; if not, write to the Free Software
 22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 23 * 
 24 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 25 * $/LicenseInfo$
 26 */
 27
 28#ifndef LL_LLCIRCUIT_H
 29#define LL_LLCIRCUIT_H
 30
 31#include <map>
 32#include <vector>
 33
 34#include "llerror.h"
 35
 36#include "lltimer.h"
 37#include "timing.h"
 38#include "net.h"
 39#include "llhost.h"
 40#include "llpacketack.h"
 41#include "lluuid.h"
 42#include "llthrottle.h"
 43#include "llstat.h"
 44
 45//
 46// Constants
 47//
 48const F32 LL_AVERAGED_PING_ALPHA = 0.2f;  // relaxation constant on ping running average
 49const F32 LL_AVERAGED_PING_MAX = 2000;    // msec
 50const F32 LL_AVERAGED_PING_MIN =  100;    // msec  // IW: increased to avoid retransmits when a process is slow
 51
 52const U32 INITIAL_PING_VALUE_MSEC = 1000; // initial value for the ping delay, or for ping delay for an unknown circuit
 53
 54const TPACKETID LL_MAX_OUT_PACKET_ID = 0x01000000;
 55
 56// 0 - flags
 57// [1,4] - packetid
 58// 5 - data offset (after message name)
 59const U8 LL_PACKET_ID_SIZE = 6;
 60
 61const S32 LL_MAX_RESENT_PACKETS_PER_FRAME = 100;
 62const S32 LL_MAX_ACKED_PACKETS_PER_FRAME = 200;
 63
 64//
 65// Prototypes and Predefines
 66//
 67class LLMessageSystem;
 68class LLEncodedDatagramService;
 69class LLSD;
 70
 71//
 72// Classes
 73//
 74
 75
 76class LLCircuitData
 77{
 78public:
 79	LLCircuitData(const LLHost &host, TPACKETID in_id, 
 80				  const F32 circuit_heartbeat_interval, const F32 circuit_timeout);
 81	~LLCircuitData();
 82
 83	S32		resendUnackedPackets(const F64 now);
 84	void	clearDuplicateList(TPACKETID oldest_id);
 85
 86
 87	void	dumpResendCountAndReset(); // Used for tracking how many resends are being done on a circuit.
 88
 89
 90
 91	// Public because stupid message system callbacks uses it.
 92	void		pingTimerStart();
 93	void		pingTimerStop(const U8 ping_id);
 94	void			ackReliablePacket(TPACKETID packet_num);
 95
 96	// remote computer information
 97	const LLUUID& getRemoteID() const { return mRemoteID; }
 98	const LLUUID& getRemoteSessionID() const { return mRemoteSessionID; }
 99	void setRemoteID(const LLUUID& id) { mRemoteID = id; }
100	void setRemoteSessionID(const LLUUID& id) { mRemoteSessionID = id; }
101
102	void		setTrusted(BOOL t);
103
104	// The local end point ID is used when establishing a trusted circuit.
105	// no matching set function for getLocalEndPointID()
106	// mLocalEndPointID should only ever be setup in the LLCircuitData constructor
107	const		LLUUID& getLocalEndPointID() const { return mLocalEndPointID; }
108
109	U32		getPingDelay() const;
110	S32				getPingsInTransit() const			{ return mPingsInTransit; }
111
112	// ACCESSORS
113	BOOL		isAlive() const;
114	BOOL		isBlocked() const;
115	BOOL		getAllowTimeout() const;
116	F32			getPingDelayAveraged();
117	F32			getPingInTransitTime();
118	U32			getPacketsIn() const;
119	S32			getBytesIn() const;
120	S32			getBytesOut() const;
121	U32			getPacketsOut() const;
122	U32			getPacketsLost() const;
123	TPACKETID	getPacketOutID() const;
124	BOOL		getTrusted() const;
125	F32			getAgeInSeconds() const;
126	S32			getUnackedPacketCount() const	{ return mUnackedPacketCount; }
127	S32			getUnackedPacketBytes() const	{ return mUnackedPacketBytes; }
128	F64         getNextPingSendTime() const { return mNextPingSendTime; }
129    F32         getOutOfOrderRate(LLStatAccum::TimeScale scale = LLStatAccum::SCALE_MINUTE) 
130                    { return mOutOfOrderRate.meanValue(scale); }
131    U32         getLastPacketGap() const { return mLastPacketGap; }
132    LLHost      getHost() const { return mHost; }
133	F64			getLastPacketInTime() const		{ return mLastPacketInTime;	}
134
135	LLThrottleGroup &getThrottleGroup()		{	return mThrottles; }
136
137	class less
138	{
139	public:
140		bool operator()(const LLCircuitData* lhs, const LLCircuitData* rhs) const
141		{
142			if (lhs->getNextPingSendTime() < rhs->getNextPingSendTime())
143			{
144				return true;
145			}
146			else if (lhs->getNextPingSendTime() > rhs->getNextPingSendTime())
147			{
148				return false;
149			}
150			else return lhs > rhs;
151		}
152	};
153
154	//
155	// Debugging stuff (not necessary for operation)
156	//
157	void					checkPeriodTime();		// Reset per-period counters if necessary.
158	friend std::ostream&	operator<<(std::ostream& s, LLCircuitData &circuit);
159	void getInfo(LLSD& info) const;
160
161	friend class LLCircuit;
162	friend class LLMessageSystem;
163	friend class LLEncodedDatagramService;
164	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.
165protected:
166	TPACKETID		nextPacketOutID();
167	void				setPacketInID(TPACKETID id);
168	void					checkPacketInID(TPACKETID id, BOOL receive_resent);
169	void			setPingDelay(U32 ping);
170	BOOL			checkCircuitTimeout();	// Return FALSE if the circuit is dead and should be cleaned up
171
172	void			addBytesIn(S32 bytes);
173	void			addBytesOut(S32 bytes);
174
175	U8				nextPingID()			{ mLastPingID++; return mLastPingID; }
176
177	BOOL			updateWatchDogTimers(LLMessageSystem *msgsys);	// Return FALSE if the circuit is dead and should be cleaned up
178
179	void			addReliablePacket(S32 mSocket, U8 *buf_ptr, S32 buf_len, LLReliablePacketParams *params);
180	BOOL			isDuplicateResend(TPACKETID packetnum);
181	// Call this method when a reliable message comes in - this will
182	// correctly place the packet in the correct list to be acked
183	// later. RAack = requested ack
184	BOOL collectRAck(TPACKETID packet_num);
185
186
187	void			setTimeoutCallback(void (*callback_func)(const LLHost &host, void *user_data), void *user_data);
188
189
190
191	void			setAlive(BOOL b_alive);
192	void			setAllowTimeout(BOOL allow);
193
194protected:
195	// Identification for this circuit.
196	LLHost mHost;
197	LLUUID mRemoteID;
198	LLUUID mRemoteSessionID;
199
200	LLThrottleGroup	mThrottles;
201
202	TPACKETID		mWrapID;
203
204	// Current packet IDs of incoming/outgoing packets
205	// Used for packet sequencing/packet loss detection.
206	TPACKETID		mPacketsOutID;
207	TPACKETID		mPacketsInID;
208	TPACKETID		mHighestPacketID;
209
210
211	// Callback and data to run in the case of a circuit timeout.
212	// Used primarily to try and reconnect to servers if they crash/die.
213	void	(*mTimeoutCallback)(const LLHost &host, void *user_data);
214	void	*mTimeoutUserData;
215
216	BOOL	mTrusted;					// Is this circuit trusted?
217	BOOL	mbAllowTimeout;				// Machines can "pause" circuits, forcing them not to be dropped
218
219	BOOL	mbAlive;					// Indicates whether a circuit is "alive", i.e. responded to pings
220
221	BOOL	mBlocked;					// Blocked is true if the circuit is hosed, i.e. far behind on pings
222
223	// Not sure what the difference between this and mLastPingSendTime is
224	F64		mPingTime;					// Time at which a ping was sent.
225
226	F64		mLastPingSendTime;			// Time we last sent a ping
227	F64		mLastPingReceivedTime;		// Time we last received a ping
228	F64     mNextPingSendTime;          // Time to try and send the next ping
229	S32		mPingsInTransit;			// Number of pings in transit
230	U8		mLastPingID;				// ID of the last ping that we sent out
231
232
233	// Used for determining the resend time for reliable resends.
234	U32		mPingDelay;             // raw ping delay
235	F32		mPingDelayAveraged;     // averaged ping delay (fast attack/slow decay)
236
237	typedef std::map<TPACKETID, U64> packet_time_map;
238
239	packet_time_map							mPotentialLostPackets;
240	packet_time_map							mRecentlyReceivedReliablePackets;
241	std::vector<TPACKETID> mAcks;
242
243	typedef std::map<TPACKETID, LLReliablePacket *> reliable_map;
244	typedef reliable_map::iterator					reliable_iter;
245
246	reliable_map							mUnackedPackets;
247	reliable_map							mFinalRetryPackets;
248
249	S32										mUnackedPacketCount;
250	S32										mUnackedPacketBytes;
251
252	F64										mLastPacketInTime;		// Time of last packet arrival
253
254	LLUUID									mLocalEndPointID;
255
256	//
257	// These variables are being used for statistical and debugging purpose ONLY,
258	// as far as I can tell.
259	//
260
261	U32		mPacketsOut;
262	U32		mPacketsIn;
263	S32		mPacketsLost;
264	S32		mBytesIn;
265	S32		mBytesOut;
266
267	F32		mLastPeriodLength;		// seconds
268	S32		mBytesInLastPeriod;
269	S32		mBytesOutLastPeriod;
270	S32		mBytesInThisPeriod;
271	S32		mBytesOutThisPeriod;
272	F32		mPeakBPSIn;				// bits per second, max of all period bps
273	F32		mPeakBPSOut;			// bits per second, max of all period bps
274	F64		mPeriodTime;
275	LLTimer	mExistenceTimer;	    // initialized when circuit created, used to track bandwidth numbers
276
277	S32		mCurrentResendCount;	// Number of resent packets since last spam
278    LLStatRate  mOutOfOrderRate;    // Rate of out of order packets coming in.
279    U32     mLastPacketGap;         // Gap in sequence number of last packet.
280
281	const F32 mHeartbeatInterval;
282	const F32 mHeartbeatTimeout;
283};
284
285
286// Actually a singleton class -- the global messagesystem
287// has a single LLCircuit member.
288class LLCircuit
289{
290public:
291	// CREATORS
292	LLCircuit(const F32 circuit_heartbeat_interval, const F32 circuit_timeout);
293	~LLCircuit();
294
295	// ACCESSORS
296	LLCircuitData* findCircuit(const LLHost& host) const;
297	BOOL isCircuitAlive(const LLHost& host) const;
298	
299	// MANIPULATORS
300	LLCircuitData	*addCircuitData(const LLHost &host, TPACKETID in_id);
301	void			removeCircuitData(const LLHost &host);
302
303	void		    updateWatchDogTimers(LLMessageSystem *msgsys);
304	void			resendUnackedPackets(S32& unacked_list_length, S32& unacked_list_size);
305
306	// this method is called during the message system processAcks()
307	// to send out any acks that did not get sent already. 
308	void sendAcks();
309
310	friend std::ostream& operator<<(std::ostream& s, LLCircuit &circuit);
311	void getInfo(LLSD& info) const;
312
313	void			dumpResends();
314
315	typedef std::map<LLHost, LLCircuitData*> circuit_data_map;
316
317	/**
318	 * @brief This method gets an iterator range starting after key in
319	 * the circuit data map.
320	 *
321	 * @param key The the host before first.
322	 * @param first[out] The first matching value after key. This
323	 * value will equal end if there are no entries.
324	 * @param end[out] The end of the iteration sequence.
325	 */
326	void getCircuitRange(
327		const LLHost& key,
328		circuit_data_map::iterator& first,
329		circuit_data_map::iterator& end);
330
331	// Lists that optimize how many circuits we need to traverse a frame
332	// HACK - this should become protected eventually, but stupid !@$@# message system/circuit classes are jumbling things up.
333	circuit_data_map mUnackedCircuitMap; // Map of circuits with unacked data
334	circuit_data_map mSendAckMap; // Map of circuits which need to send acks
335protected:
336	circuit_data_map mCircuitData;
337
338	typedef std::set<LLCircuitData *, LLCircuitData::less> ping_set_t; // Circuits sorted by next ping time
339	ping_set_t mPingSet;
340
341	// This variable points to the last circuit data we found to
342	// optimize the many, many times we call findCircuit. This may be
343	// set in otherwise const methods, so it is declared mutable.
344	mutable LLCircuitData* mLastCircuit;
345
346private:
347	const F32 mHeartbeatInterval;
348	const F32 mHeartbeatTimeout;
349};
350#endif