LLPacketHandler.cs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853
  1. /*
  2. * Copyright (c) Contributors, http://opensimulator.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the OpenSimulator Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. using System;
  28. using System.Reflection;
  29. using System.Collections.Generic;
  30. using System.Net.Sockets;
  31. using System.Threading;
  32. using System.Timers;
  33. using OpenMetaverse;
  34. using OpenMetaverse.Packets;
  35. using log4net;
  36. using OpenSim.Framework;
  37. using Timer=System.Timers.Timer;
  38. namespace OpenSim.Region.ClientStack.LindenUDP
  39. {
  40. public class LLPacketHandler : ILLPacketHandler
  41. {
  42. private static readonly ILog m_log
  43. = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  44. //private int m_resentCount;
  45. // Packet queues
  46. //
  47. LLPacketQueue m_PacketQueue;
  48. public LLPacketQueue PacketQueue
  49. {
  50. get { return m_PacketQueue; }
  51. }
  52. // Timer to run stats and acks on
  53. //
  54. private Timer m_AckTimer = new Timer(250);
  55. // A list of the packets we haven't acked yet
  56. //
  57. private List<uint> m_PendingAcks = new List<uint>();
  58. private Dictionary<uint, uint> m_PendingAcksMap = new Dictionary<uint, uint>();
  59. private Dictionary<uint, LLQueItem> m_NeedAck =
  60. new Dictionary<uint, LLQueItem>();
  61. /// <summary>
  62. /// The number of milliseconds that can pass before a packet that needs an ack is resent.
  63. /// </param>
  64. private uint m_ResendTimeout = 4000;
  65. public uint ResendTimeout
  66. {
  67. get { return m_ResendTimeout; }
  68. set { m_ResendTimeout = value; }
  69. }
  70. private int m_MaxReliableResends = 3;
  71. public int MaxReliableResends
  72. {
  73. get { return m_MaxReliableResends; }
  74. set { m_MaxReliableResends = value; }
  75. }
  76. // Track duplicated packets. This uses a Dictionary. Both insertion
  77. // and lookup are common operations and need to take advantage of
  78. // the hashing. Expiration is less common and can be allowed the
  79. // time for a linear scan.
  80. //
  81. private List<uint> m_alreadySeenList = new List<uint>();
  82. private Dictionary<uint, int>m_alreadySeenTracker = new Dictionary<uint, int>();
  83. private int m_alreadySeenWindow = 30000;
  84. private int m_lastAlreadySeenCheck = Environment.TickCount & Int32.MaxValue;
  85. // private Dictionary<uint, int> m_DupeTracker =
  86. // new Dictionary<uint, int>();
  87. // private uint m_DupeTrackerWindow = 30;
  88. // private int m_DupeTrackerLastCheck = Environment.TickCount;
  89. // Values for the SimStatsReporter
  90. //
  91. private int m_PacketsReceived = 0;
  92. private int m_PacketsReceivedReported = 0;
  93. private int m_PacketsSent = 0;
  94. private int m_PacketsSentReported = 0;
  95. private int m_UnackedBytes = 0;
  96. private int m_LastResend = 0;
  97. public int PacketsReceived
  98. {
  99. get { return m_PacketsReceived; }
  100. }
  101. public int PacketsReceivedReported
  102. {
  103. get { return m_PacketsReceivedReported; }
  104. }
  105. // The client we are working for
  106. //
  107. private IClientAPI m_Client;
  108. // Some events
  109. //
  110. public event PacketStats OnPacketStats;
  111. public event PacketDrop OnPacketDrop;
  112. //private SynchronizeClientHandler m_SynchronizeClient = null;
  113. public SynchronizeClientHandler SynchronizeClient
  114. {
  115. set { /* m_SynchronizeClient = value; */ }
  116. }
  117. // Packet sequencing
  118. //
  119. private uint m_Sequence = 0;
  120. private object m_SequenceLock = new object();
  121. private const int MAX_SEQUENCE = 0xFFFFFF;
  122. // Packet dropping
  123. //
  124. List<PacketType> m_ImportantPackets = new List<PacketType>();
  125. private bool m_ReliableIsImportant = false;
  126. public bool ReliableIsImportant
  127. {
  128. get { return m_ReliableIsImportant; }
  129. set { m_ReliableIsImportant = value; }
  130. }
  131. private int m_DropSafeTimeout;
  132. LLPacketServer m_PacketServer;
  133. private byte[] m_ZeroOutBuffer = new byte[4096];
  134. ////////////////////////////////////////////////////////////////////
  135. // Constructors
  136. //
  137. public LLPacketHandler(IClientAPI client, LLPacketServer server, ClientStackUserSettings userSettings)
  138. {
  139. m_Client = client;
  140. m_PacketServer = server;
  141. m_DropSafeTimeout = Environment.TickCount + 15000;
  142. m_PacketQueue = new LLPacketQueue(client.AgentId, userSettings);
  143. m_AckTimer.Elapsed += AckTimerElapsed;
  144. m_AckTimer.Start();
  145. }
  146. public void Stop()
  147. {
  148. m_AckTimer.Stop();
  149. m_PacketQueue.Enqueue(null);
  150. m_PacketQueue.Close();
  151. m_Client = null;
  152. }
  153. // Send one packet. This actually doesn't send anything, it queues
  154. // it. Designed to be fire-and-forget, but there is an optional
  155. // notifier.
  156. //
  157. public void OutPacket(
  158. Packet packet, ThrottleOutPacketType throttlePacketType)
  159. {
  160. OutPacket(packet, throttlePacketType, null);
  161. }
  162. public void OutPacket(
  163. Packet packet, ThrottleOutPacketType throttlePacketType,
  164. Object id)
  165. {
  166. // Call the load balancer's hook. If this is not active here
  167. // we defer to the sim server this client is actually connected
  168. // to. Packet drop notifies will not be triggered in this
  169. // configuration!
  170. //
  171. packet.Header.Sequence = 0;
  172. lock (m_NeedAck)
  173. {
  174. DropResend(id);
  175. AddAcks(ref packet);
  176. QueuePacket(packet, throttlePacketType, id);
  177. }
  178. }
  179. private void AddAcks(ref Packet packet)
  180. {
  181. // These packet types have shown to have issues with
  182. // acks being appended to the payload, just don't send
  183. // any with them until libsl is fixed.
  184. //
  185. if (packet is ViewerEffectPacket)
  186. return;
  187. if (packet is SimStatsPacket)
  188. return;
  189. // Add acks to outgoing packets
  190. //
  191. if (m_PendingAcks.Count > 0)
  192. {
  193. int count = m_PendingAcks.Count;
  194. if (count > 10)
  195. count = 10;
  196. packet.Header.AckList = new uint[count];
  197. packet.Header.AppendedAcks = true;
  198. for (int i = 0; i < count; i++)
  199. {
  200. packet.Header.AckList[i] = m_PendingAcks[i];
  201. m_PendingAcksMap.Remove(m_PendingAcks[i]);
  202. }
  203. m_PendingAcks.RemoveRange(0, count);
  204. }
  205. }
  206. private void QueuePacket(
  207. Packet packet, ThrottleOutPacketType throttlePacketType,
  208. Object id)
  209. {
  210. LLQueItem item = new LLQueItem();
  211. item.Packet = packet;
  212. item.Incoming = false;
  213. item.throttleType = throttlePacketType;
  214. item.TickCount = Environment.TickCount;
  215. item.Identifier = id;
  216. item.Resends = 0;
  217. item.Length = packet.Length;
  218. item.Sequence = packet.Header.Sequence;
  219. m_PacketQueue.Enqueue(item);
  220. m_PacketsSent++;
  221. }
  222. private void ResendUnacked()
  223. {
  224. int now = Environment.TickCount;
  225. int intervalMs = 250;
  226. if (m_LastResend != 0)
  227. intervalMs = now - m_LastResend;
  228. lock (m_NeedAck)
  229. {
  230. if (m_DropSafeTimeout > now ||
  231. intervalMs > 500) // We were frozen!
  232. {
  233. foreach (LLQueItem data in m_NeedAck.Values)
  234. {
  235. if (m_DropSafeTimeout > now)
  236. {
  237. m_NeedAck[data.Packet.Header.Sequence].TickCount = now;
  238. }
  239. else
  240. {
  241. m_NeedAck[data.Packet.Header.Sequence].TickCount += intervalMs;
  242. }
  243. }
  244. }
  245. m_LastResend = now;
  246. // Unless we have received at least one ack, don't bother resending
  247. // anything. There may not be a client there, don't clog up the
  248. // pipes.
  249. // Nothing to do
  250. //
  251. if (m_NeedAck.Count == 0)
  252. return;
  253. int resent = 0;
  254. long dueDate = now - m_ResendTimeout;
  255. List<LLQueItem> dropped = new List<LLQueItem>();
  256. foreach (LLQueItem data in m_NeedAck.Values)
  257. {
  258. Packet packet = data.Packet;
  259. // Packets this old get resent
  260. //
  261. if (data.TickCount < dueDate && data.Sequence != 0 && !m_PacketQueue.Contains(data.Sequence))
  262. {
  263. if (resent < 20) // Was 20 (= Max 117kbit/sec resends)
  264. {
  265. m_NeedAck[packet.Header.Sequence].Resends++;
  266. // The client needs to be told that a packet is being resent, otherwise it appears to believe
  267. // that it should reset its sequence to that packet number.
  268. packet.Header.Resent = true;
  269. if ((m_NeedAck[packet.Header.Sequence].Resends >= m_MaxReliableResends) &&
  270. (!m_ReliableIsImportant))
  271. {
  272. dropped.Add(data);
  273. continue;
  274. }
  275. m_NeedAck[packet.Header.Sequence].TickCount = Environment.TickCount;
  276. QueuePacket(packet, ThrottleOutPacketType.Resend, data.Identifier);
  277. resent++;
  278. }
  279. else
  280. {
  281. m_NeedAck[packet.Header.Sequence].TickCount += intervalMs;
  282. }
  283. }
  284. }
  285. foreach (LLQueItem data in dropped)
  286. {
  287. m_NeedAck.Remove(data.Packet.Header.Sequence);
  288. TriggerOnPacketDrop(data.Packet, data.Identifier);
  289. m_PacketQueue.Cancel(data.Packet.Header.Sequence);
  290. PacketPool.Instance.ReturnPacket(data.Packet);
  291. }
  292. }
  293. }
  294. // Send the pending packet acks to the client
  295. // Will send blocks of acks for up to 250 packets
  296. //
  297. private void SendAcks()
  298. {
  299. lock (m_NeedAck)
  300. {
  301. if (m_PendingAcks.Count == 0)
  302. return;
  303. PacketAckPacket acks = (PacketAckPacket)PacketPool.Instance.GetPacket(PacketType.PacketAck);
  304. // The case of equality is more common than one might think,
  305. // because this function will be called unconditionally when
  306. // the counter reaches 250. So there is a good chance another
  307. // packet with 250 blocks exists.
  308. //
  309. if (acks.Packets == null ||
  310. acks.Packets.Length != m_PendingAcks.Count)
  311. acks.Packets = new PacketAckPacket.PacketsBlock[m_PendingAcks.Count];
  312. for (int i = 0; i < m_PendingAcks.Count; i++)
  313. {
  314. acks.Packets[i] = new PacketAckPacket.PacketsBlock();
  315. acks.Packets[i].ID = m_PendingAcks[i];
  316. }
  317. m_PendingAcks.Clear();
  318. m_PendingAcksMap.Clear();
  319. acks.Header.Reliable = false;
  320. OutPacket(acks, ThrottleOutPacketType.Unknown);
  321. }
  322. }
  323. // Queue a packet ack. It will be sent either after 250 acks are
  324. // queued, or when the timer fires.
  325. //
  326. private void AckPacket(Packet packet)
  327. {
  328. lock (m_NeedAck)
  329. {
  330. if (m_PendingAcks.Count < 250)
  331. {
  332. if (!m_PendingAcksMap.ContainsKey(packet.Header.Sequence))
  333. {
  334. m_PendingAcks.Add(packet.Header.Sequence);
  335. m_PendingAcksMap.Add(packet.Header.Sequence,
  336. packet.Header.Sequence);
  337. }
  338. return;
  339. }
  340. }
  341. SendAcks();
  342. lock (m_NeedAck)
  343. {
  344. // If this is still full we have a truly exceptional
  345. // condition (means, can't happen)
  346. //
  347. if (m_PendingAcks.Count < 250)
  348. {
  349. if (!m_PendingAcksMap.ContainsKey(packet.Header.Sequence))
  350. {
  351. m_PendingAcks.Add(packet.Header.Sequence);
  352. m_PendingAcksMap.Add(packet.Header.Sequence,
  353. packet.Header.Sequence);
  354. }
  355. return;
  356. }
  357. }
  358. }
  359. // When the timer elapses, send the pending acks, trigger resends
  360. // and report all the stats.
  361. //
  362. private void AckTimerElapsed(object sender, ElapsedEventArgs ea)
  363. {
  364. SendAcks();
  365. ResendUnacked();
  366. SendPacketStats();
  367. }
  368. // Push out pachet counts for the sim status reporter
  369. //
  370. private void SendPacketStats()
  371. {
  372. PacketStats handlerPacketStats = OnPacketStats;
  373. if (handlerPacketStats != null)
  374. {
  375. handlerPacketStats(
  376. m_PacketsReceived - m_PacketsReceivedReported,
  377. m_PacketsSent - m_PacketsSentReported,
  378. m_UnackedBytes);
  379. m_PacketsReceivedReported = m_PacketsReceived;
  380. m_PacketsSentReported = m_PacketsSent;
  381. }
  382. }
  383. // We can't keep an unlimited record of dupes. This will prune the
  384. // dictionary by age.
  385. //
  386. // NOTE: this needs to be called from within lock
  387. // (m_alreadySeenTracker) context!
  388. private void ExpireSeenPackets()
  389. {
  390. if (m_alreadySeenList.Count < 1024)
  391. return;
  392. int ticks = 0;
  393. int tc = Environment.TickCount & Int32.MaxValue;
  394. if (tc >= m_lastAlreadySeenCheck)
  395. ticks = tc - m_lastAlreadySeenCheck;
  396. else
  397. ticks = Int32.MaxValue - m_lastAlreadySeenCheck + tc;
  398. if (ticks < 2000) return;
  399. m_lastAlreadySeenCheck = tc;
  400. // we calculate the drop dead tick count here instead of
  401. // in the loop: any packet with a timestamp before
  402. // dropDeadTC can be expired
  403. int dropDeadTC = tc - m_alreadySeenWindow;
  404. int i = 0;
  405. while (i < m_alreadySeenList.Count && m_alreadySeenTracker[m_alreadySeenList[i]] < dropDeadTC)
  406. {
  407. m_alreadySeenTracker.Remove(m_alreadySeenList[i]);
  408. i++;
  409. }
  410. // if we dropped packet from m_alreadySeenTracker we need
  411. // to drop them from m_alreadySeenList as well, let's do
  412. // that in one go: the list is ordered after all.
  413. if (i > 0)
  414. {
  415. m_alreadySeenList.RemoveRange(0, i);
  416. // m_log.DebugFormat("[CLIENT]: expired {0} packets, {1}:{2} left", i, m_alreadySeenList.Count, m_alreadySeenTracker.Count);
  417. }
  418. }
  419. public void InPacket(Packet packet)
  420. {
  421. if (packet == null)
  422. return;
  423. // When too many acks are needed to be sent, the client sends
  424. // a packet consisting of acks only
  425. //
  426. if (packet.Type == PacketType.PacketAck)
  427. {
  428. PacketAckPacket ackPacket = (PacketAckPacket)packet;
  429. foreach (PacketAckPacket.PacketsBlock block in ackPacket.Packets)
  430. {
  431. ProcessAck(block.ID);
  432. }
  433. PacketPool.Instance.ReturnPacket(packet);
  434. return;
  435. }
  436. // Any packet can have some packet acks in the header.
  437. // Process them here
  438. //
  439. if (packet.Header.AppendedAcks)
  440. {
  441. foreach (uint id in packet.Header.AckList)
  442. {
  443. ProcessAck(id);
  444. }
  445. }
  446. // If this client is on another partial instance, no need
  447. // to handle packets
  448. //
  449. if (!m_Client.IsActive && packet.Type != PacketType.LogoutRequest)
  450. {
  451. PacketPool.Instance.ReturnPacket(packet);
  452. return;
  453. }
  454. if (packet.Type == PacketType.StartPingCheck)
  455. {
  456. StartPingCheckPacket startPing = (StartPingCheckPacket)packet;
  457. CompletePingCheckPacket endPing
  458. = (CompletePingCheckPacket)PacketPool.Instance.GetPacket(PacketType.CompletePingCheck);
  459. endPing.PingID.PingID = startPing.PingID.PingID;
  460. OutPacket(endPing, ThrottleOutPacketType.Task);
  461. }
  462. else
  463. {
  464. LLQueItem item = new LLQueItem();
  465. item.Packet = packet;
  466. item.Incoming = true;
  467. m_PacketQueue.Enqueue(item);
  468. }
  469. }
  470. public void ProcessInPacket(LLQueItem item)
  471. {
  472. Packet packet = item.Packet;
  473. // Always ack the packet!
  474. //
  475. if (packet.Header.Reliable)
  476. AckPacket(packet);
  477. if (packet.Type != PacketType.AgentUpdate)
  478. m_PacketsReceived++;
  479. // Check for duplicate packets.. packets that the client is
  480. // resending because it didn't receive our ack
  481. //
  482. lock (m_alreadySeenTracker)
  483. {
  484. ExpireSeenPackets();
  485. if (m_alreadySeenTracker.ContainsKey(packet.Header.Sequence))
  486. return;
  487. m_alreadySeenTracker.Add(packet.Header.Sequence, Environment.TickCount & Int32.MaxValue);
  488. m_alreadySeenList.Add(packet.Header.Sequence);
  489. }
  490. m_Client.ProcessInPacket(packet);
  491. }
  492. public void Flush()
  493. {
  494. m_PacketQueue.Flush();
  495. m_UnackedBytes = (-1 * m_UnackedBytes);
  496. SendPacketStats();
  497. }
  498. public void Clear()
  499. {
  500. m_UnackedBytes = (-1 * m_UnackedBytes);
  501. SendPacketStats();
  502. lock (m_NeedAck)
  503. {
  504. m_NeedAck.Clear();
  505. m_PendingAcks.Clear();
  506. m_PendingAcksMap.Clear();
  507. }
  508. m_Sequence += 1000000;
  509. }
  510. private void ProcessAck(uint id)
  511. {
  512. LLQueItem data;
  513. lock (m_NeedAck)
  514. {
  515. //m_log.DebugFormat("[CLIENT]: In {0} received ack for packet {1}", m_Client.Scene.RegionInfo.ExternalEndPoint.Port, id);
  516. if (!m_NeedAck.TryGetValue(id, out data))
  517. return;
  518. m_NeedAck.Remove(id);
  519. m_PacketQueue.Cancel(data.Sequence);
  520. PacketPool.Instance.ReturnPacket(data.Packet);
  521. m_UnackedBytes -= data.Length;
  522. }
  523. }
  524. // Allocate packet sequence numbers in a threadsave manner
  525. //
  526. protected uint NextPacketSequenceNumber()
  527. {
  528. // Set the sequence number
  529. uint seq = 1;
  530. lock (m_SequenceLock)
  531. {
  532. if (m_Sequence >= MAX_SEQUENCE)
  533. {
  534. m_Sequence = 1;
  535. }
  536. else
  537. {
  538. m_Sequence++;
  539. }
  540. seq = m_Sequence;
  541. }
  542. return seq;
  543. }
  544. public ClientInfo GetClientInfo()
  545. {
  546. ClientInfo info = new ClientInfo();
  547. info.pendingAcks = m_PendingAcksMap;
  548. info.needAck = new Dictionary<uint, byte[]>();
  549. lock (m_NeedAck)
  550. {
  551. foreach (uint key in m_NeedAck.Keys)
  552. info.needAck.Add(key, m_NeedAck[key].Packet.ToBytes());
  553. }
  554. LLQueItem[] queitems = m_PacketQueue.GetQueueArray();
  555. for (int i = 0; i < queitems.Length; i++)
  556. {
  557. if (queitems[i].Incoming == false)
  558. info.out_packets.Add(queitems[i].Packet.ToBytes());
  559. }
  560. info.sequence = m_Sequence;
  561. float multiplier = m_PacketQueue.ThrottleMultiplier;
  562. info.resendThrottle = (int) (m_PacketQueue.ResendThrottle.Throttle / multiplier);
  563. info.landThrottle = (int) (m_PacketQueue.LandThrottle.Throttle / multiplier);
  564. info.windThrottle = (int) (m_PacketQueue.WindThrottle.Throttle / multiplier);
  565. info.cloudThrottle = (int) (m_PacketQueue.CloudThrottle.Throttle / multiplier);
  566. info.taskThrottle = (int) (m_PacketQueue.TaskThrottle.Throttle / multiplier);
  567. info.assetThrottle = (int) (m_PacketQueue.AssetThrottle.Throttle / multiplier);
  568. info.textureThrottle = (int) (m_PacketQueue.TextureThrottle.Throttle / multiplier);
  569. info.totalThrottle = (int) (m_PacketQueue.TotalThrottle.Throttle / multiplier);
  570. return info;
  571. }
  572. public void SetClientInfo(ClientInfo info)
  573. {
  574. m_PendingAcksMap = info.pendingAcks;
  575. m_PendingAcks = new List<uint>(m_PendingAcksMap.Keys);
  576. m_NeedAck = new Dictionary<uint, LLQueItem>();
  577. Packet packet = null;
  578. int packetEnd = 0;
  579. byte[] zero = new byte[3000];
  580. foreach (uint key in info.needAck.Keys)
  581. {
  582. byte[] buff = info.needAck[key];
  583. packetEnd = buff.Length - 1;
  584. try
  585. {
  586. packet = PacketPool.Instance.GetPacket(buff, ref packetEnd, zero);
  587. }
  588. catch (Exception)
  589. {
  590. }
  591. LLQueItem item = new LLQueItem();
  592. item.Packet = packet;
  593. item.Incoming = false;
  594. item.throttleType = 0;
  595. item.TickCount = Environment.TickCount;
  596. item.Identifier = 0;
  597. item.Resends = 0;
  598. item.Length = packet.Length;
  599. item.Sequence = packet.Header.Sequence;
  600. m_NeedAck.Add(key, item);
  601. }
  602. m_Sequence = info.sequence;
  603. m_PacketQueue.ResendThrottle.Throttle = info.resendThrottle;
  604. m_PacketQueue.LandThrottle.Throttle = info.landThrottle;
  605. m_PacketQueue.WindThrottle.Throttle = info.windThrottle;
  606. m_PacketQueue.CloudThrottle.Throttle = info.cloudThrottle;
  607. m_PacketQueue.TaskThrottle.Throttle = info.taskThrottle;
  608. m_PacketQueue.AssetThrottle.Throttle = info.assetThrottle;
  609. m_PacketQueue.TextureThrottle.Throttle = info.textureThrottle;
  610. m_PacketQueue.TotalThrottle.Throttle = info.totalThrottle;
  611. }
  612. public void AddImportantPacket(PacketType type)
  613. {
  614. if (m_ImportantPackets.Contains(type))
  615. return;
  616. m_ImportantPackets.Add(type);
  617. }
  618. public void RemoveImportantPacket(PacketType type)
  619. {
  620. if (!m_ImportantPackets.Contains(type))
  621. return;
  622. m_ImportantPackets.Remove(type);
  623. }
  624. private void DropResend(Object id)
  625. {
  626. LLQueItem d = null;
  627. foreach (LLQueItem data in m_NeedAck.Values)
  628. {
  629. if (data.Identifier != null && data.Identifier == id)
  630. {
  631. d = data;
  632. break;
  633. }
  634. }
  635. if (null == d) return;
  636. m_NeedAck.Remove(d.Packet.Header.Sequence);
  637. m_PacketQueue.Cancel(d.Sequence);
  638. PacketPool.Instance.ReturnPacket(d.Packet);
  639. }
  640. private void TriggerOnPacketDrop(Packet packet, Object id)
  641. {
  642. PacketDrop handlerPacketDrop = OnPacketDrop;
  643. if (handlerPacketDrop == null)
  644. return;
  645. handlerPacketDrop(packet, id);
  646. }
  647. // Convert the packet to bytes and stuff it onto the send queue
  648. //
  649. public void ProcessOutPacket(LLQueItem item)
  650. {
  651. Packet packet = item.Packet;
  652. // Assign sequence number here to prevent out of order packets
  653. if (packet.Header.Sequence == 0)
  654. {
  655. lock (m_NeedAck)
  656. {
  657. packet.Header.Sequence = NextPacketSequenceNumber();
  658. item.Sequence = packet.Header.Sequence;
  659. item.TickCount = Environment.TickCount;
  660. // We want to see that packet arrive if it's reliable
  661. if (packet.Header.Reliable)
  662. {
  663. m_UnackedBytes += item.Length;
  664. // Keep track of when this packet was sent out
  665. item.TickCount = Environment.TickCount;
  666. m_NeedAck[packet.Header.Sequence] = item;
  667. }
  668. }
  669. }
  670. // If we sent a killpacket
  671. if (packet is KillPacket)
  672. Abort();
  673. try
  674. {
  675. // If this packet has been reused/returned, the ToBytes
  676. // will blow up in our face.
  677. // Fail gracefully.
  678. //
  679. // Actually make the byte array and send it
  680. byte[] sendbuffer = item.Packet.ToBytes();
  681. if (packet.Header.Zerocoded)
  682. {
  683. int packetsize = Helpers.ZeroEncode(sendbuffer,
  684. sendbuffer.Length, m_ZeroOutBuffer);
  685. m_PacketServer.SendPacketTo(m_ZeroOutBuffer, packetsize,
  686. SocketFlags.None, m_Client.CircuitCode);
  687. }
  688. else
  689. {
  690. // Need some extra space in case we need to add proxy
  691. // information to the message later
  692. Buffer.BlockCopy(sendbuffer, 0, m_ZeroOutBuffer, 0,
  693. sendbuffer.Length);
  694. m_PacketServer.SendPacketTo(m_ZeroOutBuffer,
  695. sendbuffer.Length, SocketFlags.None, m_Client.CircuitCode);
  696. }
  697. }
  698. catch (NullReferenceException n)
  699. {
  700. m_log.Debug("[PACKET] Detected reuse of a returned packet");
  701. m_PacketQueue.Cancel(item.Sequence);
  702. return;
  703. }
  704. // If this is a reliable packet, we are still holding a ref
  705. // Dont't return in that case
  706. //
  707. if (!packet.Header.Reliable)
  708. {
  709. m_PacketQueue.Cancel(item.Sequence);
  710. PacketPool.Instance.ReturnPacket(packet);
  711. }
  712. }
  713. private void Abort()
  714. {
  715. m_PacketQueue.Close();
  716. Thread.CurrentThread.Abort();
  717. }
  718. }
  719. }