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();
}
}
}