llcircuit.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  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=viewergpl$
  7. *
  8. * Copyright (c) 2001-2009, Linden Research, Inc.
  9. *
  10. * Second Life Viewer Source Code
  11. * The source code in this file ("Source Code") is provided by Linden Lab
  12. * to you under the terms of the GNU General Public License, version 2.0
  13. * ("GPL"), unless you have obtained a separate licensing agreement
  14. * ("Other License"), formally executed by you and Linden Lab. Terms of
  15. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  16. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  17. *
  18. * There are special exceptions to the terms and conditions of the GPL as
  19. * it is applied to this Source Code. View the full text of the exception
  20. * in the file doc/FLOSS-exception.txt in this software distribution, or
  21. * online at
  22. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  23. *
  24. * By copying, modifying or distributing this software, you acknowledge
  25. * that you have read and understood your obligations described above,
  26. * and agree to abide by those obligations.
  27. *
  28. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  29. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  30. * COMPLETENESS OR PERFORMANCE.
  31. * $/LicenseInfo$
  32. */
  33. #ifndef LL_LLCIRCUIT_H
  34. #define LL_LLCIRCUIT_H
  35. #include <map>
  36. #include <vector>
  37. #include "llerror.h"
  38. #include "llhost.h"
  39. #include "llpacketack.h"
  40. #include "llpreprocessor.h"
  41. #include "llthrottle.h"
  42. #include "lltimer.h"
  43. #include "lluuid.h"
  44. class LLMessageSystem;
  45. class LLEncodedDatagramService;
  46. class LLSD;
  47. // Relaxation constant on ping running average
  48. constexpr F32 LL_AVERAGED_PING_ALPHA = 0.2f;
  49. constexpr F32 LL_AVERAGED_PING_MAX = 2000; // msec
  50. // IW: increased to avoid retransmits when a process is slow
  51. constexpr F32 LL_AVERAGED_PING_MIN = 100; // msec
  52. // Initial value for the ping delay, or for ping delay for an unknown circuit
  53. constexpr U32 INITIAL_PING_VALUE_MSEC = 1000;
  54. constexpr TPACKETID LL_MAX_OUT_PACKET_ID = 0x01000000;
  55. constexpr int LL_ERR_CIRCUIT_GONE = -23017;
  56. constexpr int LL_ERR_TCP_TIMEOUT = -23016;
  57. // 0 - flags
  58. // [1,4] - packetid
  59. // 5 - data offset (after message name)
  60. constexpr U8 LL_PACKET_ID_SIZE = 6;
  61. constexpr S32 LL_MAX_RESENT_PACKETS_PER_FRAME = 100;
  62. constexpr S32 LL_MAX_ACKED_PACKETS_PER_FRAME = 200;
  63. constexpr F32 LL_COLLECT_ACK_TIME_MAX = 2.f;
  64. class LLCircuitData
  65. {
  66. friend class LLCircuit;
  67. friend class LLMessageSystem;
  68. friend class LLEncodedDatagramService;
  69. // *HACK: so it has access to setAlive() so it can send a final shutdown
  70. // message:
  71. friend void crash_on_spaceserver_timeout(const LLHost& host, void*);
  72. protected:
  73. LOG_CLASS(LLCircuitData);
  74. public:
  75. LLCircuitData(const LLHost& host, TPACKETID in_id, F32 heartbeat_interval,
  76. F32 circuit_timeout);
  77. ~LLCircuitData();
  78. S32 resendUnackedPackets(F64 now);
  79. void clearDuplicateList(TPACKETID oldest_id);
  80. // Used for tracking how many resends are being done on a circuit.
  81. void dumpResendCountAndReset();
  82. // Public because stupid message system callbacks uses it.
  83. void pingTimerStart();
  84. void pingTimerStop(U8 ping_id);
  85. void ackReliablePacket(TPACKETID packet_num);
  86. // remote computer information
  87. LL_INLINE const LLUUID& getRemoteID() const { return mRemoteID; }
  88. LL_INLINE const LLUUID& getRemoteSessionID() const
  89. {
  90. return mRemoteSessionID;
  91. }
  92. LL_INLINE void setRemoteID(const LLUUID& id) { mRemoteID = id; }
  93. LL_INLINE void setRemoteSessionID(const LLUUID& id)
  94. {
  95. mRemoteSessionID = id;
  96. }
  97. LL_INLINE void setTrusted(bool b) { mTrusted = b; }
  98. // The local end point ID is used when establishing a trusted circuit.
  99. // no matching set function for getLocalEndPointID()
  100. // mLocalEndPointID should only ever be setup in the LLCircuitData constructor
  101. const LLUUID& getLocalEndPointID() const { return mLocalEndPointID; }
  102. LL_INLINE U32 getPingDelay() const { return mPingDelay; }
  103. LL_INLINE S32 getPingsInTransit() const { return mPingsInTransit; }
  104. // ACCESSORS
  105. LL_INLINE bool isAlive() const { return mAlive; }
  106. LL_INLINE bool isBlocked() const { return mBlocked; }
  107. LL_INLINE bool getAllowTimeout() const { return mAllowTimeout; }
  108. F32 getPingDelayAveraged();
  109. F32 getPingInTransitTime();
  110. LL_INLINE U32 getPacketsIn() const { return mPacketsIn; }
  111. LL_INLINE S32 getBytesIn() const { return mBytesIn; }
  112. LL_INLINE S32 getBytesOut() const { return mBytesOut; }
  113. LL_INLINE U32 getPacketsOut() const { return mPacketsOut; }
  114. LL_INLINE U32 getPacketsLost() const { return mPacketsLost; }
  115. LL_INLINE TPACKETID getPacketOutID() const { return mPacketsOutID; }
  116. LL_INLINE bool getTrusted() const { return mTrusted; }
  117. F32 getAgeInSeconds() const;
  118. LL_INLINE S32 getUnackedPacketCount() const { return mUnackedPacketCount; }
  119. LL_INLINE S32 getUnackedPacketBytes() const { return mUnackedPacketBytes; }
  120. LL_INLINE F64 getNextPingSendTime() const { return mNextPingSendTime; }
  121. LL_INLINE U32 getLastPacketGap() const { return mLastPacketGap; }
  122. LL_INLINE LLHost getHost() const { return mHost; }
  123. LL_INLINE F64 getLastPacketInTime() const { return mLastPacketInTime; }
  124. LL_INLINE LLThrottleGroup& getThrottleGroup() { return mThrottles; }
  125. class less
  126. {
  127. public:
  128. bool operator()(const LLCircuitData* lhs, const LLCircuitData* rhs) const
  129. {
  130. if (lhs->getNextPingSendTime() < rhs->getNextPingSendTime())
  131. {
  132. return true;
  133. }
  134. else if (lhs->getNextPingSendTime() > rhs->getNextPingSendTime())
  135. {
  136. return false;
  137. }
  138. else return lhs > rhs;
  139. }
  140. };
  141. // Debugging stuff (not necessary for operation)
  142. // Resets per-period counters if necessary.
  143. void checkPeriodTime();
  144. friend std::ostream& operator<<(std::ostream& s, LLCircuitData &circuit);
  145. void getInfo(LLSD& info) const;
  146. protected:
  147. TPACKETID nextPacketOutID();
  148. void setPacketInID(TPACKETID id);
  149. void checkPacketInID(TPACKETID id, bool receive_resent);
  150. void setPingDelay(U32 ping);
  151. // Returns false if the circuit is dead and should be cleaned up
  152. bool checkCircuitTimeout();
  153. void addBytesIn(S32 bytes);
  154. void addBytesOut(S32 bytes);
  155. LL_INLINE U8 nextPingID() { return ++mLastPingID; }
  156. // Returns false if the circuit is dead and should be cleaned up
  157. bool updateWatchDogTimers(LLMessageSystem* msgsys);
  158. void addReliablePacket(S32 mSocket, U8* buf_ptr, S32 buf_len,
  159. LLReliablePacketParams* params);
  160. bool isDuplicateResend(TPACKETID packetnum);
  161. // Call this method when a reliable message comes in - this will correctly
  162. // place the packet in the correct list to be acked later.
  163. // RAack = requested ack
  164. void collectRAck(TPACKETID packet_num);
  165. void setTimeoutCallback(void (*callback_func)(const LLHost&, void*),
  166. void* user_data);
  167. void setAlive(bool b_alive);
  168. void setAllowTimeout(bool allow);
  169. protected:
  170. // Identification for this circuit.
  171. LLHost mHost;
  172. LLUUID mRemoteID;
  173. LLUUID mRemoteSessionID;
  174. LLThrottleGroup mThrottles;
  175. TPACKETID mWrapID;
  176. // Current packet IDs of incoming/outgoing packets
  177. // Used for packet sequencing/packet loss detection.
  178. TPACKETID mPacketsOutID;
  179. TPACKETID mPacketsInID;
  180. TPACKETID mHighestPacketID;
  181. // Callback and data to run in the case of a circuit timeout.
  182. // Used primarily to try and reconnect to servers if they crash/die.
  183. void (*mTimeoutCallback)(const LLHost&, void*);
  184. void* mTimeoutUserData;
  185. // Is this circuit trusted ?
  186. bool mTrusted;
  187. // Machines can "pause" circuits, forcing them not to be dropped
  188. bool mAllowTimeout;
  189. // Indicates whether a circuit is "alive", i.e. responded to pings
  190. bool mAlive;
  191. // Blocked is true if the circuit is hosed, i.e. far behind on pings
  192. bool mBlocked;
  193. // Not sure what the difference between this and mLastPingSendTime is
  194. F64 mPingTime; // Time at which a ping was sent.
  195. F64 mLastPingSendTime; // Time we last sent a ping
  196. F64 mLastPingReceivedTime; // Time we last received a ping
  197. F64 mNextPingSendTime; // Time to try & send the next ping
  198. S32 mPingsInTransit; // Number of pings in transit
  199. U8 mLastPingID; // ID of the last ping we sent out
  200. // Used for determining the resend time for reliable resends.
  201. // Raw ping delay
  202. U32 mPingDelay;
  203. // Averaged ping delay (fast attack/slow decay)
  204. F32 mPingDelayAveraged;
  205. typedef std::map<TPACKETID, U64> packet_time_map;
  206. packet_time_map mPotentialLostPackets;
  207. packet_time_map mRecentlyReceivedReliablePackets;
  208. typedef std::vector<TPACKETID> acks_vec_t;
  209. acks_vec_t mAcks;
  210. // First ack creation time
  211. F32 mAckCreationTime;
  212. typedef std::map<TPACKETID, LLReliablePacket*> reliable_map;
  213. typedef reliable_map::iterator reliable_iter;
  214. reliable_map mUnackedPackets;
  215. reliable_map mFinalRetryPackets;
  216. S32 mUnackedPacketCount;
  217. S32 mUnackedPacketBytes;
  218. F64 mLastPacketInTime; // Time of last packet arrival
  219. LLUUID mLocalEndPointID;
  220. // These variables are being used for statistical and debugging purpose
  221. // ONLY, as far as I can tell.
  222. U32 mPacketsOut;
  223. U32 mPacketsIn;
  224. S32 mPacketsLost;
  225. S32 mBytesIn;
  226. S32 mBytesOut;
  227. F32 mLastPeriodLength; // seconds
  228. S32 mBytesInLastPeriod;
  229. S32 mBytesOutLastPeriod;
  230. S32 mBytesInThisPeriod;
  231. S32 mBytesOutThisPeriod;
  232. F32 mPeakBPSIn; // bits/s, max of all period bps
  233. F32 mPeakBPSOut; // bits/s, max of all period bps
  234. F64 mPeriodTime;
  235. // Initialized when circuit created, used to track bandwidth numbers
  236. LLTimer mExistenceTimer;
  237. // Number of resent packets since last spam
  238. S32 mCurrentResendCount;
  239. // Gap in sequence number of last packet.
  240. U32 mLastPacketGap;
  241. const F32 mHeartbeatInterval;
  242. const F32 mHeartbeatTimeout;
  243. };
  244. // Actually a singleton class -- the global messagesystem has a single
  245. // LLCircuit member.
  246. class LLCircuit
  247. {
  248. protected:
  249. LOG_CLASS(LLCircuit);
  250. public:
  251. LLCircuit(F32 circuit_heartbeat_interval, F32 circuit_timeout);
  252. ~LLCircuit();
  253. LLCircuitData* findCircuit(const LLHost& host) const;
  254. bool isCircuitAlive(const LLHost& host) const;
  255. LLCircuitData* addCircuitData(const LLHost& host, TPACKETID in_id);
  256. void removeCircuitData(const LLHost& host);
  257. void updateWatchDogTimers(LLMessageSystem *msgsys);
  258. void resendUnackedPackets(S32& unacked_list_len, S32& unacked_list_size);
  259. // This method is called during the message system processAcks() to send
  260. // out any acks that did not get sent already.
  261. void sendAcks(F32 collect_time);
  262. friend std::ostream& operator<<(std::ostream& s, LLCircuit &circuit);
  263. void getInfo(LLSD& info) const;
  264. void dumpResends();
  265. typedef std::map<LLHost, LLCircuitData*> circ_data_map_t;
  266. /**
  267. * @brief This method gets an iterator range starting after key in
  268. * the circuit data map.
  269. *
  270. * @param key The the host before first.
  271. * @param first[out] The first matching value after key. This
  272. * value will equal end if there are no entries.
  273. * @param end[out] The end of the iteration sequence.
  274. */
  275. void getCircuitRange(const LLHost& key, circ_data_map_t::iterator& first,
  276. circ_data_map_t::iterator& end);
  277. public:
  278. // Lists that optimize how many circuits we need to traverse a frame
  279. // *HACK: this should become protected eventually, but stupid !@$@# message
  280. // system/circuit classes are jumbling things up.
  281. circ_data_map_t mUnackedCircuitMap; // Circuits with unacked data
  282. circ_data_map_t mSendAckMap; // Circuits needing to send ack
  283. protected:
  284. circ_data_map_t mCircuitData;
  285. // Circuits sorted by next ping time
  286. typedef std::set<LLCircuitData*, LLCircuitData::less> ping_set_t;
  287. ping_set_t mPingSet;
  288. // This variable points to the last circuit data we found to optimize the
  289. // many, many times we call findCircuit. This may be set in otherwise const
  290. // methods, so it is declared mutable.
  291. mutable LLCircuitData* mLastCircuit;
  292. private:
  293. const F32 mHeartbeatInterval;
  294. const F32 mHeartbeatTimeout;
  295. };
  296. #endif