diff --git a/OpenMetaverse/NetworkManager.cs b/OpenMetaverse/NetworkManager.cs
index 35ef7115..04ab1688 100644
--- a/OpenMetaverse/NetworkManager.cs
+++ b/OpenMetaverse/NetworkManager.cs
@@ -101,12 +101,33 @@ namespace OpenMetaverse
public Packet Packet;
/// True if the sequence number needs to be set, otherwise false
public bool SetSequence;
+ /// 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;
public OutgoingPacket(Simulator simulator, Packet packet, bool setSequence)
{
Simulator = simulator;
Packet = packet;
SetSequence = setSequence;
+ ResendCount = 0;
+ TickCount = 0;
+ }
+
+ public void IncrementResendCount()
+ {
+ ++ResendCount;
+ }
+
+ public void SetTickCount()
+ {
+ TickCount = Environment.TickCount;
+ }
+
+ public void ZeroTickCount()
+ {
+ TickCount = 0;
}
}
diff --git a/OpenMetaverse/ParcelManager.cs b/OpenMetaverse/ParcelManager.cs
index 8d6a86f2..c5e4cfcd 100644
--- a/OpenMetaverse/ParcelManager.cs
+++ b/OpenMetaverse/ParcelManager.cs
@@ -918,13 +918,11 @@ namespace OpenMetaverse
(y + 1) * 4.0f, (x + 1) * 4.0f,
y * 4.0f, x * 4.0f, int.MaxValue, false);
- // Wait a reasonable amount of time for a reply before sending the next request
+ // Wait the given amount of time for a reply before sending the next request
if (!WaitForSimParcel.WaitOne(msDelay, false))
- {
- Logger.Log("Timeout Waiting for ParcelProperties Response, try increasing the delay between requests", Helpers.LogLevel.Debug, Client);
- timeouts++;
- }
- count++;
+ ++timeouts;
+
+ ++count;
}
}
}
diff --git a/OpenMetaverse/Simulator.cs b/OpenMetaverse/Simulator.cs
index f5750f90..8638f32d 100644
--- a/OpenMetaverse/Simulator.cs
+++ b/OpenMetaverse/Simulator.cs
@@ -391,7 +391,7 @@ namespace OpenMetaverse
/// (for duplicate checking)
internal Queue PacketArchive;
/// Packets we sent out that need ACKs from the simulator
- internal Dictionary NeedAck = new Dictionary();
+ internal Dictionary NeedAck = new Dictionary();
private NetworkManager Network;
private Queue InBytes, OutBytes;
@@ -608,9 +608,7 @@ namespace OpenMetaverse
byte[] buffer;
int bytes;
- // Keep track of when this packet was sent out
- packet.TickCount = Environment.TickCount;
-
+ // Set sequence implies that this is not a resent packet
if (setSequence)
{
// Reset to zero if we've hit the upper sequence number limit
@@ -620,10 +618,15 @@ namespace OpenMetaverse
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] = packet;
+ NeedAck[packet.Header.Sequence] = outgoing;
}
if (packet.Header.Resent)
@@ -649,6 +652,9 @@ namespace OpenMetaverse
packet.Header.AppendedAcks = false;
packet.Header.AckList = new uint[0];
}
+
+ // Update the sent time for this packet
+ SetResentTime(packet.Header.Sequence);
}
else
{
@@ -890,6 +896,13 @@ namespace OpenMetaverse
{
}
+ private void SetResentTime(uint sequence)
+ {
+ NetworkManager.OutgoingPacket outgoing;
+ if (NeedAck.TryGetValue(sequence, out outgoing))
+ outgoing.SetTickCount();
+ }
+
///
/// Sends out pending acknowledgements
///
@@ -933,26 +946,26 @@ namespace OpenMetaverse
int now = Environment.TickCount;
// Resend packets
- foreach (Packet packet in NeedAck.Values)
+ foreach (NetworkManager.OutgoingPacket outgoing in NeedAck.Values)
{
- if (packet.TickCount != 0 && now - packet.TickCount > Client.Settings.RESEND_TIMEOUT)
+ if (outgoing.TickCount != 0 && now - outgoing.TickCount > Client.Settings.RESEND_TIMEOUT)
{
- if (packet.ResendCount < Client.Settings.MAX_RESEND_COUNT)
+ if (outgoing.ResendCount < Client.Settings.MAX_RESEND_COUNT)
{
try
{
if (Client.Settings.LOG_RESENDS)
{
Logger.DebugLog(String.Format("Resending packet #{0} ({1}), {2}ms have passed",
- packet.Header.Sequence, packet.GetType(), now - packet.TickCount), Client);
+ outgoing.Packet.Header.Sequence, outgoing.Packet.GetType(), now - outgoing.TickCount), Client);
}
- packet.TickCount = 0;
- packet.Header.Resent = true;
+ outgoing.ZeroTickCount();
+ outgoing.Packet.Header.Resent = true;
++Stats.ResentPackets;
- ++packet.ResendCount;
+ outgoing.IncrementResendCount();
- SendPacket(packet, false);
+ SendPacket(outgoing.Packet, false);
}
catch (Exception ex)
{
@@ -964,10 +977,10 @@ namespace OpenMetaverse
if (Client.Settings.LOG_RESENDS)
{
Logger.DebugLog(String.Format("Dropping packet #{0} ({1}) after {2} failed attempts",
- packet.Header.Sequence, packet.GetType(), packet.ResendCount));
+ outgoing.Packet.Header.Sequence, outgoing.Packet.GetType(), outgoing.ResendCount));
}
- dropAck.Add(packet.Header.Sequence);
+ dropAck.Add(outgoing.Packet.Header.Sequence);
}
}
}
diff --git a/OpenMetaverse/_Packets_.cs b/OpenMetaverse/_Packets_.cs
index 6852f9e8..ed6ac4d2 100644
--- a/OpenMetaverse/_Packets_.cs
+++ b/OpenMetaverse/_Packets_.cs
@@ -781,9 +781,6 @@ namespace OpenMetaverse.Packets
public abstract PacketType Type { get; }
public abstract void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer);
public abstract void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer);
- public int ResendCount;
- public int TickCount;
-
public abstract byte[] ToBytes();
public static PacketType GetType(ushort id, PacketFrequency frequency)
{
diff --git a/Programs/Simian/Extensions/UDPServer.cs b/Programs/Simian/Extensions/UDPServer.cs
index eeac1961..f9ac4e5b 100644
--- a/Programs/Simian/Extensions/UDPServer.cs
+++ b/Programs/Simian/Extensions/UDPServer.cs
@@ -8,6 +8,45 @@ using OpenMetaverse.Packets;
namespace Simian
{
+ public struct IncomingPacket
+ {
+ public UDPClient Client;
+ public Packet Packet;
+ }
+
+ public struct OutgoingPacket
+ {
+ public UDPClient Client;
+ public Packet Packet;
+ /// 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;
+
+ public OutgoingPacket(UDPClient client, Packet packet)
+ {
+ Client = client;
+ Packet = packet;
+ ResendCount = 0;
+ TickCount = 0;
+ }
+
+ public void IncrementResendCount()
+ {
+ ++ResendCount;
+ }
+
+ public void SetTickCount()
+ {
+ TickCount = Environment.TickCount;
+ }
+
+ public void ZeroTickCount()
+ {
+ TickCount = 0;
+ }
+ }
+
public class UDPClient
{
///
@@ -17,7 +56,7 @@ namespace Simian
/// Sequence numbers of packets we've received (for duplicate checking)
public Queue PacketArchive = new Queue();
/// Packets we have sent that need to be ACKed by the client
- public Dictionary NeedAcks = new Dictionary();
+ public Dictionary NeedAcks = new Dictionary();
/// ACKs that are queued up, waiting to be sent to the client
public SortedList PendingAcks = new SortedList();
/// Current packet sequence number
@@ -47,12 +86,6 @@ namespace Simian
}
}
- public struct IncomingPacket
- {
- public UDPClient Client;
- public Packet Packet;
- }
-
public class UDPManager : ISimianExtension, IUDPProvider
{
Simian Server;
@@ -184,9 +217,7 @@ namespace Simian
byte[] buffer;
int bytes;
- // Keep track of when this packet was sent out
- packet.TickCount = Environment.TickCount;
-
+ // Set sequence implies that this is not a resent packet
if (setSequence)
{
// Reset to zero if we've hit the upper sequence number limit
@@ -197,9 +228,14 @@ namespace Simian
if (packet.Header.Reliable)
{
+ // Wrap this packet in a struct to track timeouts and resends
+ OutgoingPacket outgoing = new OutgoingPacket(null, packet);
+ // Keep track of when this packet was sent out (right now)
+ outgoing.TickCount = Environment.TickCount;
+
// Add this packet to the list of ACK responses we are waiting on from this client
lock (client.NeedAcks)
- client.NeedAcks[sequence] = packet;
+ client.NeedAcks[sequence] = outgoing;
if (packet.Header.Resent)
{
@@ -224,6 +260,9 @@ namespace Simian
packet.Header.AppendedAcks = false;
packet.Header.AckList = new uint[0];
}
+
+ // Update the sent time for this packet
+ SetResentTime(client, packet.Header.Sequence);
}
else
{
@@ -340,6 +379,13 @@ namespace Simian
SendPacket(client, acks, PacketCategory.Overhead, true);
}
+ void SetResentTime(UDPClient client, uint sequence)
+ {
+ OutgoingPacket outgoing;
+ if (client.NeedAcks.TryGetValue(sequence, out outgoing))
+ outgoing.SetTickCount();
+ }
+
public void ResendUnacked(UDPClient client)
{
lock (client.NeedAcks)
@@ -348,28 +394,28 @@ namespace Simian
int now = Environment.TickCount;
// Resend packets
- foreach (Packet packet in client.NeedAcks.Values)
+ foreach (OutgoingPacket outgoing in client.NeedAcks.Values)
{
- if (packet.TickCount != 0 && now - packet.TickCount > 4000)
+ if (outgoing.TickCount != 0 && now - outgoing.TickCount > 4000)
{
- if (packet.ResendCount < 3)
+ if (outgoing.ResendCount < 3)
{
Logger.DebugLog(String.Format("Resending packet #{0} ({1}), {2}ms have passed",
- packet.Header.Sequence, packet.GetType(), now - packet.TickCount));
+ outgoing.Packet.Header.Sequence, outgoing.Packet.GetType(), now - outgoing.TickCount));
- packet.TickCount = 0;
- packet.Header.Resent = true;
+ outgoing.ZeroTickCount();
+ outgoing.Packet.Header.Resent = true;
//++Stats.ResentPackets;
- ++packet.ResendCount;
+ outgoing.IncrementResendCount();
- SendPacket(client, packet, PacketCategory.Overhead, false);
+ SendPacket(client, outgoing.Packet, PacketCategory.Overhead, false);
}
else
{
Logger.Log(String.Format("Dropping packet #{0} ({1}) after {2} failed attempts",
- packet.Header.Sequence, packet.GetType(), packet.ResendCount), Helpers.LogLevel.Warning);
+ outgoing.Packet.Header.Sequence, outgoing.Packet.GetType(), outgoing.ResendCount), Helpers.LogLevel.Warning);
- dropAck.Add(packet.Header.Sequence);
+ dropAck.Add(outgoing.Packet.Header.Sequence);
//Disconnect an agent if no packets are received for some time
//TODO: Send logout packet? Also, 10000 should be a setting somewhere.
diff --git a/Programs/mapgenerator/mapgenerator.cs b/Programs/mapgenerator/mapgenerator.cs
index f53bb565..685c7909 100644
--- a/Programs/mapgenerator/mapgenerator.cs
+++ b/Programs/mapgenerator/mapgenerator.cs
@@ -813,20 +813,6 @@ namespace mapgenerator
writer.WriteLine(" " + packet.Name + " = " + (0x30000 | packet.ID) + ",");
writer.WriteLine(" }" + Environment.NewLine);
-
- // Write all of the XmlInclude statements for the Packet class to allow packet serialization
- //writer.WriteLine("#if PACKETSERIALIZE");
- //foreach (MapPacket packet in protocol.LowMaps)
- // if (packet != null)
- // writer.WriteLine(" [XmlInclude(typeof(" + packet.Name + "Packet))]");
- //foreach (MapPacket packet in protocol.MediumMaps)
- // if (packet != null)
- // writer.WriteLine(" [XmlInclude(typeof(" + packet.Name + "Packet))]");
- //foreach (MapPacket packet in protocol.HighMaps)
- // if (packet != null)
- // writer.WriteLine(" [XmlInclude(typeof(" + packet.Name + "Packet))]");
- //writer.WriteLine("#endif");
-
// Write the base Packet class
writer.WriteLine(
" public abstract partial class Packet" + Environment.NewLine + " {" + Environment.NewLine +
@@ -834,14 +820,7 @@ namespace mapgenerator
" public abstract PacketType Type { get; }" + Environment.NewLine +
" public abstract void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer);" + Environment.NewLine +
" public abstract void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer);" + Environment.NewLine +
- " public int ResendCount;" + Environment.NewLine +
- " public int TickCount;" + Environment.NewLine + Environment.NewLine +
- " public abstract byte[] ToBytes();" //+ Environment.NewLine + Environment.NewLine +
- //" public void ToXml(XmlWriter xmlWriter)" + Environment.NewLine +
- //" {" + Environment.NewLine +
- //" XmlSerializer serializer = new XmlSerializer(typeof(Packet));" + Environment.NewLine +
- //" serializer.Serialize(xmlWriter, this);" + Environment.NewLine +
- //" }");
+ " public abstract byte[] ToBytes();"
);
@@ -875,31 +854,6 @@ namespace mapgenerator
" break;" + Environment.NewLine + " }" + Environment.NewLine + Environment.NewLine +
" return PacketType.Default;" + Environment.NewLine + " }" + Environment.NewLine);
- // TODO: Not sure if this function is useful to anyone, but if it is it needs to be
- // rewritten to not overwrite passed in pointers and decode the entire packet just
- // to read the header
-
- // Write the Packet.GetType() function
- //writer.WriteLine(
- // " public static PacketType GetType(byte[] bytes, int packetEnd, byte[] zeroBuffer)" + Environment.NewLine +
- // " {" + Environment.NewLine + " ushort id; PacketFrequency freq;" + Environment.NewLine +
- // " int i = 0, end = packetEnd;" + Environment.NewLine +
- // " Header header = Header.BuildHeader(bytes, ref i, ref end);" + Environment.NewLine +
- // " if (header.Zerocoded)" + Environment.NewLine + " {" + Environment.NewLine +
- // " end = Helpers.ZeroDecode(bytes, end + 1, zeroBuffer) - 1;" + Environment.NewLine +
- // " bytes = zeroBuffer;" + Environment.NewLine + " }" + Environment.NewLine + Environment.NewLine +
- // " if (bytes[6] == 0xFF)" + Environment.NewLine + " {" + Environment.NewLine +
- // " if (bytes[7] == 0xFF)" + Environment.NewLine + " {" + Environment.NewLine +
- // " id = (ushort)((bytes[8] << 8) + bytes[9]); freq = PacketFrequency.Low;" + Environment.NewLine +
- // " }" + Environment.NewLine +
- // " else" + Environment.NewLine +
- // " {" + Environment.NewLine + " id = (ushort)bytes[7]; freq = PacketFrequency.Medium;" +
- // Environment.NewLine + " }" + Environment.NewLine + " }" + Environment.NewLine +
- // " else" + Environment.NewLine + " {" + Environment.NewLine +
- // " id = (ushort)bytes[6]; freq = PacketFrequency.High;" + Environment.NewLine +
- // " }" + Environment.NewLine +
- // " return GetType(id, freq);" + Environment.NewLine +
- // " }" + Environment.NewLine);
// Write the Packet.BuildPacket(PacketType) function
writer.WriteLine(" public static Packet BuildPacket(PacketType type)");