// Convert the packet to bytes and stuff it onto the send queue // public void ProcessOutPacket(LLQueItem item) { Packet packet = item.Packet; // Assign sequence number here to prevent out of order packets if (packet.Header.Sequence == 0) { lock (m_NeedAck) { packet.Header.Sequence = NextPacketSequenceNumber(); item.Sequence = packet.Header.Sequence; item.TickCount = Environment.TickCount; // We want to see that packet arrive if it's reliable if (packet.Header.Reliable) { m_UnackedBytes += item.Length; // Keep track of when this packet was sent out item.TickCount = Environment.TickCount; m_NeedAck[packet.Header.Sequence] = item; } } } // If we sent a killpacket if (packet is KillPacket) { Abort(); } try { // If this packet has been reused/returned, the ToBytes // will blow up in our face. // Fail gracefully. // // Actually make the byte array and send it byte[] sendbuffer = item.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); } } catch (NullReferenceException) { m_log.Debug("[PACKET] Detected reuse of a returned packet"); m_PacketQueue.Cancel(item.Sequence); return; } // If this is a reliable packet, we are still holding a ref // Dont't return in that case // if (!packet.Header.Reliable) { m_PacketQueue.Cancel(item.Sequence); PacketPool.Instance.ReturnPacket(packet); } }