/indra/llmessage/llcircuit.cpp

https://bitbucket.org/lindenlab/viewer-beta/ · C++ · 1412 lines · 1009 code · 214 blank · 189 comment · 142 complexity · a21a61a51bb26413ae388c4bf5bad65c MD5 · raw file

  1. /**
  2. * @file llcircuit.cpp
  3. * @brief Class to track UDP endpoints for the message system.
  4. *
  5. * $LicenseInfo:firstyear=2002&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "linden_common.h"
  27. #if LL_WINDOWS
  28. #include <process.h>
  29. #else
  30. #if LL_LINUX
  31. #include <dlfcn.h> // RTLD_LAZY
  32. #endif
  33. #include <sys/types.h>
  34. #include <sys/socket.h>
  35. #include <netinet/in.h>
  36. #endif
  37. #if !defined(USE_CIRCUIT_LIST)
  38. #include <algorithm>
  39. #endif
  40. #include <sstream>
  41. #include <iterator>
  42. #include <stack>
  43. #include "llcircuit.h"
  44. #include "message.h"
  45. #include "llrand.h"
  46. #include "llstl.h"
  47. #include "lltransfermanager.h"
  48. #include "llmodularmath.h"
  49. const S32 PING_START_BLOCK = 3; // How many pings behind we have to be to consider ourself blocked.
  50. const S32 PING_RELEASE_BLOCK = 2; // How many pings behind we have to be to consider ourself unblocked.
  51. const F32 TARGET_PERIOD_LENGTH = 5.f; // seconds
  52. const F32 LL_DUPLICATE_SUPPRESSION_TIMEOUT = 60.f; //seconds - this can be long, as time-based cleanup is
  53. // only done when wrapping packetids, now...
  54. LLCircuitData::LLCircuitData(const LLHost &host, TPACKETID in_id,
  55. const F32 circuit_heartbeat_interval, const F32 circuit_timeout)
  56. : mHost (host),
  57. mWrapID(0),
  58. mPacketsOutID(0),
  59. mPacketsInID(in_id),
  60. mHighestPacketID(in_id),
  61. mTimeoutCallback(NULL),
  62. mTimeoutUserData(NULL),
  63. mTrusted(FALSE),
  64. mbAllowTimeout(TRUE),
  65. mbAlive(TRUE),
  66. mBlocked(FALSE),
  67. mPingTime(0.0),
  68. mLastPingSendTime(0.0),
  69. mLastPingReceivedTime(0.0),
  70. mNextPingSendTime(0.0),
  71. mPingsInTransit(0),
  72. mLastPingID(0),
  73. mPingDelay(INITIAL_PING_VALUE_MSEC),
  74. mPingDelayAveraged((F32)INITIAL_PING_VALUE_MSEC),
  75. mUnackedPacketCount(0),
  76. mUnackedPacketBytes(0),
  77. mLastPacketInTime(0.0),
  78. mLocalEndPointID(),
  79. mPacketsOut(0),
  80. mPacketsIn(0),
  81. mPacketsLost(0),
  82. mBytesIn(0),
  83. mBytesOut(0),
  84. mLastPeriodLength(-1.f),
  85. mBytesInLastPeriod(0),
  86. mBytesOutLastPeriod(0),
  87. mBytesInThisPeriod(0),
  88. mBytesOutThisPeriod(0),
  89. mPeakBPSIn(0.f),
  90. mPeakBPSOut(0.f),
  91. mPeriodTime(0.0),
  92. mExistenceTimer(),
  93. mCurrentResendCount(0),
  94. mLastPacketGap(0),
  95. mHeartbeatInterval(circuit_heartbeat_interval),
  96. mHeartbeatTimeout(circuit_timeout)
  97. {
  98. // Need to guarantee that this time is up to date, we may be creating a circuit even though we haven't been
  99. // running a message system loop.
  100. F64 mt_sec = LLMessageSystem::getMessageTimeSeconds(TRUE);
  101. F32 distribution_offset = ll_frand();
  102. mPingTime = mt_sec;
  103. mLastPingSendTime = mt_sec + mHeartbeatInterval * distribution_offset;
  104. mLastPingReceivedTime = mt_sec;
  105. mNextPingSendTime = mLastPingSendTime + 0.95*mHeartbeatInterval + ll_frand(0.1f*mHeartbeatInterval);
  106. mPeriodTime = mt_sec;
  107. mLocalEndPointID.generate();
  108. }
  109. LLCircuitData::~LLCircuitData()
  110. {
  111. LLReliablePacket *packetp = NULL;
  112. // Clean up all pending transfers.
  113. gTransferManager.cleanupConnection(mHost);
  114. // remove all pending reliable messages on this circuit
  115. std::vector<TPACKETID> doomed;
  116. reliable_iter iter;
  117. reliable_iter end = mUnackedPackets.end();
  118. for(iter = mUnackedPackets.begin(); iter != end; ++iter)
  119. {
  120. packetp = iter->second;
  121. gMessageSystem->mFailedResendPackets++;
  122. if(gMessageSystem->mVerboseLog)
  123. {
  124. doomed.push_back(packetp->mPacketID);
  125. }
  126. if (packetp->mCallback)
  127. {
  128. packetp->mCallback(packetp->mCallbackData,LL_ERR_CIRCUIT_GONE);
  129. }
  130. // Update stats
  131. mUnackedPacketCount--;
  132. mUnackedPacketBytes -= packetp->mBufferLength;
  133. delete packetp;
  134. }
  135. // remove all pending final retry reliable messages on this circuit
  136. end = mFinalRetryPackets.end();
  137. for(iter = mFinalRetryPackets.begin(); iter != end; ++iter)
  138. {
  139. packetp = iter->second;
  140. gMessageSystem->mFailedResendPackets++;
  141. if(gMessageSystem->mVerboseLog)
  142. {
  143. doomed.push_back(packetp->mPacketID);
  144. }
  145. if (packetp->mCallback)
  146. {
  147. packetp->mCallback(packetp->mCallbackData,LL_ERR_CIRCUIT_GONE);
  148. }
  149. // Update stats
  150. mUnackedPacketCount--;
  151. mUnackedPacketBytes -= packetp->mBufferLength;
  152. delete packetp;
  153. }
  154. // log aborted reliable packets for this circuit.
  155. if(gMessageSystem->mVerboseLog && !doomed.empty())
  156. {
  157. std::ostringstream str;
  158. std::ostream_iterator<TPACKETID> append(str, " ");
  159. str << "MSG: -> " << mHost << "\tABORTING RELIABLE:\t";
  160. std::copy(doomed.begin(), doomed.end(), append);
  161. llinfos << str.str() << llendl;
  162. }
  163. }
  164. void LLCircuitData::ackReliablePacket(TPACKETID packet_num)
  165. {
  166. reliable_iter iter;
  167. LLReliablePacket *packetp;
  168. iter = mUnackedPackets.find(packet_num);
  169. if (iter != mUnackedPackets.end())
  170. {
  171. packetp = iter->second;
  172. if(gMessageSystem->mVerboseLog)
  173. {
  174. std::ostringstream str;
  175. str << "MSG: <- " << packetp->mHost << "\tRELIABLE ACKED:\t"
  176. << packetp->mPacketID;
  177. llinfos << str.str() << llendl;
  178. }
  179. if (packetp->mCallback)
  180. {
  181. if (packetp->mTimeout < 0.f) // negative timeout will always return timeout even for successful ack, for debugging
  182. {
  183. packetp->mCallback(packetp->mCallbackData,LL_ERR_TCP_TIMEOUT);
  184. }
  185. else
  186. {
  187. packetp->mCallback(packetp->mCallbackData,LL_ERR_NOERR);
  188. }
  189. }
  190. // Update stats
  191. mUnackedPacketCount--;
  192. mUnackedPacketBytes -= packetp->mBufferLength;
  193. // Cleanup
  194. delete packetp;
  195. mUnackedPackets.erase(iter);
  196. return;
  197. }
  198. iter = mFinalRetryPackets.find(packet_num);
  199. if (iter != mFinalRetryPackets.end())
  200. {
  201. packetp = iter->second;
  202. // llinfos << "Packet " << packet_num << " removed from the pending list" << llendl;
  203. if(gMessageSystem->mVerboseLog)
  204. {
  205. std::ostringstream str;
  206. str << "MSG: <- " << packetp->mHost << "\tRELIABLE ACKED:\t"
  207. << packetp->mPacketID;
  208. llinfos << str.str() << llendl;
  209. }
  210. if (packetp->mCallback)
  211. {
  212. if (packetp->mTimeout < 0.f) // negative timeout will always return timeout even for successful ack, for debugging
  213. {
  214. packetp->mCallback(packetp->mCallbackData,LL_ERR_TCP_TIMEOUT);
  215. }
  216. else
  217. {
  218. packetp->mCallback(packetp->mCallbackData,LL_ERR_NOERR);
  219. }
  220. }
  221. // Update stats
  222. mUnackedPacketCount--;
  223. mUnackedPacketBytes -= packetp->mBufferLength;
  224. // Cleanup
  225. delete packetp;
  226. mFinalRetryPackets.erase(iter);
  227. }
  228. else
  229. {
  230. // Couldn't find this packet on either of the unacked lists.
  231. // maybe it's a duplicate ack?
  232. }
  233. }
  234. S32 LLCircuitData::resendUnackedPackets(const F64 now)
  235. {
  236. S32 resent_packets = 0;
  237. LLReliablePacket *packetp;
  238. //
  239. // Theoretically we should search through the list for the packet with the oldest
  240. // packet ID, as otherwise when we WRAP we will resend reliable packets out of order.
  241. // Since resends are ALREADY out of order, and wrapping is highly rare (16+million packets),
  242. // I'm not going to worry about this for now - djs
  243. //
  244. reliable_iter iter;
  245. BOOL have_resend_overflow = FALSE;
  246. for (iter = mUnackedPackets.begin(); iter != mUnackedPackets.end();)
  247. {
  248. packetp = iter->second;
  249. // Only check overflow if we haven't had one yet.
  250. if (!have_resend_overflow)
  251. {
  252. have_resend_overflow = mThrottles.checkOverflow(TC_RESEND, 0);
  253. }
  254. if (have_resend_overflow)
  255. {
  256. // We've exceeded our bandwidth for resends.
  257. // Time to stop trying to send them.
  258. // If we have too many unacked packets, we need to start dropping expired ones.
  259. if (mUnackedPacketBytes > 512000)
  260. {
  261. if (now > packetp->mExpirationTime)
  262. {
  263. // This circuit has overflowed. Do not retry. Do not pass go.
  264. packetp->mRetries = 0;
  265. // Remove it from this list and add it to the final list.
  266. mUnackedPackets.erase(iter++);
  267. mFinalRetryPackets[packetp->mPacketID] = packetp;
  268. }
  269. else
  270. {
  271. ++iter;
  272. }
  273. // Move on to the next unacked packet.
  274. continue;
  275. }
  276. if (mUnackedPacketBytes > 256000 && !(getPacketsOut() % 1024))
  277. {
  278. // Warn if we've got a lot of resends waiting.
  279. llwarns << mHost << " has " << mUnackedPacketBytes
  280. << " bytes of reliable messages waiting" << llendl;
  281. }
  282. // Stop resending. There are less than 512000 unacked packets.
  283. break;
  284. }
  285. if (now > packetp->mExpirationTime)
  286. {
  287. packetp->mRetries--;
  288. // retry
  289. mCurrentResendCount++;
  290. gMessageSystem->mResentPackets++;
  291. if(gMessageSystem->mVerboseLog)
  292. {
  293. std::ostringstream str;
  294. str << "MSG: -> " << packetp->mHost
  295. << "\tRESENDING RELIABLE:\t" << packetp->mPacketID;
  296. llinfos << str.str() << llendl;
  297. }
  298. packetp->mBuffer[0] |= LL_RESENT_FLAG; // tag packet id as being a resend
  299. gMessageSystem->mPacketRing.sendPacket(packetp->mSocket,
  300. (char *)packetp->mBuffer, packetp->mBufferLength,
  301. packetp->mHost);
  302. mThrottles.throttleOverflow(TC_RESEND, packetp->mBufferLength * 8.f);
  303. // The new method, retry time based on ping
  304. if (packetp->mPingBasedRetry)
  305. {
  306. packetp->mExpirationTime = now + llmax(LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS, (LL_RELIABLE_TIMEOUT_FACTOR * getPingDelayAveraged()));
  307. }
  308. else
  309. {
  310. // custom, constant retry time
  311. packetp->mExpirationTime = now + packetp->mTimeout;
  312. }
  313. if (!packetp->mRetries)
  314. {
  315. // Last resend, remove it from this list and add it to the final list.
  316. mUnackedPackets.erase(iter++);
  317. mFinalRetryPackets[packetp->mPacketID] = packetp;
  318. }
  319. else
  320. {
  321. // Don't remove it yet, it still gets to try to resend at least once.
  322. ++iter;
  323. }
  324. resent_packets++;
  325. }
  326. else
  327. {
  328. // Don't need to do anything with this packet, keep iterating.
  329. ++iter;
  330. }
  331. }
  332. for (iter = mFinalRetryPackets.begin(); iter != mFinalRetryPackets.end();)
  333. {
  334. packetp = iter->second;
  335. if (now > packetp->mExpirationTime)
  336. {
  337. // fail (too many retries)
  338. //llinfos << "Packet " << packetp->mPacketID << " removed from the pending list: exceeded retry limit" << llendl;
  339. //if (packetp->mMessageName)
  340. //{
  341. // llinfos << "Packet name " << packetp->mMessageName << llendl;
  342. //}
  343. gMessageSystem->mFailedResendPackets++;
  344. if(gMessageSystem->mVerboseLog)
  345. {
  346. std::ostringstream str;
  347. str << "MSG: -> " << packetp->mHost << "\tABORTING RELIABLE:\t"
  348. << packetp->mPacketID;
  349. llinfos << str.str() << llendl;
  350. }
  351. if (packetp->mCallback)
  352. {
  353. packetp->mCallback(packetp->mCallbackData,LL_ERR_TCP_TIMEOUT);
  354. }
  355. // Update stats
  356. mUnackedPacketCount--;
  357. mUnackedPacketBytes -= packetp->mBufferLength;
  358. mFinalRetryPackets.erase(iter++);
  359. delete packetp;
  360. }
  361. else
  362. {
  363. ++iter;
  364. }
  365. }
  366. return mUnackedPacketCount;
  367. }
  368. LLCircuit::LLCircuit(const F32 circuit_heartbeat_interval, const F32 circuit_timeout) : mLastCircuit(NULL),
  369. mHeartbeatInterval(circuit_heartbeat_interval), mHeartbeatTimeout(circuit_timeout)
  370. {
  371. }
  372. LLCircuit::~LLCircuit()
  373. {
  374. // delete pointers in the map.
  375. std::for_each(mCircuitData.begin(),
  376. mCircuitData.end(),
  377. llcompose1(
  378. DeletePointerFunctor<LLCircuitData>(),
  379. llselect2nd<circuit_data_map::value_type>()));
  380. }
  381. LLCircuitData *LLCircuit::addCircuitData(const LLHost &host, TPACKETID in_id)
  382. {
  383. // This should really validate if one already exists
  384. llinfos << "LLCircuit::addCircuitData for " << host << llendl;
  385. LLCircuitData *tempp = new LLCircuitData(host, in_id, mHeartbeatInterval, mHeartbeatTimeout);
  386. mCircuitData.insert(circuit_data_map::value_type(host, tempp));
  387. mPingSet.insert(tempp);
  388. mLastCircuit = tempp;
  389. return tempp;
  390. }
  391. void LLCircuit::removeCircuitData(const LLHost &host)
  392. {
  393. llinfos << "LLCircuit::removeCircuitData for " << host << llendl;
  394. mLastCircuit = NULL;
  395. circuit_data_map::iterator it = mCircuitData.find(host);
  396. if(it != mCircuitData.end())
  397. {
  398. LLCircuitData *cdp = it->second;
  399. mCircuitData.erase(it);
  400. LLCircuit::ping_set_t::iterator psit = mPingSet.find(cdp);
  401. if (psit != mPingSet.end())
  402. {
  403. mPingSet.erase(psit);
  404. }
  405. else
  406. {
  407. llwarns << "Couldn't find entry for next ping in ping set!" << llendl;
  408. }
  409. // Clean up from optimization maps
  410. mUnackedCircuitMap.erase(host);
  411. mSendAckMap.erase(host);
  412. delete cdp;
  413. }
  414. // This also has to happen AFTER we nuke the circuit, because various
  415. // callbacks for the circuit may result in messages being sent to
  416. // this circuit, and the setting of mLastCircuit. We don't check
  417. // if the host matches, but we don't really care because mLastCircuit
  418. // is an optimization, and this happens VERY rarely.
  419. mLastCircuit = NULL;
  420. }
  421. void LLCircuitData::setAlive(BOOL b_alive)
  422. {
  423. if (mbAlive != b_alive)
  424. {
  425. mPacketsOutID = 0;
  426. mPacketsInID = 0;
  427. mbAlive = b_alive;
  428. }
  429. if (b_alive)
  430. {
  431. mLastPingReceivedTime = LLMessageSystem::getMessageTimeSeconds();
  432. mPingsInTransit = 0;
  433. mBlocked = FALSE;
  434. }
  435. }
  436. void LLCircuitData::setAllowTimeout(BOOL allow)
  437. {
  438. mbAllowTimeout = allow;
  439. if (allow)
  440. {
  441. // resuming circuit
  442. // make sure it's alive
  443. setAlive(TRUE);
  444. }
  445. }
  446. // Reset per-period counters if necessary.
  447. void LLCircuitData::checkPeriodTime()
  448. {
  449. F64 mt_sec = LLMessageSystem::getMessageTimeSeconds();
  450. F64 period_length = mt_sec - mPeriodTime;
  451. if ( period_length > TARGET_PERIOD_LENGTH)
  452. {
  453. F32 bps_in = (F32)(mBytesInThisPeriod * 8.f / period_length);
  454. if (bps_in > mPeakBPSIn)
  455. {
  456. mPeakBPSIn = bps_in;
  457. }
  458. F32 bps_out = (F32)(mBytesOutThisPeriod * 8.f / period_length);
  459. if (bps_out > mPeakBPSOut)
  460. {
  461. mPeakBPSOut = bps_out;
  462. }
  463. mBytesInLastPeriod = mBytesInThisPeriod;
  464. mBytesOutLastPeriod = mBytesOutThisPeriod;
  465. mBytesInThisPeriod = 0;
  466. mBytesOutThisPeriod = 0;
  467. mLastPeriodLength = (F32)period_length;
  468. mPeriodTime = mt_sec;
  469. }
  470. }
  471. void LLCircuitData::addBytesIn(S32 bytes)
  472. {
  473. mBytesIn += bytes;
  474. mBytesInThisPeriod += bytes;
  475. }
  476. void LLCircuitData::addBytesOut(S32 bytes)
  477. {
  478. mBytesOut += bytes;
  479. mBytesOutThisPeriod += bytes;
  480. }
  481. void LLCircuitData::addReliablePacket(S32 mSocket, U8 *buf_ptr, S32 buf_len, LLReliablePacketParams *params)
  482. {
  483. LLReliablePacket *packet_info;
  484. packet_info = new LLReliablePacket(mSocket, buf_ptr, buf_len, params);
  485. mUnackedPacketCount++;
  486. mUnackedPacketBytes += packet_info->mBufferLength;
  487. if (params && params->mRetries)
  488. {
  489. mUnackedPackets[packet_info->mPacketID] = packet_info;
  490. }
  491. else
  492. {
  493. mFinalRetryPackets[packet_info->mPacketID] = packet_info;
  494. }
  495. }
  496. void LLCircuit::resendUnackedPackets(S32& unacked_list_length, S32& unacked_list_size)
  497. {
  498. F64 now = LLMessageSystem::getMessageTimeSeconds();
  499. unacked_list_length = 0;
  500. unacked_list_size = 0;
  501. LLCircuitData* circ;
  502. circuit_data_map::iterator end = mUnackedCircuitMap.end();
  503. for(circuit_data_map::iterator it = mUnackedCircuitMap.begin(); it != end; ++it)
  504. {
  505. circ = (*it).second;
  506. unacked_list_length += circ->resendUnackedPackets(now);
  507. unacked_list_size += circ->getUnackedPacketBytes();
  508. }
  509. }
  510. BOOL LLCircuitData::isDuplicateResend(TPACKETID packetnum)
  511. {
  512. return (mRecentlyReceivedReliablePackets.find(packetnum) != mRecentlyReceivedReliablePackets.end());
  513. }
  514. void LLCircuit::dumpResends()
  515. {
  516. circuit_data_map::iterator end = mCircuitData.end();
  517. for(circuit_data_map::iterator it = mCircuitData.begin(); it != end; ++it)
  518. {
  519. (*it).second->dumpResendCountAndReset();
  520. }
  521. }
  522. LLCircuitData* LLCircuit::findCircuit(const LLHost& host) const
  523. {
  524. // An optimization on finding the previously found circuit.
  525. if (mLastCircuit && (mLastCircuit->mHost == host))
  526. {
  527. return mLastCircuit;
  528. }
  529. circuit_data_map::const_iterator it = mCircuitData.find(host);
  530. if(it == mCircuitData.end())
  531. {
  532. return NULL;
  533. }
  534. mLastCircuit = it->second;
  535. return mLastCircuit;
  536. }
  537. BOOL LLCircuit::isCircuitAlive(const LLHost& host) const
  538. {
  539. LLCircuitData *cdp = findCircuit(host);
  540. if(cdp)
  541. {
  542. return cdp->mbAlive;
  543. }
  544. return FALSE;
  545. }
  546. void LLCircuitData::setTimeoutCallback(void (*callback_func)(const LLHost &host, void *user_data), void *user_data)
  547. {
  548. mTimeoutCallback = callback_func;
  549. mTimeoutUserData = user_data;
  550. }
  551. void LLCircuitData::checkPacketInID(TPACKETID id, BOOL receive_resent)
  552. {
  553. // Done as floats so we don't have to worry about running out of room
  554. // with U32 getting poked into an S32.
  555. F32 delta = (F32)mHighestPacketID - (F32)id;
  556. if (delta > (0.5f*LL_MAX_OUT_PACKET_ID))
  557. {
  558. // We've almost definitely wrapped, reset the mLastPacketID to be low again.
  559. mHighestPacketID = id;
  560. }
  561. else if (delta < (-0.5f*LL_MAX_OUT_PACKET_ID))
  562. {
  563. // This is almost definitely an old packet coming in after a wrap, ignore it.
  564. }
  565. else
  566. {
  567. mHighestPacketID = llmax(mHighestPacketID, id);
  568. }
  569. // Save packet arrival time
  570. mLastPacketInTime = LLMessageSystem::getMessageTimeSeconds();
  571. // Have we received anything on this circuit yet?
  572. if (0 == mPacketsIn)
  573. {
  574. // Must be first packet from unclosed circuit.
  575. mPacketsIn++;
  576. setPacketInID((id + 1) % LL_MAX_OUT_PACKET_ID);
  577. mLastPacketGap = 0;
  578. mOutOfOrderRate.count(0);
  579. return;
  580. }
  581. mPacketsIn++;
  582. // now, check to see if we've got a gap
  583. U32 gap = 0;
  584. if ((mPacketsInID == id))
  585. {
  586. // nope! bump and wrap the counter, then return
  587. mPacketsInID++;
  588. mPacketsInID = (mPacketsInID) % LL_MAX_OUT_PACKET_ID;
  589. }
  590. else if (id < mWrapID)
  591. {
  592. // id < mWrapID will happen if the first few packets are out of order. . .
  593. // at that point we haven't marked anything "potentially lost" and
  594. // the out-of-order packet will cause a full wrap marking all the IDs "potentially lost"
  595. // do nothing
  596. }
  597. else
  598. {
  599. // we have a gap! if that id is in the map, remove it from the map, leave mCurrentCircuit->mPacketsInID
  600. // alone
  601. // otherwise, walk from mCurrentCircuit->mPacketsInID to id with wrapping, adding the values to the map
  602. // and setting mPacketsInID to id + 1 % LL_MAX_OUT_PACKET_ID
  603. // babbage: all operands in expression are unsigned, so modular
  604. // arithmetic will always find correct gap, regardless of wrap arounds.
  605. const U8 width = 24;
  606. gap = LLModularMath::subtract<width>(mPacketsInID, id);
  607. if (mPotentialLostPackets.find(id) != mPotentialLostPackets.end())
  608. {
  609. if(gMessageSystem->mVerboseLog)
  610. {
  611. std::ostringstream str;
  612. str << "MSG: <- " << mHost << "\tRECOVERING LOST:\t" << id;
  613. llinfos << str.str() << llendl;
  614. }
  615. // llinfos << "removing potential lost: " << id << llendl;
  616. mPotentialLostPackets.erase(id);
  617. }
  618. else if (!receive_resent) // don't freak out over out-of-order reliable resends
  619. {
  620. U64 time = LLMessageSystem::getMessageTimeUsecs();
  621. TPACKETID index = mPacketsInID;
  622. S32 gap_count = 0;
  623. if ((index < id) && ((id - index) < 16))
  624. {
  625. while (index != id)
  626. {
  627. if(gMessageSystem->mVerboseLog)
  628. {
  629. std::ostringstream str;
  630. str << "MSG: <- " << mHost << "\tPACKET GAP:\t"
  631. << index;
  632. llinfos << str.str() << llendl;
  633. }
  634. // llinfos << "adding potential lost: " << index << llendl;
  635. mPotentialLostPackets[index] = time;
  636. index++;
  637. index = index % LL_MAX_OUT_PACKET_ID;
  638. gap_count++;
  639. }
  640. }
  641. else
  642. {
  643. llinfos << "packet_out_of_order - got packet " << id << " expecting " << index << " from " << mHost << llendl;
  644. if(gMessageSystem->mVerboseLog)
  645. {
  646. std::ostringstream str;
  647. str << "MSG: <- " << mHost << "\tPACKET GAP:\t"
  648. << id << " expected " << index;
  649. llinfos << str.str() << llendl;
  650. }
  651. }
  652. mPacketsInID = id + 1;
  653. mPacketsInID = (mPacketsInID) % LL_MAX_OUT_PACKET_ID;
  654. if (gap_count > 128)
  655. {
  656. llwarns << "Packet loss gap filler running amok!" << llendl;
  657. }
  658. else if (gap_count > 16)
  659. {
  660. llwarns << "Sustaining large amounts of packet loss!" << llendl;
  661. }
  662. }
  663. }
  664. mOutOfOrderRate.count(gap);
  665. mLastPacketGap = gap;
  666. }
  667. void LLCircuit::updateWatchDogTimers(LLMessageSystem *msgsys)
  668. {
  669. F64 cur_time = LLMessageSystem::getMessageTimeSeconds();
  670. S32 count = mPingSet.size();
  671. S32 cur = 0;
  672. // Only process each circuit once at most, stop processing if no circuits
  673. while((cur < count) && !mPingSet.empty())
  674. {
  675. cur++;
  676. LLCircuit::ping_set_t::iterator psit = mPingSet.begin();
  677. LLCircuitData *cdp = *psit;
  678. if (!cdp->mbAlive)
  679. {
  680. // We suspect that this case should never happen, given how
  681. // the alive status is set.
  682. // Skip over dead circuits, just add the ping interval and push it to the back
  683. // Always remember to remove it from the set before changing the sorting
  684. // key (mNextPingSendTime)
  685. mPingSet.erase(psit);
  686. cdp->mNextPingSendTime = cur_time + mHeartbeatInterval;
  687. mPingSet.insert(cdp);
  688. continue;
  689. }
  690. else
  691. {
  692. // Check to see if this needs a ping
  693. if (cur_time < cdp->mNextPingSendTime)
  694. {
  695. // This circuit doesn't need a ping, break out because
  696. // we have a sorted list, thus no more circuits need pings
  697. break;
  698. }
  699. // Update watchdog timers
  700. if (cdp->updateWatchDogTimers(msgsys))
  701. {
  702. // Randomize our pings a bit by doing some up to 5% early or late
  703. F64 dt = 0.95f*mHeartbeatInterval + ll_frand(0.1f*mHeartbeatInterval);
  704. // Remove it, and reinsert it with the new next ping time.
  705. // Always remove before changing the sorting key.
  706. mPingSet.erase(psit);
  707. cdp->mNextPingSendTime = cur_time + dt;
  708. mPingSet.insert(cdp);
  709. // Update our throttles
  710. cdp->mThrottles.dynamicAdjust();
  711. // Update some stats, this is not terribly important
  712. cdp->checkPeriodTime();
  713. }
  714. else
  715. {
  716. // This mPingSet.erase isn't necessary, because removing the circuit will
  717. // remove the ping set.
  718. //mPingSet.erase(psit);
  719. removeCircuitData(cdp->mHost);
  720. }
  721. }
  722. }
  723. }
  724. BOOL LLCircuitData::updateWatchDogTimers(LLMessageSystem *msgsys)
  725. {
  726. F64 cur_time = LLMessageSystem::getMessageTimeSeconds();
  727. mLastPingSendTime = cur_time;
  728. if (!checkCircuitTimeout())
  729. {
  730. // Pass this back to the calling LLCircuit, this circuit needs to be cleaned up.
  731. return FALSE;
  732. }
  733. // WARNING!
  734. // Duplicate suppression can FAIL if packets are delivered out of
  735. // order, although it's EXTREMELY unlikely. It would require
  736. // that the ping get delivered out of order enough that the ACK
  737. // for the packet that it was out of order with was received BEFORE
  738. // the ping was sent.
  739. // Find the current oldest reliable packetID
  740. // This is to handle the case if we actually manage to wrap our
  741. // packet IDs - the oldest will actually have a higher packet ID
  742. // than the current.
  743. BOOL wrapped = FALSE;
  744. reliable_iter iter;
  745. iter = mUnackedPackets.upper_bound(getPacketOutID());
  746. if (iter == mUnackedPackets.end())
  747. {
  748. // Nothing AFTER this one, so we want the lowest packet ID
  749. // then.
  750. iter = mUnackedPackets.begin();
  751. wrapped = TRUE;
  752. }
  753. TPACKETID packet_id = 0;
  754. // Check against the "final" packets
  755. BOOL wrapped_final = FALSE;
  756. reliable_iter iter_final;
  757. iter_final = mFinalRetryPackets.upper_bound(getPacketOutID());
  758. if (iter_final == mFinalRetryPackets.end())
  759. {
  760. iter_final = mFinalRetryPackets.begin();
  761. wrapped_final = TRUE;
  762. }
  763. //llinfos << mHost << " - unacked count " << mUnackedPackets.size() << llendl;
  764. //llinfos << mHost << " - final count " << mFinalRetryPackets.size() << llendl;
  765. if (wrapped != wrapped_final)
  766. {
  767. // One of the "unacked" or "final" lists hasn't wrapped. Whichever one
  768. // hasn't has the oldest packet.
  769. if (!wrapped)
  770. {
  771. // Hasn't wrapped, so the one on the
  772. // unacked packet list is older
  773. packet_id = iter->first;
  774. //llinfos << mHost << ": nowrapped unacked" << llendl;
  775. }
  776. else
  777. {
  778. packet_id = iter_final->first;
  779. //llinfos << mHost << ": nowrapped final" << llendl;
  780. }
  781. }
  782. else
  783. {
  784. // They both wrapped, we can just use the minimum of the two.
  785. if ((iter == mUnackedPackets.end()) && (iter_final == mFinalRetryPackets.end()))
  786. {
  787. // Wow! No unacked packets at all!
  788. // Send the ID of the last packet we sent out.
  789. // This will flush all of the destination's
  790. // unacked packets, theoretically.
  791. //llinfos << mHost << ": No unacked!" << llendl;
  792. packet_id = getPacketOutID();
  793. }
  794. else
  795. {
  796. BOOL had_unacked = FALSE;
  797. if (iter != mUnackedPackets.end())
  798. {
  799. // Unacked list has the lowest so far
  800. packet_id = iter->first;
  801. had_unacked = TRUE;
  802. //llinfos << mHost << ": Unacked" << llendl;
  803. }
  804. if (iter_final != mFinalRetryPackets.end())
  805. {
  806. // Use the lowest of the unacked list and the final list
  807. if (had_unacked)
  808. {
  809. // Both had a packet, use the lowest.
  810. packet_id = llmin(packet_id, iter_final->first);
  811. //llinfos << mHost << ": Min of unacked/final" << llendl;
  812. }
  813. else
  814. {
  815. // Only the final had a packet, use it.
  816. packet_id = iter_final->first;
  817. //llinfos << mHost << ": Final!" << llendl;
  818. }
  819. }
  820. }
  821. }
  822. // Send off the another ping.
  823. pingTimerStart();
  824. msgsys->newMessageFast(_PREHASH_StartPingCheck);
  825. msgsys->nextBlock(_PREHASH_PingID);
  826. msgsys->addU8Fast(_PREHASH_PingID, nextPingID());
  827. msgsys->addU32Fast(_PREHASH_OldestUnacked, packet_id);
  828. msgsys->sendMessage(mHost);
  829. // Also do lost packet accounting.
  830. // Check to see if anything on our lost list is old enough to
  831. // be considered lost
  832. LLCircuitData::packet_time_map::iterator it;
  833. U64 timeout = (U64)(1000000.0*llmin(LL_MAX_LOST_TIMEOUT, getPingDelayAveraged() * LL_LOST_TIMEOUT_FACTOR));
  834. U64 mt_usec = LLMessageSystem::getMessageTimeUsecs();
  835. for (it = mPotentialLostPackets.begin(); it != mPotentialLostPackets.end(); )
  836. {
  837. U64 delta_t_usec = mt_usec - (*it).second;
  838. if (delta_t_usec > timeout)
  839. {
  840. // let's call this one a loss!
  841. mPacketsLost++;
  842. gMessageSystem->mDroppedPackets++;
  843. if(gMessageSystem->mVerboseLog)
  844. {
  845. std::ostringstream str;
  846. str << "MSG: <- " << mHost << "\tLOST PACKET:\t"
  847. << (*it).first;
  848. llinfos << str.str() << llendl;
  849. }
  850. mPotentialLostPackets.erase(it++);
  851. }
  852. else
  853. {
  854. ++it;
  855. }
  856. }
  857. return TRUE;
  858. }
  859. void LLCircuitData::clearDuplicateList(TPACKETID oldest_id)
  860. {
  861. // purge old data from the duplicate suppression queue
  862. // we want to KEEP all x where oldest_id <= x <= last incoming packet, and delete everything else.
  863. //llinfos << mHost << ": clearing before oldest " << oldest_id << llendl;
  864. //llinfos << "Recent list before: " << mRecentlyReceivedReliablePackets.size() << llendl;
  865. if (oldest_id < mHighestPacketID)
  866. {
  867. // Clean up everything with a packet ID less than oldest_id.
  868. packet_time_map::iterator pit_start;
  869. packet_time_map::iterator pit_end;
  870. pit_start = mRecentlyReceivedReliablePackets.begin();
  871. pit_end = mRecentlyReceivedReliablePackets.lower_bound(oldest_id);
  872. mRecentlyReceivedReliablePackets.erase(pit_start, pit_end);
  873. }
  874. // Do timeout checks on everything with an ID > mHighestPacketID.
  875. // This should be empty except for wrapping IDs. Thus, this should be
  876. // highly rare.
  877. U64 mt_usec = LLMessageSystem::getMessageTimeUsecs();
  878. packet_time_map::iterator pit;
  879. for(pit = mRecentlyReceivedReliablePackets.upper_bound(mHighestPacketID);
  880. pit != mRecentlyReceivedReliablePackets.end(); )
  881. {
  882. // Validate that the packet ID seems far enough away
  883. if ((pit->first - mHighestPacketID) < 100)
  884. {
  885. llwarns << "Probably incorrectly timing out non-wrapped packets!" << llendl;
  886. }
  887. U64 delta_t_usec = mt_usec - (*pit).second;
  888. F64 delta_t_sec = delta_t_usec * SEC_PER_USEC;
  889. if (delta_t_sec > LL_DUPLICATE_SUPPRESSION_TIMEOUT)
  890. {
  891. // enough time has elapsed we're not likely to get a duplicate on this one
  892. llinfos << "Clearing " << pit->first << " from recent list" << llendl;
  893. mRecentlyReceivedReliablePackets.erase(pit++);
  894. }
  895. else
  896. {
  897. ++pit;
  898. }
  899. }
  900. //llinfos << "Recent list after: " << mRecentlyReceivedReliablePackets.size() << llendl;
  901. }
  902. BOOL LLCircuitData::checkCircuitTimeout()
  903. {
  904. F64 time_since_last_ping = LLMessageSystem::getMessageTimeSeconds() - mLastPingReceivedTime;
  905. // Nota Bene: This needs to be turned off if you are debugging multiple simulators
  906. if (time_since_last_ping > mHeartbeatTimeout)
  907. {
  908. llwarns << "LLCircuitData::checkCircuitTimeout for " << mHost << " last ping " << time_since_last_ping << " seconds ago." <<llendl;
  909. setAlive(FALSE);
  910. if (mTimeoutCallback)
  911. {
  912. llwarns << "LLCircuitData::checkCircuitTimeout for " << mHost << " calling callback." << llendl;
  913. mTimeoutCallback(mHost, mTimeoutUserData);
  914. }
  915. if (!isAlive())
  916. {
  917. // The callback didn't try and resurrect the circuit. We should kill it.
  918. llwarns << "LLCircuitData::checkCircuitTimeout for " << mHost << " still dead, dropping." << llendl;
  919. return FALSE;
  920. }
  921. }
  922. return TRUE;
  923. }
  924. // Call this method when a reliable message comes in - this will
  925. // correctly place the packet in the correct list to be acked later.
  926. BOOL LLCircuitData::collectRAck(TPACKETID packet_num)
  927. {
  928. if (mAcks.empty())
  929. {
  930. // First extra ack, we need to add ourselves to the list of circuits that need to send acks
  931. gMessageSystem->mCircuitInfo.mSendAckMap[mHost] = this;
  932. }
  933. mAcks.push_back(packet_num);
  934. return TRUE;
  935. }
  936. // this method is called during the message system processAcks() to
  937. // send out any acks that did not get sent already.
  938. void LLCircuit::sendAcks()
  939. {
  940. LLCircuitData* cd;
  941. circuit_data_map::iterator end = mSendAckMap.end();
  942. for(circuit_data_map::iterator it = mSendAckMap.begin(); it != end; ++it)
  943. {
  944. cd = (*it).second;
  945. S32 count = (S32)cd->mAcks.size();
  946. if(count > 0)
  947. {
  948. // send the packet acks
  949. S32 acks_this_packet = 0;
  950. for(S32 i = 0; i < count; ++i)
  951. {
  952. if(acks_this_packet == 0)
  953. {
  954. gMessageSystem->newMessageFast(_PREHASH_PacketAck);
  955. }
  956. gMessageSystem->nextBlockFast(_PREHASH_Packets);
  957. gMessageSystem->addU32Fast(_PREHASH_ID, cd->mAcks[i]);
  958. ++acks_this_packet;
  959. if(acks_this_packet > 250)
  960. {
  961. gMessageSystem->sendMessage(cd->mHost);
  962. acks_this_packet = 0;
  963. }
  964. }
  965. if(acks_this_packet > 0)
  966. {
  967. gMessageSystem->sendMessage(cd->mHost);
  968. }
  969. if(gMessageSystem->mVerboseLog)
  970. {
  971. std::ostringstream str;
  972. str << "MSG: -> " << cd->mHost << "\tPACKET ACKS:\t";
  973. std::ostream_iterator<TPACKETID> append(str, " ");
  974. std::copy(cd->mAcks.begin(), cd->mAcks.end(), append);
  975. llinfos << str.str() << llendl;
  976. }
  977. // empty out the acks list
  978. cd->mAcks.clear();
  979. }
  980. }
  981. // All acks have been sent, clear the map
  982. mSendAckMap.clear();
  983. }
  984. std::ostream& operator<<(std::ostream& s, LLCircuitData& circuit)
  985. {
  986. F32 age = circuit.mExistenceTimer.getElapsedTimeF32();
  987. using namespace std;
  988. s << "Circuit " << circuit.mHost << " ";
  989. s << circuit.mRemoteID << " ";
  990. s << (circuit.mbAlive ? "Alive" : "Not Alive") << " ";
  991. s << (circuit.mbAllowTimeout ? "Timeout Allowed" : "Timeout Not Allowed");
  992. s << endl;
  993. s << " Packets Lost: " << circuit.mPacketsLost;
  994. s << " Measured Ping: " << circuit.mPingDelay;
  995. s << " Averaged Ping: " << circuit.mPingDelayAveraged;
  996. s << endl;
  997. s << "Global In/Out " << S32(age) << " sec";
  998. s << " KBytes: " << circuit.mBytesIn / 1024 << "/" << circuit.mBytesOut / 1024;
  999. s << " Kbps: ";
  1000. s << S32(circuit.mBytesIn * 8.f / circuit.mExistenceTimer.getElapsedTimeF32() / 1024.f);
  1001. s << "/";
  1002. s << S32(circuit.mBytesOut * 8.f / circuit.mExistenceTimer.getElapsedTimeF32() / 1024.f);
  1003. s << " Packets: " << circuit.mPacketsIn << "/" << circuit.mPacketsOut;
  1004. s << endl;
  1005. s << "Recent In/Out " << S32(circuit.mLastPeriodLength) << " sec";
  1006. s << " KBytes: ";
  1007. s << circuit.mBytesInLastPeriod / 1024;
  1008. s << "/";
  1009. s << circuit.mBytesOutLastPeriod / 1024;
  1010. s << " Kbps: ";
  1011. s << S32(circuit.mBytesInLastPeriod * 8.f / circuit.mLastPeriodLength / 1024.f);
  1012. s << "/";
  1013. s << S32(circuit.mBytesOutLastPeriod * 8.f / circuit.mLastPeriodLength / 1024.f);
  1014. s << " Peak kbps: ";
  1015. s << S32(circuit.mPeakBPSIn / 1024.f);
  1016. s << "/";
  1017. s << S32(circuit.mPeakBPSOut / 1024.f);
  1018. s << endl;
  1019. return s;
  1020. }
  1021. void LLCircuitData::getInfo(LLSD& info) const
  1022. {
  1023. info["Host"] = mHost.getIPandPort();
  1024. info["Alive"] = mbAlive;
  1025. info["Age"] = mExistenceTimer.getElapsedTimeF32();
  1026. }
  1027. void LLCircuitData::dumpResendCountAndReset()
  1028. {
  1029. if (mCurrentResendCount)
  1030. {
  1031. llinfos << "Circuit: " << mHost << " resent " << mCurrentResendCount << " packets" << llendl;
  1032. mCurrentResendCount = 0;
  1033. }
  1034. }
  1035. std::ostream& operator<<(std::ostream& s, LLCircuit &circuit)
  1036. {
  1037. s << "Circuit Info:" << std::endl;
  1038. LLCircuit::circuit_data_map::iterator end = circuit.mCircuitData.end();
  1039. LLCircuit::circuit_data_map::iterator it;
  1040. for(it = circuit.mCircuitData.begin(); it != end; ++it)
  1041. {
  1042. s << *((*it).second) << std::endl;
  1043. }
  1044. return s;
  1045. }
  1046. void LLCircuit::getInfo(LLSD& info) const
  1047. {
  1048. LLCircuit::circuit_data_map::const_iterator end = mCircuitData.end();
  1049. LLCircuit::circuit_data_map::const_iterator it;
  1050. LLSD circuit_info;
  1051. for(it = mCircuitData.begin(); it != end; ++it)
  1052. {
  1053. (*it).second->getInfo(circuit_info);
  1054. info["Circuits"].append(circuit_info);
  1055. }
  1056. }
  1057. void LLCircuit::getCircuitRange(
  1058. const LLHost& key,
  1059. LLCircuit::circuit_data_map::iterator& first,
  1060. LLCircuit::circuit_data_map::iterator& end)
  1061. {
  1062. end = mCircuitData.end();
  1063. first = mCircuitData.upper_bound(key);
  1064. }
  1065. TPACKETID LLCircuitData::nextPacketOutID()
  1066. {
  1067. mPacketsOut++;
  1068. TPACKETID id;
  1069. id = (mPacketsOutID + 1) % LL_MAX_OUT_PACKET_ID;
  1070. if (id < mPacketsOutID)
  1071. {
  1072. // we just wrapped on a circuit, reset the wrap ID to zero
  1073. mWrapID = 0;
  1074. }
  1075. mPacketsOutID = id;
  1076. return id;
  1077. }
  1078. void LLCircuitData::setPacketInID(TPACKETID id)
  1079. {
  1080. id = id % LL_MAX_OUT_PACKET_ID;
  1081. mPacketsInID = id;
  1082. mRecentlyReceivedReliablePackets.clear();
  1083. mWrapID = id;
  1084. }
  1085. void LLCircuitData::pingTimerStop(const U8 ping_id)
  1086. {
  1087. F64 mt_secs = LLMessageSystem::getMessageTimeSeconds();
  1088. // Nota Bene: no averaging of ping times until we get a feel for how this works
  1089. F64 time = mt_secs - mPingTime;
  1090. if (time == 0.0)
  1091. {
  1092. // Ack, we got our ping response on the same frame! Sigh, let's get a real time otherwise
  1093. // all of our ping calculations will be skewed.
  1094. mt_secs = LLMessageSystem::getMessageTimeSeconds(TRUE);
  1095. }
  1096. mLastPingReceivedTime = mt_secs;
  1097. // If ping is longer than 1 second, we'll get sequence deltas in the ping.
  1098. // Approximate by assuming each ping counts for 1 second (slightly low, probably)
  1099. S32 delta_ping = (S32)mLastPingID - (S32) ping_id;
  1100. if (delta_ping < 0)
  1101. {
  1102. delta_ping += 256;
  1103. }
  1104. U32 msec = (U32) ((delta_ping*mHeartbeatInterval + time) * 1000.f);
  1105. setPingDelay(msec);
  1106. mPingsInTransit = delta_ping;
  1107. if (mBlocked && (mPingsInTransit <= PING_RELEASE_BLOCK))
  1108. {
  1109. mBlocked = FALSE;
  1110. }
  1111. }
  1112. void LLCircuitData::pingTimerStart()
  1113. {
  1114. mPingTime = LLMessageSystem::getMessageTimeSeconds();
  1115. mPingsInTransit++;
  1116. if (!mBlocked && (mPingsInTransit > PING_START_BLOCK))
  1117. {
  1118. mBlocked = TRUE;
  1119. }
  1120. }
  1121. U32 LLCircuitData::getPacketsIn() const
  1122. {
  1123. return mPacketsIn;
  1124. }
  1125. S32 LLCircuitData::getBytesIn() const
  1126. {
  1127. return mBytesIn;
  1128. }
  1129. S32 LLCircuitData::getBytesOut() const
  1130. {
  1131. return mBytesOut;
  1132. }
  1133. U32 LLCircuitData::getPacketsOut() const
  1134. {
  1135. return mPacketsOut;
  1136. }
  1137. TPACKETID LLCircuitData::getPacketOutID() const
  1138. {
  1139. return mPacketsOutID;
  1140. }
  1141. U32 LLCircuitData::getPacketsLost() const
  1142. {
  1143. return mPacketsLost;
  1144. }
  1145. BOOL LLCircuitData::isAlive() const
  1146. {
  1147. return mbAlive;
  1148. }
  1149. BOOL LLCircuitData::isBlocked() const
  1150. {
  1151. return mBlocked;
  1152. }
  1153. BOOL LLCircuitData::getAllowTimeout() const
  1154. {
  1155. return mbAllowTimeout;
  1156. }
  1157. U32 LLCircuitData::getPingDelay() const
  1158. {
  1159. return mPingDelay;
  1160. }
  1161. F32 LLCircuitData::getPingInTransitTime()
  1162. {
  1163. // This may be inaccurate in the case of a circuit that was "dead" and then revived,
  1164. // but only until the first round trip ping is sent - djs
  1165. F32 time_since_ping_was_sent = 0;
  1166. if (mPingsInTransit)
  1167. {
  1168. time_since_ping_was_sent = (F32)((mPingsInTransit*mHeartbeatInterval - 1)
  1169. + (LLMessageSystem::getMessageTimeSeconds() - mPingTime))*1000.f;
  1170. }
  1171. return time_since_ping_was_sent;
  1172. }
  1173. void LLCircuitData::setPingDelay(U32 ping)
  1174. {
  1175. mPingDelay = ping;
  1176. mPingDelayAveraged = llmax((F32)ping, getPingDelayAveraged());
  1177. mPingDelayAveraged = ((1.f - LL_AVERAGED_PING_ALPHA) * mPingDelayAveraged)
  1178. + (LL_AVERAGED_PING_ALPHA * (F32) ping);
  1179. mPingDelayAveraged = llclamp(mPingDelayAveraged,
  1180. LL_AVERAGED_PING_MIN,
  1181. LL_AVERAGED_PING_MAX);
  1182. }
  1183. F32 LLCircuitData::getPingDelayAveraged()
  1184. {
  1185. return llmin(llmax(getPingInTransitTime(), mPingDelayAveraged), LL_AVERAGED_PING_MAX);
  1186. }
  1187. BOOL LLCircuitData::getTrusted() const
  1188. {
  1189. return mTrusted;
  1190. }
  1191. void LLCircuitData::setTrusted(BOOL t)
  1192. {
  1193. mTrusted = t;
  1194. }
  1195. F32 LLCircuitData::getAgeInSeconds() const
  1196. {
  1197. return mExistenceTimer.getElapsedTimeF32();
  1198. }