diff --git a/OpenMetaverse/NetworkManager.cs b/OpenMetaverse/NetworkManager.cs
index fb4531b3..87907f79 100644
--- a/OpenMetaverse/NetworkManager.cs
+++ b/OpenMetaverse/NetworkManager.cs
@@ -82,33 +82,6 @@ namespace OpenMetaverse
}
}
- ///
- /// Holds a simulator reference and a serialized packet, these structs are put in
- /// the packet outbox for sending
- ///
- public class OutgoingPacket
- {
- /// Reference to the simulator this packet is destined for
- public readonly Simulator Simulator;
- /// Packet that needs to be sent
- public readonly UDPPacketBuffer Buffer;
- /// Sequence number of the wrapped packet
- public uint SequenceNumber;
- /// Number of times this packet has been resent
- public int ResendCount;
- /// Environment.TickCount when this packet was last sent over the wire
- public int TickCount;
- /// Type of the packet
- public PacketType Type;
-
- public OutgoingPacket(Simulator simulator, UDPPacketBuffer buffer, PacketType type)
- {
- Simulator = simulator;
- Buffer = buffer;
- this.Type = type;
- }
- }
-
#endregion Structs
#region Delegates
diff --git a/OpenMetaverse/ObjectPool.cs b/OpenMetaverse/ObjectPool.cs
index b69799b3..75a42679 100644
--- a/OpenMetaverse/ObjectPool.cs
+++ b/OpenMetaverse/ObjectPool.cs
@@ -9,7 +9,7 @@ namespace OpenMetaverse
public class UDPPacketBuffer
{
/// Size of the byte array used to store raw packet data
- public const int BufferSize = 4096;
+ public const int DEFAULT_BUFFER_SIZE = 4096;
/// Raw packet data buffer
public readonly byte[] Data;
/// Length of the data to transmit
@@ -26,7 +26,7 @@ namespace OpenMetaverse
///
public UDPPacketBuffer()
{
- Data = new byte[BufferSize];
+ Data = new byte[DEFAULT_BUFFER_SIZE];
// Will be modified later by BeginReceiveFrom()
RemoteEndPoint = new IPEndPoint(Settings.BIND_ADDR, 0);
}
@@ -37,7 +37,7 @@ namespace OpenMetaverse
/// EndPoint of the remote host
public UDPPacketBuffer(IPEndPoint endPoint)
{
- Data = new byte[BufferSize];
+ Data = new byte[DEFAULT_BUFFER_SIZE];
RemoteEndPoint = endPoint;
}
@@ -52,6 +52,40 @@ namespace OpenMetaverse
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);
diff --git a/OpenMetaverse/OutgoingPacket.cs b/OpenMetaverse/OutgoingPacket.cs
new file mode 100644
index 00000000..19192e53
--- /dev/null
+++ b/OpenMetaverse/OutgoingPacket.cs
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSimulator Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using OpenMetaverse;
+using System.Net;
+using OpenMetaverse.Packets;
+
+namespace OpenMetaverse
+{
+ ///
+ /// Holds a simulator client reference and a serialized packet,
+ /// along with some network statistics and related info.
+ ///
+ public sealed class OutgoingPacket
+ {
+ /// Reference to the simulator this packet is destined for
+ public readonly object Client;
+ /// Packet that needs to be sent
+ public readonly UDPPacketBuffer Buffer;
+ /// Sequence number of the wrapped packet
+ public uint SequenceNumber;
+ /// Number of times this packet has been resent
+ public int ResendCount;
+ /// Environment.TickCount when this packet was last sent over the wire
+ public int TickCount;
+ /// Type of the packet
+ public PacketType Type;
+ ///
+ /// This is a caller-managed field representing the number of bytes to use/used in Buffer
+ ///
+ public int DataSize;
+
+ ///
+ /// Reference count to be used on this packet to know when it's safe to return to the pool
+ ///
+ private int _refCount;
+ ///
+ /// Lock to protect the reference count
+ ///
+ private object _refCountLock = new object();
+
+ /// Category this packet belongs to
+ public int Category;
+
+ private bool _fromPool = false;
+ public bool BufferFromPool
+ {
+ get { return _fromPool; }
+ }
+
+ public OutgoingPacket(Simulator simulator, UDPPacketBuffer buffer, PacketType type)
+ {
+ Client = simulator;
+ Buffer = buffer;
+ this.Type = type;
+ }
+
+ public Simulator Simulator
+ {
+ get { return Client is Simulator ? Client as Simulator : null; }
+ }
+
+ ///
+ /// The endpoint this data is headed for
+ ///
+ public IPEndPoint Destination
+ {
+ get { return Buffer.RemoteEndPoint is IPEndPoint ? Buffer.RemoteEndPoint as IPEndPoint : null; }
+ }
+
+ ///
+ /// Default constructor
+ ///
+ public OutgoingPacket(object client, byte[] buffer, int category, int dataSize, IPEndPoint destination,
+ bool fromBufferPool, Packets.PacketType type)
+ {
+ SequenceNumber = 0;
+ ResendCount = 0;
+ TickCount = 0;
+
+ Client = client;
+ Category = category;
+ _fromPool = fromBufferPool;
+ Type = type;
+ DataSize = dataSize;
+ Buffer = new UDPPacketBuffer(buffer, dataSize, destination, category, fromBufferPool);
+ }
+
+ public void AddRef()
+ {
+ if (BufferFromPool)
+ {
+ lock (_refCountLock)
+ {
+ ++_refCount;
+ }
+ }
+ }
+
+ public void DecRef(Interfaces.IByteBufferPool returnPool)
+ {
+ if (BufferFromPool)
+ {
+ bool returnToBuffer = false;
+ lock (_refCountLock)
+ {
+ if (--_refCount <= 0)
+ {
+ returnToBuffer = true;
+ }
+ }
+
+ if (returnToBuffer)
+ {
+ Array data = Buffer.Data;
+ returnPool.ReturnBytes(Buffer.Data);
+ }
+ }
+ }
+ }
+}
diff --git a/OpenMetaverse/Simulator.cs b/OpenMetaverse/Simulator.cs
index e5b1950f..4923c624 100644
--- a/OpenMetaverse/Simulator.cs
+++ b/OpenMetaverse/Simulator.cs
@@ -478,7 +478,7 @@ namespace OpenMetaverse
/// (for duplicate checking)
internal IncomingPacketIDCollection PacketArchive;
/// Packets we sent out that need ACKs from the simulator
- internal SortedDictionary NeedAck = new SortedDictionary();
+ internal SortedDictionary NeedAck = new SortedDictionary();
/// Sequence number for pause/resume
internal int pauseSerial;
/// Indicates if UDP connection to the sim is fully established
@@ -730,7 +730,7 @@ namespace OpenMetaverse
CloseCircuitPacket close = new CloseCircuitPacket();
UDPPacketBuffer buf = new UDPPacketBuffer(remoteEndPoint);
byte[] data = close.ToBytes();
- Buffer.BlockCopy(data, 0, buf.Data, 0, data.Length);
+ buf.CopyFrom(data);
buf.DataLength = data.Length;
AsyncBeginSend(buf);
@@ -867,18 +867,18 @@ namespace OpenMetaverse
// Remove the MSG_ZEROCODED flag and send the unencoded data
// instead
data[0] = (byte)(data[0] & ~Helpers.MSG_ZEROCODED);
- Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
+ buffer.CopyFrom(data, dataLength);
}
}
else
{
- Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
+ buffer.CopyFrom(data, dataLength);
}
buffer.DataLength = dataLength;
#region Queue or Send
- NetworkManager.OutgoingPacket outgoingPacket = new NetworkManager.OutgoingPacket(this, buffer, type);
+ OutgoingPacket outgoingPacket = new OutgoingPacket(this, buffer, type);
// Send ACK and logout packets directly, everything else goes through the queue
if (Client.Settings.THROTTLE_OUTGOING_PACKETS == false ||
@@ -902,7 +902,7 @@ namespace OpenMetaverse
#endregion
}
- internal void SendPacketFinal(NetworkManager.OutgoingPacket outgoingPacket)
+ internal void SendPacketFinal(OutgoingPacket outgoingPacket)
{
UDPPacketBuffer buffer = outgoingPacket.Buffer;
byte flags = buffer.Data[0];
@@ -1235,19 +1235,19 @@ namespace OpenMetaverse
{
if (NeedAck.Count <= 0) return;
- NetworkManager.OutgoingPacket[] array;
+ OutgoingPacket[] array;
lock (NeedAck)
{
// Create a temporary copy of the outgoing packets array to iterate over
- array = new NetworkManager.OutgoingPacket[NeedAck.Count];
+ array = new OutgoingPacket[NeedAck.Count];
NeedAck.Values.CopyTo(array, 0);
}
int now = Environment.TickCount;
// Resend packets
- foreach (NetworkManager.OutgoingPacket outgoing in array)
+ foreach (OutgoingPacket outgoing in array)
{
if (outgoing.TickCount == 0 || now - outgoing.TickCount <= Client.Settings.RESEND_TIMEOUT) continue;
diff --git a/OpenMetaverse/UDPBase.cs b/OpenMetaverse/UDPBase.cs
index 2ac82620..146c50c0 100644
--- a/OpenMetaverse/UDPBase.cs
+++ b/OpenMetaverse/UDPBase.cs
@@ -149,7 +149,7 @@ namespace OpenMetaverse
//wrappedBuffer.Instance.Data,
buf.Data,
0,
- UDPPacketBuffer.BufferSize,
+ UDPPacketBuffer.DEFAULT_BUFFER_SIZE,
SocketFlags.None,
ref buf.RemoteEndPoint,
AsyncEndReceive,
@@ -170,7 +170,7 @@ namespace OpenMetaverse
//wrappedBuffer.Instance.Data,
buf.Data,
0,
- UDPPacketBuffer.BufferSize,
+ UDPPacketBuffer.DEFAULT_BUFFER_SIZE,
SocketFlags.None,
ref buf.RemoteEndPoint,
AsyncEndReceive,