Exemplo n.º 1
0
        /// <summary>
        /// Turn a packet into an array of bytes. If necessary zerocde it. The returned array will be the correct length.
        /// </summary>
        /// <param name="packet">The packet to encode</param>
        protected byte[] GetBytes(OpenMetaverse.Packets.Packet packet)
        {
            byte[] bytes  = packet.ToBytes();
            int    length = bytes.Length;

            if (packet.Header.Zerocoded)
            {
                byte[] zerod = new byte[8192];
                length = Helpers.ZeroEncode(bytes, bytes.Length, zerod);
                bytes  = zerod.Take(length).ToArray();
            }
            return(bytes);
        }
Exemplo n.º 2
0
        public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents, bool allowSplitting)
        {
            // CoarseLocationUpdate and AvatarGroupsReply packets cannot be split in an automated way
            if ((packet.Type == PacketType.CoarseLocationUpdate || packet.Type == PacketType.AvatarGroupsReply) && allowSplitting)
                allowSplitting = false;

            if (allowSplitting && packet.HasVariableBlocks)
            {
                byte[][] datas = packet.ToBytesMultiple();
                int packetCount = datas.Length;

                if (packetCount < 1)
                    m_log.Error("[LLUDPSERVER]: Failed to split " + packet.Type + " with estimated length " + packet.Length);

                for (int i = 0; i < packetCount; i++)
                {
                    byte[] data = datas[i];
                    m_scene.ForEachClient(
                        delegate(IClientAPI client)
                        {
                            if (client is LLClientView)
                                SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null);
                        }
                    );
                }
            }
            else
            {
                byte[] data = packet.ToBytes();
                m_scene.ForEachClient(
                    delegate(IClientAPI client)
                    {
                        if (client is LLClientView)
                            SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null);
                    }
                );
            }
        }
Exemplo n.º 3
0
            // Inject: inject a packet
            public void Inject(Packet packet, Direction direction)
            {
                if (direction == Direction.Incoming)
                {
                    if (firstReceive)
                    {
                        proxy.queuedIncomingInjections.Add(packet);
                        return;
                    }

                    incomingInjections.Add(++incomingSequence);
                    packet.Header.Sequence = incomingSequence;
                }
                else
                {
                    outgoingInjections.Add(++outgoingSequence);
                    packet.Header.Sequence = outgoingSequence;
                }

                if (packet.Header.Reliable)
                    WaitForAck(packet, direction);

                if (direction == Direction.Incoming)
                {
                    byte[] buffer = packet.ToBytes();
                    if (!packet.Header.Zerocoded)
                        socket.SendTo(buffer, buffer.Length, SocketFlags.None, clientEndPoint);
                    else
                    {
                        int zeroLength = Helpers.ZeroEncode(buffer, buffer.Length, zeroBuffer);
                        socket.SendTo(zeroBuffer, zeroLength, SocketFlags.None, clientEndPoint);
                    }
                }
                else
                    proxy.SendPacket(packet, remoteEndPoint, false);
            }
Exemplo n.º 4
0
 // SendPacket: send a packet from the sim to the client via our fake sim endpoint
 public void SendPacket(Packet packet, bool skipZero)
 {
     byte[] buffer = packet.ToBytes();
     if (skipZero || !packet.Header.Zerocoded)
         socket.SendTo(buffer, buffer.Length, SocketFlags.None, clientEndPoint);
     else
     {
         int zeroLength = Helpers.ZeroEncode(buffer, buffer.Length, zeroBuffer);
         socket.SendTo(zeroBuffer, zeroLength, SocketFlags.None, clientEndPoint);
     }
 }
Exemplo n.º 5
0
        /// <summary>
        /// Sends a packet directly to the simulator without queuing
        /// </summary>
        /// <param name="packet">Packet to be sent</param>
        /// <param name="setSequence">True to set the sequence number, false to
        /// leave it as is</param>
        public void SendPacketUnqueued(Packet packet, bool setSequence)
        {
            byte[] buffer;
            int bytes;

            // Set sequence implies that this is not a resent packet
            if (setSequence)
            {
                // Reset to zero if we've hit the upper sequence number limit
                Interlocked.CompareExchange(ref Sequence, 0, Settings.MAX_SEQUENCE);
                // Increment and fetch the current sequence number
                packet.Header.Sequence = (uint)Interlocked.Increment(ref Sequence);

                if (packet.Header.Reliable)
                {
                    // Wrap this packet in a struct to track timeouts and resends
                    NetworkManager.OutgoingPacket outgoing = new NetworkManager.OutgoingPacket(this, packet, true);
                    // Keep track of when this packet was first sent out (right now)
                    outgoing.TickCount = Environment.TickCount;

                    // Add this packet to the list of ACK responses we are waiting on from the server
                    lock (NeedAck)
                    {
                        NeedAck[packet.Header.Sequence] = outgoing;
                    }

                    if (packet.Header.Resent)
                    {
                        // This packet has already been sent out once, strip any appended ACKs
                        // off it and reinsert them into the outgoing ACK queue under the
                        // assumption that this packet will continually be rejected from the
                        // server or that the appended ACKs are possibly making the delivery fail
                        if (packet.Header.AckList.Length > 0)
                        {
                            Logger.DebugLog(String.Format("Purging ACKs from packet #{0} ({1}) which will be resent.",
                                packet.Header.Sequence, packet.GetType()));

                            lock (PendingAcks)
                            {
                                foreach (uint sequence in packet.Header.AckList)
                                {
                                    if (!PendingAcks.ContainsKey(sequence))
                                        PendingAcks[sequence] = sequence;
                                }
                            }

                            packet.Header.AppendedAcks = false;
                            packet.Header.AckList = new uint[0];
                        }

                        // Update the sent time for this packet
                        SetResentTime(packet.Header.Sequence);
                    }
                    else
                    {
                        // This packet is not a resend, check if the conditions are favorable
                        // to ACK appending
                        if (packet.Type != PacketType.PacketAck &&
                            packet.Type != PacketType.LogoutRequest)
                        {
                            lock (PendingAcks)
                            {
                                if (PendingAcks.Count > 0 &&
                                    PendingAcks.Count < Client.Settings.MAX_APPENDED_ACKS)
                                {
                                    // Append all of the queued up outgoing ACKs to this packet
                                    packet.Header.AckList = new uint[PendingAcks.Count];

                                    for (int i = 0; i < PendingAcks.Count; i++)
                                        packet.Header.AckList[i] = PendingAcks.Values[i];

                                    PendingAcks.Clear();
                                    packet.Header.AppendedAcks = true;
                                }
                            }
                        }
                    }
                }
                else if (packet.Header.AckList.Length > 0)
                {
                    // Sanity check for ACKS appended on an unreliable packet, this is bad form
                    Logger.Log("Sending appended ACKs on an unreliable packet", Helpers.LogLevel.Warning);
                }
            }

            // Serialize the packet
            buffer = packet.ToBytes();
            bytes = buffer.Length;
            Stats.SentBytes += (ulong)bytes;
            ++Stats.SentPackets;

            UDPPacketBuffer buf = new UDPPacketBuffer(ipEndPoint);

            // Zerocode if needed
            if (packet.Header.Zerocoded)
                bytes = Helpers.ZeroEncode(buffer, bytes, buf.Data);
            else
                Buffer.BlockCopy(buffer, 0, buf.Data, 0, bytes);

            buf.DataLength = bytes;

            AsyncBeginSend(buf);
        }
Exemplo n.º 6
0
            // Inject: inject a packet
            public void Inject(Packet packet, Direction direction)
            {
                if (direction == Direction.Incoming)
                {
                    if (firstReceive)
                    {
                        proxy.queuedIncomingInjections.Add(packet);
                        return;
                    }

                    incomingInjections.Add(++incomingSequence);
                    packet.Header.Sequence = incomingSequence;
                }
                else
                {
                    outgoingInjections.Add(++outgoingSequence);
                    packet.Header.Sequence = outgoingSequence;
                }

#if DEBUG_SEQUENCE
				Console.WriteLine("INJECT " + (direction == Direction.Incoming ? "<-" : "->") + " " + packet.Type + " #" + packet.Header.Sequence);

#endif
                if ((packet.Header.Data[0] & Helpers.MSG_RELIABLE) != 0)
                    WaitForAck(packet, direction);

                if (direction == Direction.Incoming)
                {
                    byte[] buffer = packet.ToBytes();
                    if ((packet.Header.Data[0] & Helpers.MSG_ZEROCODED) == 0)
                        socket.SendTo(buffer, buffer.Length, SocketFlags.None, clientEndPoint);
                    else
                    {
                        int zeroLength = Helpers.ZeroEncode(buffer, buffer.Length, zeroBuffer);
                        socket.SendTo(zeroBuffer, zeroLength, SocketFlags.None, clientEndPoint);
                    }
                }
                else
                    proxy.SendPacket(packet, remoteEndPoint, false);
            }
Exemplo n.º 7
0
        // SendPacket: send a packet to a sim from our fake client endpoint
        public void SendPacket(Packet packet, IPEndPoint endPoint, bool skipZero)
        {
            byte[] buffer = packet.ToBytes();
            if (skipZero || (packet.Header.Data[0] & Helpers.MSG_ZEROCODED) == 0)
                simFacingSocket.SendTo(buffer, buffer.Length, SocketFlags.None, endPoint);
            else
            {
                int zeroLength = Helpers.ZeroEncode(buffer, buffer.Length, zeroBuffer);
                simFacingSocket.SendTo(zeroBuffer, zeroLength, SocketFlags.None, endPoint);
            }

        }
Exemplo n.º 8
0
        public void SendPacket(LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting)
        {
            // CoarseLocationUpdate packets cannot be split in an automated way
            if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting)
                allowSplitting = false;

            if (allowSplitting && packet.HasVariableBlocks)
            {
                byte[][] datas = packet.ToBytesMultiple();
                int packetCount = datas.Length;

                //if (packetCount > 1)
                //    m_log.Debug("[LLUDPSERVER]: Split " + packet.Type + " packet into " + packetCount + " packets");

                for (int i = 0; i < packetCount; i++)
                {
                    byte[] data = datas[i];
                    SendPacketData(udpClient, data, packet.Type, category);
                }
            }
            else
            {
                byte[] data = packet.ToBytes();
                SendPacketData(udpClient, data, packet.Type, category);
            }
        }
Exemplo n.º 9
0
        public void SendPacket(LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting,
            UnackedPacketMethod resendMethod, UnackedPacketMethod finishedMethod)
        {
            // CoarseLocationUpdate packets cannot be split in an automated way
            if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting)
                allowSplitting = false;

            if (allowSplitting && packet.HasVariableBlocks)
            {
                byte[][] datas = packet.ToBytesMultiple();
                int packetCount = datas.Length;

                if (packetCount < 1)
                    MainConsole.Instance.Error("[LLUDPSERVER]: Failed to split " + packet.Type +
                                               " with estimated length " +
                                               packet.Length);

                for (int i = 0; i < packetCount; i++)
                {
                    byte[] data = datas[i];
                    SendPacketData(udpClient, data, packet, category, resendMethod, finishedMethod);
                    data = null;
                }
                datas = null;
            }
            else
            {
                byte[] data = packet.ToBytes();
                SendPacketData(udpClient, data, packet, category, resendMethod, finishedMethod);
                data = null;
            }
            packet = null;
        }
Exemplo n.º 10
0
        public void SendPacket(LLAgent agent, Packet packet, ThrottleCategory category, bool allowSplitting)
        {
            // CoarseLocationUpdate and AvatarGroupsReply packets cannot be split in an automated way
            if ((packet.Type == PacketType.CoarseLocationUpdate || packet.Type == PacketType.AvatarGroupsReply) && allowSplitting)
                allowSplitting = false;

            try
            {
                if (allowSplitting && packet.HasVariableBlocks)
                {
                    byte[][] datas = packet.ToBytesMultiple();
                    int packetCount = datas.Length;

                    if (packetCount < 1)
                        m_log.Error("[LLUDPSERVER]: Failed to split " + packet.Type + " with estimated length " + packet.Length);

                    for (int i = 0; i < packetCount; i++)
                    {
                        byte[] data = datas[i];
                        SendPacketData(agent, data, packet.Type, category);
                    }
                }
                else
                {
                    byte[] data = packet.ToBytes();
                    SendPacketData(agent, data, packet.Type, category);
                }
            }
            catch (NullReferenceException)
            {
                System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(1, true);
                m_log.Error("An invalid " + packet.Type + " packet was built in:" + Environment.NewLine + trace.ToString());
            }
        }
Exemplo n.º 11
0
        public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents, bool allowSplitting)
        {
            // CoarseLocationUpdate packets cannot be split in an automated way
            if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting)
                allowSplitting = false;

            if (allowSplitting && packet.HasVariableBlocks)
            {
                byte[][] datas = packet.ToBytesMultiple();
                int packetCount = datas.Length;

                //if (packetCount > 1)
                //    m_log.Debug("[LLUDPSERVER]: Split " + packet.Type + " packet into " + packetCount + " packets");

                for (int i = 0; i < packetCount; i++)
                {
                    byte[] data = datas[i];
                    m_scene.ForEachClient(
                        delegate(IClientAPI client)
                        {
                            if (client is LLClientView)
                                SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category);
                        }
                    );
                }
            }
            else
            {
                byte[] data = packet.ToBytes();
                m_scene.ForEachClient(
                    delegate(IClientAPI client)
                    {
                        if (client is LLClientView)
                            SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category);
                    }
                );
            }
        }
Exemplo n.º 12
0
 /// <summary>
 /// Load a packet to be received by the LLUDPServer on the next receive call
 /// </summary>
 /// <param name="packet"></param>
 public void LoadReceive(Packet packet, EndPoint epSender)
 {
     LoadReceive(packet.ToBytes(), epSender);
 }
Exemplo n.º 13
0
        public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents,
                                    bool allowSplitting, UnackedPacketMethod resendMethod,
                                    UnackedPacketMethod finishedMethod)
        {
            // CoarseLocationUpdate and AvatarGroupsReply packets cannot be split in an automated way
            if ((packet.Type == PacketType.CoarseLocationUpdate || packet.Type == PacketType.AvatarGroupsReply) &&
                allowSplitting)
                allowSplitting = false;

            if (allowSplitting && packet.HasVariableBlocks)
            {
                byte[][] datas = packet.ToBytesMultiple();
                int packetCount = datas.Length;

                if (packetCount < 1)
                    MainConsole.Instance.Error("[LLUDP Server]: Failed to split " + packet.Type +
                                               " with estimated length " + packet.Length);

                for (int i = 0; i < packetCount; i++)
                {
                    byte[] data = datas[i];
                    ForEachInternalClient(
                        delegate(IClientAPI client)
                            {
                                if (client is LLClientView)
                                    SendPacketData(((LLClientView) client).UDPClient, data, packet, category,
                                                   resendMethod, finishedMethod);
                            }
                        );
                }
            }
            else
            {
                byte[] data = packet.ToBytes();
                ForEachInternalClient(
                    delegate(IClientAPI client)
                        {
                            if (client is LLClientView)
                                SendPacketData(((LLClientView) client).UDPClient, data, packet, category, resendMethod,
                                               finishedMethod);
                        }
                    );
            }
        }
Exemplo n.º 14
0
        public void SendPacket(LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting)
        {
            // CoarseLocationUpdate packets cannot be split in an automated way
            if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting)
                allowSplitting = false;

            if (allowSplitting && packet.HasVariableBlocks)
            {
                byte[][] datas;
                int[] sizes;

                if (packet.UsesBufferPooling)
                {
                    datas = packet.ToBytesMultiple(_bufferPool, out sizes);
                }
                else
                {
                    datas = packet.ToBytesMultiple();
                    sizes = new int[datas.Length];

                    for (int i = 0; i < datas.Length; i++)
                    {
                        sizes[i] = datas[i].Length;
                    }
                }

                //add up all the sizes of the data going out for this packet. if it is more than MAX_PACKET_SIZE
                //drop it and log it
                long totalSz = 0;
                foreach (int size in sizes)
                {
                    totalSz += size;
                }

                if (totalSz > MAX_PACKET_SIZE)
                {
                    m_log.ErrorFormat("[LLUDPSERVER] Not sending HUGE packet Type:{0}, Size: {1}", packet.Type, totalSz);
                    datas = null;
                    return;
                }

                int packetCount = datas.Length;

                if (packetCount < 1)
                    m_log.Error("[LLUDPSERVER]: Failed to split " + packet.Type + " with estimated length " + packet.Length);

                for (int i = 0; i < packetCount; i++)
                {
                    byte[] data = datas[i];
                    SendPacketData(udpClient, data, sizes[i], packet.Type, category, packet.UsesBufferPooling);
                }
            }
            else
            {
                byte[] data;
                int size = 0;
                
                if (packet.UsesBufferPooling)
                {
                    data = packet.ToBytes(_bufferPool, ref size);
                }
                else
                {
                    data = packet.ToBytes();
                    size = data.Length;
                }

                if (size > MAX_PACKET_SIZE)
                {
                    m_log.ErrorFormat("[LLUDPSERVER] Not sending HUGE packet Type:{0}, Size: {1}", packet.Type, size);
                    data = null;
                    return;
                }

                SendPacketData(udpClient, data, size, packet.Type, category, packet.UsesBufferPooling);
            }
        }
Exemplo n.º 15
0
        /// <summary>
        /// Start the process of sending a packet to the client.
        /// </summary>
        /// <param name="udpClient"></param>
        /// <param name="packet"></param>
        /// <param name="category"></param>
        /// <param name="allowSplitting"></param>
        /// <param name="method">
        /// The method to call if the packet is not acked by the client.  If null, then a standard
        /// resend of the packet is done.
        /// </param>
        public virtual void SendPacket(
            LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting, UnackedPacketMethod method)
        {
            // CoarseLocationUpdate packets cannot be split in an automated way
            if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting)
                allowSplitting = false;

            if (allowSplitting && packet.HasVariableBlocks)
            {
                byte[][] datas = packet.ToBytesMultiple();
                int packetCount = datas.Length;

                if (packetCount < 1)
                    m_log.Error("[LLUDPSERVER]: Failed to split " + packet.Type + " with estimated length " + packet.Length);

                for (int i = 0; i < packetCount; i++)
                {
                    byte[] data = datas[i];
                    SendPacketData(udpClient, data, packet.Type, category, method);
                }
            }
            else
            {
                byte[] data = packet.ToBytes();
                SendPacketData(udpClient, data, packet.Type, category, method);
            }

            PacketPool.Instance.ReturnPacket(packet);

            m_dataPresentEvent.Set();
        }
Exemplo n.º 16
0
        /// <summary>
        /// Sends a packet
        /// </summary>
        /// <param name="packet">Packet to be sent</param>
        public void SendPacket(Packet packet)
        {
            // DEBUG: This can go away after we are sure nothing in the library is trying to do this
            if (packet.Header.AppendedAcks || (packet.Header.AckList != null && packet.Header.AckList.Length > 0))
                Logger.Log("Attempting to send packet " + packet.Type + " with ACKs appended before serialization", Helpers.LogLevel.Error);

            if (packet.HasVariableBlocks)
            {
                byte[][] datas = packet.ToBytesMultiple();
                int packetCount = datas.Length;

                if (packetCount > 1)
                    Logger.DebugLog("Split " + packet.Type + " packet into " + packetCount + " packets");

                for (int i = 0; i < packetCount; i++)
                {
                    byte[] data = datas[i];
                    SendPacketData(data, data.Length, packet.Type, packet.Header.Zerocoded);
                }
            }
            else
            {
                byte[] data = packet.ToBytes();
                SendPacketData(data, data.Length, packet.Type, packet.Header.Zerocoded);
            }
        }
Exemplo n.º 17
0
        /// <summary>
        /// Sends a packet
        /// </summary>
        /// <param name="packet">Packet to be sent</param>
        public void SendPacket(Packet packet)
        {
            // DEBUG: This can go away after we are sure nothing in the library is trying to do this
            if (packet.Header.AppendedAcks || (packet.Header.AckList != null && packet.Header.AckList.Length > 0))
                Logger.Log("Attempting to send packet " + packet.Type + " with ACKs appended before serialization", Helpers.LogLevel.Error);

            if (packet.HasVariableBlocks)
            {
                byte[][] datas;
                try { datas = packet.ToBytesMultiple(); }
                catch (NullReferenceException)
                {
                    Logger.Log("Failed to serialize " + packet.Type + " packet to one or more payloads due to a missing block or field. StackTrace: " +
                        Environment.StackTrace, Helpers.LogLevel.Error);
                    return;
                }
                int packetCount = datas.Length;

                if (packetCount > 1)
                    Logger.DebugLog("Split " + packet.Type + " packet into " + packetCount + " packets");

                for (int i = 0; i < packetCount; i++)
                {
                    byte[] data = datas[i];
                    SendPacketData(data, data.Length, packet.Type, packet.Header.Zerocoded);
                }
            }
            else
            {
                byte[] data = packet.ToBytes();
                SendPacketData(data, data.Length, packet.Type, packet.Header.Zerocoded);
            }
        }
Exemplo n.º 18
0
        public void SendPacket(Packet packet, bool setSequence)
        {
            byte[] buffer;
            int bytes;

            // Keep track of when this packet was sent out
            packet.TickCount = Environment.TickCount;

            if (setSequence)
            {
                // Reset to zero if we've hit the upper sequence number limit
                Interlocked.CompareExchange(ref currentSequence, 0, 0xFFFFFF);
                // Increment and fetch the current sequence number
                uint sequence = (uint)Interlocked.Increment(ref currentSequence);
                packet.Header.Sequence = sequence;

                if (packet.Header.Reliable)
                {
                    // Add this packet to the list of ACK responses we are waiting on from the client
                    lock (needAcks)
                        needAcks[sequence] = packet;

                    if (packet.Header.Resent)
                    {
                        // This packet has already been sent out once, strip any appended ACKs
                        // off it and reinsert them into the outgoing ACK queue under the 
                        // assumption that this packet will continually be rejected from the
                        // client or that the appended ACKs are possibly making the delivery fail
                        if (packet.Header.AckList.Length > 0)
                        {
                            Logger.DebugLog(String.Format("Purging ACKs from packet #{0} ({1}) which will be resent.",
                                packet.Header.Sequence, packet.GetType()));

                            lock (pendingAcks)
                            {
                                foreach (uint ack in packet.Header.AckList)
                                {
                                    if (!pendingAcks.ContainsKey(ack))
                                        pendingAcks[ack] = ack;
                                }
                            }

                            packet.Header.AppendedAcks = false;
                            packet.Header.AckList = new uint[0];
                        }
                    }
                    else
                    {
                        // This packet is not a resend, check if the conditions are favorable
                        // to ACK appending
                        if (packet.Type != PacketType.PacketAck)
                        {
                            lock (pendingAcks)
                            {
                                if (pendingAcks.Count > 0 &&
                                    pendingAcks.Count < 10)
                                {
                                    // Append all of the queued up outgoing ACKs to this packet
                                    packet.Header.AckList = new uint[pendingAcks.Count];

                                    for (int i = 0; i < pendingAcks.Count; i++)
                                        packet.Header.AckList[i] = pendingAcks.Values[i];

                                    pendingAcks.Clear();
                                    packet.Header.AppendedAcks = true;
                                }
                            }
                        }
                    }
                }
                else if (packet.Header.AckList.Length > 0)
                {
                    // Sanity check for ACKS appended on an unreliable packet, this is bad form
                    Logger.Log("Sending appended ACKs on an unreliable packet", Helpers.LogLevel.Warning);
                }
            }

            // Serialize the packet
            buffer = packet.ToBytes();
            bytes = buffer.Length;
            //Stats.SentBytes += (ulong)bytes;
            //++Stats.SentPackets;

            UDPPacketBuffer buf;

            // Zerocode if needed
            if (packet.Header.Zerocoded)
            {
                buf = new UDPPacketBuffer(address, true, false);

                bytes = Helpers.ZeroEncode(buffer, bytes, buf.Data);
                buf.DataLength = bytes;
            }
            else
            {
                buf = new UDPPacketBuffer(address, false, false);

                buf.Data = buffer;
                buf.DataLength = bytes;
            }

            udpServer.AsyncBeginSend(buf);
        }