diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index ec945cd55a..a1e270bf85 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -392,7 +392,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // in it to process. It's an on-purpose threadlock though because // without it, the clientloop will suck up all sim resources. - m_PacketHandler = new LLPacketHandler(this); + m_PacketHandler = new LLPacketHandler(this, m_networkServer); m_PacketHandler.SynchronizeClient = SynchronizeClient; RegisterLocalPacketHandlers(); @@ -616,12 +616,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (nextPacket.Incoming) { DebugPacket("IN", nextPacket.Packet); - m_PacketHandler.ProcessInPacket(nextPacket.Packet); + m_PacketHandler.ProcessInPacket(nextPacket); } else { DebugPacket("OUT", nextPacket.Packet); - ProcessOutPacket(nextPacket.Packet); + m_PacketHandler.ProcessOutPacket(nextPacket); } } } @@ -745,7 +745,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP + "Any further actions taken will not be processed.\n" + "Please relog", true); - ProcessOutPacket(packet); + LLQueItem item = new LLQueItem(); + item.Packet = packet; + + m_PacketHandler.ProcessOutPacket(item); // There may be a better way to do this. Perhaps kick? Not sure this propogates notifications to // listeners yet, though. @@ -3685,47 +3688,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_PacketHandler.PacketQueue.SetThrottleFromClient(throttles); } - // Previously ClientView.m_packetQueue - - /// - /// Helper routine to prepare the packet for sending to UDP client - /// This converts it to bytes and puts it on the outgoing buffer - /// - /// - protected virtual void ProcessOutPacket(Packet Pack) - { - // Keep track of when this packet was sent out - Pack.TickCount = System.Environment.TickCount; - - // Actually make the byte array and send it - try - { - byte[] sendbuffer = Pack.ToBytes(); - PacketPool.Instance.ReturnPacket(Pack); - - if (Pack.Header.Zerocoded) - { - int packetsize = Helpers.ZeroEncode(sendbuffer, sendbuffer.Length, ZeroOutBuffer); - m_networkServer.SendPacketTo(ZeroOutBuffer, packetsize, SocketFlags.None, m_circuitCode); - } - else - { - //Need some extra space in case we need to add proxy information to the message later - Buffer.BlockCopy(sendbuffer, 0, ZeroOutBuffer, 0, sendbuffer.Length); - m_networkServer.SendPacketTo(ZeroOutBuffer, sendbuffer.Length, SocketFlags.None, m_circuitCode); - } - } - catch (Exception e) - { - m_log.Warn("[client]: " + - "ClientView.m_packetQueue.cs:ProcessOutPacket() - WARNING: Socket exception occurred on connection " + - m_userEndPoint.ToString() + " - killing thread"); - m_log.Error(e.ToString()); - Close(true); - } - } - - /// /// method gets called when a new packet has arrived from the UDP server. This happens after it's been decoded into a libsl object /// /// diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs b/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs index b035150723..51448f2333 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs @@ -31,10 +31,13 @@ using System.Collections.Generic; using System.Net; using System.Net.Sockets; using System.Timers; +using System.Reflection; using libsecondlife; using libsecondlife.Packets; using Timer = System.Timers.Timer; using OpenSim.Framework; +using OpenSim.Region.ClientStack.LindenUDP; +using log4net; namespace OpenSim.Region.ClientStack.LindenUDP { @@ -55,7 +58,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP uint ResendTimeout { get; set; } void InPacket(Packet packet); - void ProcessInPacket(Packet packet); + void ProcessInPacket(LLQueItem item); + void ProcessOutPacket(LLQueItem item); void OutPacket(Packet NewPack, ThrottleOutPacketType throttlePacketType); void OutPacket(Packet NewPack, @@ -72,6 +76,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP public class LLPacketHandler : IPacketHandler { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + // Packet queues // LLPacketQueue m_PacketQueue; @@ -181,13 +188,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP List m_ImportantPackets = new List(); + LLPacketServer m_PacketServer; + private byte[] m_ZeroOutBuffer = new byte[4096]; + //////////////////////////////////////////////////////////////////// // Constructors // - public LLPacketHandler(IClientAPI client) + public LLPacketHandler(IClientAPI client, LLPacketServer server) { m_Client = client; + m_PacketServer = server; m_PacketQueue = new LLPacketQueue(client.AgentId); @@ -228,21 +239,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP return; } - packet.Header.Sequence = NextPacketSequenceNumber(); - lock (m_NeedAck) { DropResend(id); AddAcks(ref packet); QueuePacket(packet, throttlePacketType, id); - - // We want to see that packet arrive if it's reliable - if (packet.Header.Reliable) - { - m_UnackedBytes += packet.ToBytes().Length; - m_NeedAck[packet.Header.Sequence] = new AckData(packet, id); - } } } @@ -531,8 +533,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } - public void ProcessInPacket(Packet packet) + public void ProcessInPacket(LLQueItem item) { + Packet packet = item.Packet; + // Always ack the packet! // if (packet.Header.Reliable) @@ -698,5 +702,62 @@ namespace OpenSim.Region.ClientStack.LindenUDP handlerPacketDrop(packet, id); } + + // Convert the packet to bytes and stuff it onto the send queue + // + public void ProcessOutPacket(LLQueItem item) + { + Packet packet = item.Packet; + + // Keep track of when this packet was sent out + packet.TickCount = System.Environment.TickCount; + + // Assign sequence number here to prevent out of order packets + packet.Header.Sequence = NextPacketSequenceNumber(); + + lock(m_NeedAck) + { + // We want to see that packet arrive if it's reliable + if (packet.Header.Reliable) + { + m_UnackedBytes += packet.ToBytes().Length; + m_NeedAck[packet.Header.Sequence] = new AckData(packet, + item.Identifier); + } + } + + // Actually make the byte array and send it + try + { + byte[] sendbuffer = packet.ToBytes(); + + if (packet.Header.Zerocoded) + { + int packetsize = Helpers.ZeroEncode(sendbuffer, + sendbuffer.Length, m_ZeroOutBuffer); + m_PacketServer.SendPacketTo(m_ZeroOutBuffer, packetsize, + SocketFlags.None, m_Client.CircuitCode); + } + else + { + // Need some extra space in case we need to add proxy + // information to the message later + Buffer.BlockCopy(sendbuffer, 0, m_ZeroOutBuffer, 0, + sendbuffer.Length); + m_PacketServer.SendPacketTo(m_ZeroOutBuffer, + sendbuffer.Length, SocketFlags.None, m_Client.CircuitCode); + } + + PacketPool.Instance.ReturnPacket(packet); + } + catch (Exception e) + { + m_log.Warn("[client]: " + + "PacketHandler:ProcessOutPacket() - WARNING: Socket "+ + "exception occurred - killing thread"); + m_log.Error(e.ToString()); + m_Client.Close(true); + } + } } }