using System; using System.Collections.Generic; using System.Net; namespace OpenMetaverse { // this class encapsulates a single packet that // is either sent or received by a UDP socket public class UDPPacketBuffer { /// Size of the byte array used to store raw packet data public const int DEFAULT_BUFFER_SIZE = 4096; /// Raw packet data buffer public readonly byte[] Data; /// Length of the data to transmit public int DataLength; /// EndPoint of the remote host public EndPoint RemoteEndPoint; /// /// Was the buffer leased from a pool? /// public bool BytesLeasedFromPool; /// /// Create an allocated UDP packet buffer for receiving a packet /// public UDPPacketBuffer() { Data = new byte[DEFAULT_BUFFER_SIZE]; // Will be modified later by BeginReceiveFrom() RemoteEndPoint = new IPEndPoint(Settings.BIND_ADDR, 0); } /// /// Create an allocated UDP packet buffer for sending a packet /// /// EndPoint of the remote host public UDPPacketBuffer(IPEndPoint endPoint) { Data = new byte[DEFAULT_BUFFER_SIZE]; RemoteEndPoint = endPoint; } /// /// Create an allocated UDP packet buffer for sending a packet /// /// EndPoint of the remote host /// Size of the buffer to allocate for packet data public UDPPacketBuffer(IPEndPoint endPoint, int bufferSize) { Data = new byte[bufferSize]; RemoteEndPoint = endPoint; } /// /// Create an allocated UDP packet buffer for sending a packet /// public UDPPacketBuffer(byte[] buffer, int bufferSize, IPEndPoint destination, int category, bool fromBufferPool) { Data = new byte[bufferSize]; this.CopyFrom(buffer, bufferSize); DataLength = bufferSize; RemoteEndPoint = destination; BytesLeasedFromPool = fromBufferPool; } /// /// Create an allocated UDP packet buffer for sending a packet /// /// EndPoint of the remote host /// The actual buffer to use for packet data (no allocation). public UDPPacketBuffer(IPEndPoint endPoint, byte[] data) { Data = data; RemoteEndPoint = endPoint; } public void CopyFrom(Array src, int length) { Buffer.BlockCopy(src, 0, this.Data, 0, length); } public void CopyFrom(Array src) { this.CopyFrom(src, src.Length); } public void ResetEndpoint() { RemoteEndPoint = new IPEndPoint(Settings.BIND_ADDR, 0); } } /// /// Object pool for packet buffers. This is used to allocate memory for all /// incoming and outgoing packets, and zerocoding buffers for those packets /// public class PacketBufferPool : ObjectPoolBase { private IPEndPoint _endPoint; /// /// Initialize the object pool in client mode /// /// Server to connect to /// /// public PacketBufferPool(IPEndPoint endPoint, int itemsPerSegment, int minSegments) { _endPoint = endPoint; Initialize(itemsPerSegment, minSegments, true, 1000 * 60 * 5); } /// /// Initialize the object pool in server mode /// /// /// public PacketBufferPool(int itemsPerSegment, int minSegments) { _endPoint = null; Initialize(itemsPerSegment, minSegments, true, 1000 * 60 * 5); } /// /// Returns a packet buffer with EndPoint set if the buffer is in /// client mode, or with EndPoint set to null in server mode /// /// Initialized UDPPacketBuffer object protected override UDPPacketBuffer GetObjectInstance() { return _endPoint != null ? new UDPPacketBuffer(_endPoint) : new UDPPacketBuffer(); } } public static class Pool { public static PacketBufferPool PoolInstance; /// /// Default constructor /// static Pool() { PoolInstance = new PacketBufferPool(new IPEndPoint(Settings.BIND_ADDR, 0), 16, 1); } /// /// Check a packet buffer out of the pool /// /// A packet buffer object public static WrappedObject CheckOut() { return PoolInstance.CheckOut(); } } }