LLPacketHandler.cs 26 KB

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