diff --git a/OpenMetaverse/Simulator.cs b/OpenMetaverse/Simulator.cs
index a0757fbb..0aea3894 100644
--- a/OpenMetaverse/Simulator.cs
+++ b/OpenMetaverse/Simulator.cs
@@ -360,7 +360,7 @@ namespace OpenMetaverse
#region Properties
/// The IP address and port of the server
- public IPEndPoint IPEndPoint { get { return ipEndPoint; } }
+ public IPEndPoint IPEndPoint { get { return remoteEndPoint; } }
/// Whether there is a working connection to the simulator or
/// not
public bool Connected { get { return connected; } }
@@ -400,7 +400,6 @@ namespace OpenMetaverse
private Queue InBytes, OutBytes;
// ACKs that are queued up to be sent to the simulator
private SortedList PendingAcks = new SortedList();
- private IPEndPoint ipEndPoint;
private Timer AckTimer;
private Timer PingTimer;
private Timer StatsTimer;
@@ -421,7 +420,6 @@ namespace OpenMetaverse
{
Client = client;
- ipEndPoint = address;
Handle = handle;
Estate = new EstateTools(Client);
Network = Client.Network;
@@ -563,7 +561,7 @@ namespace OpenMetaverse
{
// Try to send the CloseCircuit notice
CloseCircuitPacket close = new CloseCircuitPacket();
- UDPPacketBuffer buf = new UDPPacketBuffer(ipEndPoint);
+ UDPPacketBuffer buf = new UDPPacketBuffer(remoteEndPoint);
byte[] data = close.ToBytes();
Buffer.BlockCopy(data, 0, buf.Data, 0, data.Length);
buf.DataLength = data.Length;
@@ -659,31 +657,7 @@ namespace OpenMetaverse
// Add this packet to the list of ACK responses we are waiting on from the server
lock (NeedAck) NeedAck[packet.Header.Sequence] = outgoingPacket;
- 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];
- }
- }
- else
+ if (!packet.Header.Resent)
{
// This packet is not a resend, check if the conditions are favorable
// to ACK appending
@@ -715,13 +689,38 @@ namespace OpenMetaverse
}
}
+ 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];
+ }
+ }
+
// Serialize the packet
buffer = packet.ToBytes();
bytes = buffer.Length;
Stats.SentBytes += (ulong)bytes;
++Stats.SentPackets;
- UDPPacketBuffer buf = new UDPPacketBuffer(ipEndPoint);
+ UDPPacketBuffer buf = new UDPPacketBuffer(remoteEndPoint);
// Zerocode if needed
if (packet.Header.Zerocoded)
@@ -756,7 +755,7 @@ namespace OpenMetaverse
Stats.SentBytes += (ulong)payload.Length;
++Stats.SentPackets;
- UDPPacketBuffer buf = new UDPPacketBuffer(ipEndPoint);
+ UDPPacketBuffer buf = new UDPPacketBuffer(remoteEndPoint);
Buffer.BlockCopy(payload, 0, buf.Data, 0, payload.Length);
buf.DataLength = payload.Length;
@@ -813,9 +812,9 @@ namespace OpenMetaverse
public override string ToString()
{
if (!String.IsNullOrEmpty(Name))
- return String.Format("{0} ({1})", Name, ipEndPoint);
+ return String.Format("{0} ({1})", Name, remoteEndPoint);
else
- return String.Format("({0})", ipEndPoint);
+ return String.Format("({0})", remoteEndPoint);
}
///
@@ -837,7 +836,7 @@ namespace OpenMetaverse
Simulator sim = obj as Simulator;
if (sim == null)
return false;
- return (ipEndPoint.Equals(sim.ipEndPoint));
+ return (remoteEndPoint.Equals(sim.remoteEndPoint));
}
public static bool operator ==(Simulator lhs, Simulator rhs)
@@ -854,7 +853,7 @@ namespace OpenMetaverse
return false;
}
- return lhs.ipEndPoint.Equals(rhs.ipEndPoint);
+ return lhs.remoteEndPoint.Equals(rhs.remoteEndPoint);
}
public static bool operator !=(Simulator lhs, Simulator rhs)
@@ -867,7 +866,7 @@ namespace OpenMetaverse
Packet packet = null;
// Check if this packet came from the server we expected it to come from
- if (!ipEndPoint.Address.Equals(((IPEndPoint)buffer.RemoteEndPoint).Address))
+ if (!remoteEndPoint.Address.Equals(((IPEndPoint)buffer.RemoteEndPoint).Address))
{
Logger.Log("Received " + buffer.DataLength + " bytes of data from unrecognized source " +
((IPEndPoint)buffer.RemoteEndPoint).ToString(), Helpers.LogLevel.Warning, Client);
@@ -976,59 +975,52 @@ namespace OpenMetaverse
///
private void ResendUnacked()
{
- lock (NeedAck)
+ if (NeedAck.Count > 0)
{
- if (NeedAck.Count > 0)
+ NetworkManager.OutgoingPacket[] array;
+
+ lock (NeedAck)
{
// Create a temporary copy of the outgoing packets array to iterate over
- NetworkManager.OutgoingPacket[] array = new NetworkManager.OutgoingPacket[NeedAck.Count];
+ array = new NetworkManager.OutgoingPacket[NeedAck.Count];
NeedAck.Values.CopyTo(array, 0);
+ }
- int now = Environment.TickCount;
+ int now = Environment.TickCount;
- // Resend packets
- for (int i = 0; i < array.Length; i++)
+ // Resend packets
+ for (int i = 0; i < array.Length; i++)
+ {
+ NetworkManager.OutgoingPacket outgoing = array[i];
+
+ if (outgoing.TickCount != 0 && now - outgoing.TickCount > Client.Settings.RESEND_TIMEOUT)
{
- NetworkManager.OutgoingPacket outgoing = array[i];
-
- if (outgoing.TickCount != 0 && now - outgoing.TickCount > Client.Settings.RESEND_TIMEOUT)
+ if (outgoing.ResendCount < Client.Settings.MAX_RESEND_COUNT)
{
- if (outgoing.ResendCount < Client.Settings.MAX_RESEND_COUNT)
+ if (Client.Settings.LOG_RESENDS)
{
- try
- {
- if (Client.Settings.LOG_RESENDS)
- {
- Logger.DebugLog(String.Format("Resending packet #{0} ({1}), {2}ms have passed",
- outgoing.Packet.Header.Sequence, outgoing.Packet.GetType(),
- now - outgoing.TickCount),Client);
- }
-
- // The TickCount will be set to the current time when the packet
- // is actually sent out again. Set it to zero while it sits in the
- // queue to avoid requeueing the same packet
-
- outgoing.TickCount = 0;
- outgoing.SetSequence = false;
- outgoing.Packet.Header.Resent = true;
- ++outgoing.ResendCount;
-
- ++Stats.ResentPackets;
-
- SendPacket(outgoing);
- }
- catch (Exception ex)
- {
- Logger.DebugLog("Exception trying to resend packet: " + ex.ToString(), Client);
- }
+ Logger.DebugLog(String.Format("Resending packet #{0} ({1}), {2}ms have passed",
+ outgoing.Packet.Header.Sequence, outgoing.Packet.GetType(),
+ now - outgoing.TickCount), Client);
}
- else
- {
- Logger.DebugLog(String.Format("Dropping packet #{0} ({1}) after {2} failed attempts",
- outgoing.Packet.Header.Sequence, outgoing.Packet.GetType(), outgoing.ResendCount));
- NeedAck.Remove(outgoing.Packet.Header.Sequence);
- }
+ // The TickCount will be set to the current time when the packet
+ // is actually sent out again
+ outgoing.TickCount = 0;
+ outgoing.SetSequence = false;
+ outgoing.Packet.Header.Resent = true;
+ ++outgoing.ResendCount;
+
+ ++Stats.ResentPackets;
+
+ SendPacket(outgoing);
+ }
+ else
+ {
+ Logger.DebugLog(String.Format("Dropping packet #{0} ({1}) after {2} failed attempts",
+ outgoing.Packet.Header.Sequence, outgoing.Packet.GetType(), outgoing.ResendCount));
+
+ lock (NeedAck) NeedAck.Remove(outgoing.Packet.Header.Sequence);
}
}
}
diff --git a/OpenMetaverse/UDPBase.cs b/OpenMetaverse/UDPBase.cs
index fce90627..26022f26 100644
--- a/OpenMetaverse/UDPBase.cs
+++ b/OpenMetaverse/UDPBase.cs
@@ -56,11 +56,7 @@ namespace OpenMetaverse
// wait until all outstanding operations are completed before shutting down.
// this avoids the problem of closing the socket with outstanding operations
// and trying to catch the inevitable ObjectDisposedException.
-#if PocketPC
- private OpenMetaverse.ReaderWriterLock rwLock = new OpenMetaverse.ReaderWriterLock();
-#else
private ReaderWriterLock rwLock = new ReaderWriterLock();
-#endif
// number of outstanding operations. This is a reference count
// which we use to ensure that the threads exit cleanly. Note that
@@ -71,8 +67,8 @@ namespace OpenMetaverse
// the all important shutdownFlag. This is synchronized through the ReaderWriterLock.
private volatile bool shutdownFlag = true;
- //
- private IPEndPoint remoteEndPoint = null;
+ // the remote endpoint to communicate with
+ protected IPEndPoint remoteEndPoint = null;
///
diff --git a/Programs/Simian/Extensions/ConnectionManagement.cs b/Programs/Simian/Extensions/ConnectionManagement.cs
index 4a732558..8f4f5b40 100644
--- a/Programs/Simian/Extensions/ConnectionManagement.cs
+++ b/Programs/Simian/Extensions/ConnectionManagement.cs
@@ -17,9 +17,9 @@ namespace Simian.Extensions
{
this.server = server;
- server.UDP.RegisterPacketCallback(PacketType.UseCircuitCode, new PacketCallback(UseCircuitCodeHandler));
- server.UDP.RegisterPacketCallback(PacketType.StartPingCheck, new PacketCallback(StartPingCheckHandler));
- server.UDP.RegisterPacketCallback(PacketType.LogoutRequest, new PacketCallback(LogoutRequestHandler));
+ server.UDP.RegisterPacketCallback(PacketType.UseCircuitCode, UseCircuitCodeHandler);
+ server.UDP.RegisterPacketCallback(PacketType.StartPingCheck, StartPingCheckHandler);
+ server.UDP.RegisterPacketCallback(PacketType.LogoutRequest, LogoutRequestHandler);
}
public void Stop()
diff --git a/Programs/Simian/Extensions/FriendManager.cs b/Programs/Simian/Extensions/FriendManager.cs
index bb01cfb6..64598009 100644
--- a/Programs/Simian/Extensions/FriendManager.cs
+++ b/Programs/Simian/Extensions/FriendManager.cs
@@ -35,77 +35,73 @@ namespace Simian.Extensions
{
lock (server.Agents)
{
- foreach (Agent recipient in server.Agents.Values)
+ // HACK: Only works for agents currently online
+ Agent recipient;
+ if (server.Agents.TryGetValue(im.MessageBlock.ToAgentID, out recipient))
{
- if (recipient.AgentID == im.MessageBlock.ToAgentID)
+ ImprovedInstantMessagePacket sendIM = new ImprovedInstantMessagePacket();
+ sendIM.MessageBlock.RegionID = UUID.Random(); //FIXME
+ sendIM.MessageBlock.ParentEstateID = 1;
+ sendIM.MessageBlock.FromGroup = false;
+ sendIM.MessageBlock.FromAgentName = Utils.StringToBytes(agent.Avatar.Name);
+ sendIM.MessageBlock.ToAgentID = im.MessageBlock.ToAgentID;
+ sendIM.MessageBlock.Dialog = im.MessageBlock.Dialog;
+ sendIM.MessageBlock.Offline = (byte)InstantMessageOnline.Online;
+ sendIM.MessageBlock.ID = agent.AgentID;
+ sendIM.MessageBlock.Message = im.MessageBlock.Message;
+ sendIM.MessageBlock.BinaryBucket = new byte[0];
+ sendIM.MessageBlock.Timestamp = 0;
+ sendIM.MessageBlock.Position = agent.Avatar.Position;
+
+ sendIM.AgentData.AgentID = agent.AgentID;
+
+ server.UDP.SendPacket(recipient.AgentID, sendIM, PacketCategory.Transaction);
+
+ if (dialog == InstantMessageDialog.FriendshipAccepted)
{
- ImprovedInstantMessagePacket sendIM = new ImprovedInstantMessagePacket();
- sendIM.MessageBlock.RegionID = UUID.Random(); //FIXME
- sendIM.MessageBlock.ParentEstateID = 1;
- sendIM.MessageBlock.FromGroup = false;
- sendIM.MessageBlock.FromAgentName = Utils.StringToBytes(agent.Avatar.Name);
- sendIM.MessageBlock.ToAgentID = im.MessageBlock.ToAgentID;
- sendIM.MessageBlock.Dialog = im.MessageBlock.Dialog;
- sendIM.MessageBlock.Offline = (byte)InstantMessageOnline.Online;
- sendIM.MessageBlock.ID = agent.AgentID;
- sendIM.MessageBlock.Message = im.MessageBlock.Message;
- sendIM.MessageBlock.BinaryBucket = new byte[0];
- sendIM.MessageBlock.Timestamp = 0;
- sendIM.MessageBlock.Position = agent.Avatar.Position;
+ bool receiverOnline = server.Agents.ContainsKey(agent.AgentID);
+ bool senderOnline = server.Agents.ContainsKey(recipient.AgentID);
- sendIM.AgentData.AgentID = agent.AgentID;
-
- server.UDP.SendPacket(recipient.AgentID, sendIM, PacketCategory.Transaction);
-
- if (dialog == InstantMessageDialog.FriendshipAccepted)
+ if (receiverOnline)
{
- bool receiverOnline = server.Agents.ContainsKey(agent.AgentID);
- bool senderOnline = server.Agents.ContainsKey(recipient.AgentID);
-
- if (receiverOnline)
- {
- if (senderOnline)
- {
- OnlineNotificationPacket notify = new OnlineNotificationPacket();
- notify.AgentBlock = new OnlineNotificationPacket.AgentBlockBlock[0];
- notify.AgentBlock[0] = new OnlineNotificationPacket.AgentBlockBlock();
- notify.AgentBlock[0].AgentID = agent.AgentID;
- server.UDP.SendPacket(recipient.AgentID, notify, PacketCategory.State);
- }
- else
- {
- OfflineNotificationPacket notify = new OfflineNotificationPacket();
- notify.AgentBlock = new OfflineNotificationPacket.AgentBlockBlock[0];
- notify.AgentBlock[0] = new OfflineNotificationPacket.AgentBlockBlock();
- notify.AgentBlock[0].AgentID = agent.AgentID;
- server.UDP.SendPacket(recipient.AgentID, notify, PacketCategory.State);
- }
- }
-
if (senderOnline)
{
- if (receiverOnline)
- {
- OnlineNotificationPacket notify = new OnlineNotificationPacket();
- notify.AgentBlock = new OnlineNotificationPacket.AgentBlockBlock[0];
- notify.AgentBlock[0] = new OnlineNotificationPacket.AgentBlockBlock();
- notify.AgentBlock[0].AgentID = recipient.AgentID;
- server.UDP.SendPacket(agent.AgentID, notify, PacketCategory.State);
- }
- else
- {
- OfflineNotificationPacket notify = new OfflineNotificationPacket();
- notify.AgentBlock = new OfflineNotificationPacket.AgentBlockBlock[0];
- notify.AgentBlock[0] = new OfflineNotificationPacket.AgentBlockBlock();
- notify.AgentBlock[0].AgentID = recipient.AgentID;
- server.UDP.SendPacket(agent.AgentID, notify, PacketCategory.State);
- }
+ OnlineNotificationPacket notify = new OnlineNotificationPacket();
+ notify.AgentBlock = new OnlineNotificationPacket.AgentBlockBlock[0];
+ notify.AgentBlock[0] = new OnlineNotificationPacket.AgentBlockBlock();
+ notify.AgentBlock[0].AgentID = agent.AgentID;
+ server.UDP.SendPacket(recipient.AgentID, notify, PacketCategory.State);
}
+ else
+ {
+ OfflineNotificationPacket notify = new OfflineNotificationPacket();
+ notify.AgentBlock = new OfflineNotificationPacket.AgentBlockBlock[0];
+ notify.AgentBlock[0] = new OfflineNotificationPacket.AgentBlockBlock();
+ notify.AgentBlock[0].AgentID = agent.AgentID;
+ server.UDP.SendPacket(recipient.AgentID, notify, PacketCategory.State);
+ }
+ }
- }
-
- break;
- }
+ if (senderOnline)
+ {
+ if (receiverOnline)
+ {
+ OnlineNotificationPacket notify = new OnlineNotificationPacket();
+ notify.AgentBlock = new OnlineNotificationPacket.AgentBlockBlock[0];
+ notify.AgentBlock[0] = new OnlineNotificationPacket.AgentBlockBlock();
+ notify.AgentBlock[0].AgentID = recipient.AgentID;
+ server.UDP.SendPacket(agent.AgentID, notify, PacketCategory.State);
+ }
+ else
+ {
+ OfflineNotificationPacket notify = new OfflineNotificationPacket();
+ notify.AgentBlock = new OfflineNotificationPacket.AgentBlockBlock[0];
+ notify.AgentBlock[0] = new OfflineNotificationPacket.AgentBlockBlock();
+ notify.AgentBlock[0].AgentID = recipient.AgentID;
+ server.UDP.SendPacket(agent.AgentID, notify, PacketCategory.State);
+ }
+ }
+ }
}
}
}
diff --git a/Programs/Simian/Extensions/Messaging.cs b/Programs/Simian/Extensions/Messaging.cs
index d9d715aa..c0de013a 100644
--- a/Programs/Simian/Extensions/Messaging.cs
+++ b/Programs/Simian/Extensions/Messaging.cs
@@ -58,30 +58,27 @@ namespace Simian.Extensions
{
lock (server.Agents)
{
- foreach (Agent recipient in server.Agents.Values)
+ // HACK: Only works for agents currently online
+ Agent recipient;
+ if (server.Agents.TryGetValue(im.MessageBlock.ToAgentID, out recipient))
{
- if (recipient.AgentID == im.MessageBlock.ToAgentID)
- {
- ImprovedInstantMessagePacket sendIM = new ImprovedInstantMessagePacket();
- sendIM.MessageBlock.RegionID = UUID.Random(); //FIXME
- sendIM.MessageBlock.ParentEstateID = 1;
- sendIM.MessageBlock.FromGroup = false;
- sendIM.MessageBlock.FromAgentName = Utils.StringToBytes(agent.Avatar.Name);
- sendIM.MessageBlock.ToAgentID = im.MessageBlock.ToAgentID;
- sendIM.MessageBlock.Dialog = im.MessageBlock.Dialog;
- sendIM.MessageBlock.Offline = (byte)InstantMessageOnline.Online;
- sendIM.MessageBlock.ID = agent.AgentID;
- sendIM.MessageBlock.Message = im.MessageBlock.Message;
- sendIM.MessageBlock.BinaryBucket = new byte[0];
- sendIM.MessageBlock.Timestamp = 0;
- sendIM.MessageBlock.Position = agent.Avatar.Position;
+ ImprovedInstantMessagePacket sendIM = new ImprovedInstantMessagePacket();
+ sendIM.MessageBlock.RegionID = UUID.Random(); //FIXME
+ sendIM.MessageBlock.ParentEstateID = 1;
+ sendIM.MessageBlock.FromGroup = false;
+ sendIM.MessageBlock.FromAgentName = Utils.StringToBytes(agent.Avatar.Name);
+ sendIM.MessageBlock.ToAgentID = im.MessageBlock.ToAgentID;
+ sendIM.MessageBlock.Dialog = im.MessageBlock.Dialog;
+ sendIM.MessageBlock.Offline = (byte)InstantMessageOnline.Online;
+ sendIM.MessageBlock.ID = agent.AgentID;
+ sendIM.MessageBlock.Message = im.MessageBlock.Message;
+ sendIM.MessageBlock.BinaryBucket = new byte[0];
+ sendIM.MessageBlock.Timestamp = 0;
+ sendIM.MessageBlock.Position = agent.Avatar.Position;
- sendIM.AgentData.AgentID = agent.AgentID;
+ sendIM.AgentData.AgentID = agent.AgentID;
- server.UDP.SendPacket(recipient.AgentID, sendIM, PacketCategory.Transaction);
-
- break;
- }
+ server.UDP.SendPacket(recipient.AgentID, sendIM, PacketCategory.Transaction);
}
}
}
diff --git a/Programs/Simian/Extensions/Money.cs b/Programs/Simian/Extensions/Money.cs
index 6c5b9bd0..8364360e 100644
--- a/Programs/Simian/Extensions/Money.cs
+++ b/Programs/Simian/Extensions/Money.cs
@@ -54,18 +54,15 @@ namespace Simian.Extensions
lock (server.Agents)
{
- foreach (Agent recipient in server.Agents.Values)
+ // HACK: Only works for sending money to someone who is online
+ Agent recipient;
+ if (server.Agents.TryGetValue(request.MoneyData.DestID, out recipient))
{
- if (recipient.AgentID == request.MoneyData.DestID)
- {
- agent.Balance -= request.MoneyData.Amount;
- recipient.Balance += request.MoneyData.Amount;
+ agent.Balance -= request.MoneyData.Amount;
+ recipient.Balance += request.MoneyData.Amount;
- SendBalance(agent, UUID.Zero, String.Format("You paid L${0} to {1}.", request.MoneyData.Amount, recipient.Avatar.Name));
- SendBalance(agent, UUID.Zero, String.Format("{1} paid you L${0}.", request.MoneyData.Amount, agent.Avatar.Name));
-
- break;
- }
+ SendBalance(agent, UUID.Zero, String.Format("You paid L${0} to {1}.", request.MoneyData.Amount, recipient.Avatar.Name));
+ SendBalance(agent, UUID.Zero, String.Format("{1} paid you L${0}.", request.MoneyData.Amount, agent.Avatar.Name));
}
}
}
diff --git a/Programs/Simian/Extensions/UDPManager.cs b/Programs/Simian/Extensions/UDPManager.cs
index 6da03c9e..7709deaa 100644
--- a/Programs/Simian/Extensions/UDPManager.cs
+++ b/Programs/Simian/Extensions/UDPManager.cs
@@ -22,10 +22,13 @@ namespace Simian
public int ResendCount;
/// Environment.TickCount when this packet was last sent over the wire
public int TickCount;
+ /// Category this packet belongs to
+ public PacketCategory Category;
- public OutgoingPacket(Packet packet)
+ public OutgoingPacket(Packet packet, PacketCategory category)
{
Packet = packet;
+ Category = category;
}
}
@@ -98,11 +101,6 @@ namespace Simian
return udpServer.RemoveClient(agent);
}
- public bool RemoveClient(Agent agent, IPEndPoint endpoint)
- {
- return udpServer.RemoveClient(agent, endpoint);
- }
-
public uint CreateCircuit(Agent agent)
{
return udpServer.CreateCircuit(agent);
@@ -176,11 +174,6 @@ namespace Simian
return false;
}
- public bool RemoveClient(Agent agent, IPEndPoint endpoint)
- {
- return clients.Remove(agent.AgentID, endpoint);
- }
-
public uint CreateCircuit(Agent agent)
{
uint circuitCode = (uint)Interlocked.Increment(ref currentCircuitCode);
@@ -197,7 +190,7 @@ namespace Simian
public void BroadcastPacket(Packet packet, PacketCategory category)
{
clients.ForEach(
- delegate(UDPClient client) { SendPacket(client, packet, category, true); });
+ delegate(UDPClient client) { SendPacket(client, new OutgoingPacket(packet, category)); });
}
public void SendPacket(UUID agentID, Packet packet, PacketCategory category)
@@ -211,16 +204,19 @@ namespace Simian
return;
}
- SendPacket(client, packet, category, true);
+ SendPacket(client, new OutgoingPacket(packet, category));
}
- void SendPacket(UDPClient client, Packet packet, PacketCategory category, bool setSequence)
+ void SendPacket(UDPClient client, OutgoingPacket outgoingPacket)
{
+ Packet packet = outgoingPacket.Packet;
byte[] buffer;
int bytes;
- // Set sequence implies that this is not a resent packet
- if (setSequence)
+ // Update the sent time for this packet
+ outgoingPacket.TickCount = Environment.TickCount;
+
+ if (!packet.Header.Resent)
{
// Reset to zero if we've hit the upper sequence number limit
Interlocked.CompareExchange(ref client.CurrentSequence, 0, 0xFFFFFF);
@@ -230,71 +226,55 @@ namespace Simian
if (packet.Header.Reliable)
{
- OutgoingPacket outgoing;
+ // Add this packet to the list of ACK responses we are waiting on from this client
+ lock (client.NeedAcks)
+ client.NeedAcks[sequence] = outgoingPacket;
- if (packet.Header.Resent && client.NeedAcks.TryGetValue(packet.Header.Sequence, out outgoing))
+ // This packet is reliable and not a resend, check if the conditions are favorable
+ // to ACK appending
+ if (packet.Type != PacketType.PacketAck)
{
- // 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)
+ lock (client.PendingAcks)
{
- Logger.DebugLog(String.Format("Purging ACKs from packet #{0} ({1}) which will be resent.",
- packet.Header.Sequence, packet.GetType()));
+ int count = client.PendingAcks.Count;
- lock (client.PendingAcks)
+ if (count > 0 && count < 10)
{
- foreach (uint ack in packet.Header.AckList)
- {
- if (!client.PendingAcks.ContainsKey(ack))
- client.PendingAcks[ack] = ack;
- }
- }
+ // Append all of the queued up outgoing ACKs to this packet
+ packet.Header.AckList = new uint[count];
- packet.Header.AppendedAcks = false;
- packet.Header.AckList = new uint[0];
- }
- }
- else
- {
- // Wrap this packet in a struct to track timeouts and resends
- outgoing = new OutgoingPacket(packet);
+ for (int i = 0; i < count; i++)
+ packet.Header.AckList[i] = client.PendingAcks.Values[i];
- // Add this packet to the list of ACK responses we are waiting on from this client
- lock (client.NeedAcks)
- client.NeedAcks[sequence] = outgoing;
-
- // This packet is not a resend, check if the conditions are favorable
- // to ACK appending
- if (packet.Type != PacketType.PacketAck)
- {
- lock (client.PendingAcks)
- {
- int count = client.PendingAcks.Count;
-
- if (count > 0 && count < 10)
- {
- // Append all of the queued up outgoing ACKs to this packet
- packet.Header.AckList = new uint[count];
-
- for (int i = 0; i < count; i++)
- packet.Header.AckList[i] = client.PendingAcks.Values[i];
-
- client.PendingAcks.Clear();
- packet.Header.AppendedAcks = true;
- }
+ client.PendingAcks.Clear();
+ packet.Header.AppendedAcks = true;
}
}
}
-
- // Update the sent time for this packet
- outgoing.TickCount = Environment.TickCount;
}
- else if (packet.Header.AckList.Length > 0)
+ }
+ else
+ {
+ // 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)
{
- // 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);
+ Logger.DebugLog(String.Format("Purging ACKs from packet #{0} ({1}) which will be resent.",
+ packet.Header.Sequence, packet.GetType()));
+
+ lock (client.PendingAcks)
+ {
+ foreach (uint ack in packet.Header.AckList)
+ {
+ if (!client.PendingAcks.ContainsKey(ack))
+ client.PendingAcks[ack] = ack;
+ }
+ }
+
+ packet.Header.AppendedAcks = false;
+ packet.Header.AckList = new uint[0];
}
}
@@ -345,7 +325,7 @@ namespace Simian
acks.Packets[0] = new PacketAckPacket.PacketsBlock();
acks.Packets[0].ID = ack;
- SendPacket(client, acks, PacketCategory.Overhead, true);
+ SendPacket(client, new OutgoingPacket(acks, PacketCategory.Overhead));
}
public void SendAcks(UDPClient client)
@@ -378,19 +358,29 @@ namespace Simian
}
if (acks != null)
- SendPacket(client, acks, PacketCategory.Overhead, true);
+ SendPacket(client, new OutgoingPacket(acks, PacketCategory.Overhead));
}
public void ResendUnacked(UDPClient client)
{
- lock (client.NeedAcks)
+ if (client.NeedAcks.Count > 0)
{
- List dropAck = new List();
+ OutgoingPacket[] array;
int now = Environment.TickCount;
- // Resend packets
- foreach (OutgoingPacket outgoing in client.NeedAcks.Values)
+ lock (client.NeedAcks)
{
+ // Create a temporary copy of the outgoing packets array to iterate over
+ array = new OutgoingPacket[client.NeedAcks.Count];
+ client.NeedAcks.Values.CopyTo(array, 0);
+ }
+
+ // Resend packets
+ for (int i = 0; i < array.Length; i++)
+ {
+ OutgoingPacket outgoing = array[i];
+
+ // FIXME: Make 4000 and 3 .ini settings
if (outgoing.TickCount != 0 && now - outgoing.TickCount > 4000)
{
if (outgoing.ResendCount < 3)
@@ -398,12 +388,15 @@ namespace Simian
Logger.DebugLog(String.Format("Resending packet #{0} ({1}), {2}ms have passed",
outgoing.Packet.Header.Sequence, outgoing.Packet.GetType(), now - outgoing.TickCount));
- outgoing.TickCount = Environment.TickCount;
+ // The TickCount will be set to the current time when the packet
+ // is actually sent out again
+ outgoing.TickCount = 0;
outgoing.Packet.Header.Resent = true;
++outgoing.ResendCount;
+
//++Stats.ResentPackets;
- SendPacket(client, outgoing.Packet, PacketCategory.Overhead, false);
+ SendPacket(client, outgoing);
}
else
{
@@ -411,10 +404,10 @@ namespace Simian
outgoing.Packet.Header.Sequence, outgoing.Packet.GetType(), outgoing.ResendCount),
Helpers.LogLevel.Warning);
- dropAck.Add(outgoing.Packet.Header.Sequence);
+ lock (client.NeedAcks) client.NeedAcks.Remove(outgoing.Packet.Header.Sequence);
//Disconnect an agent if no packets are received for some time
- //TODO: 60000 should be a setting somewhere.
+ //FIXME: Make 60000 an .ini setting
if (Environment.TickCount - client.Agent.TickLastPacketReceived > 60000)
{
Logger.Log(String.Format("Ack timeout for {0}, disconnecting", client.Agent.Avatar.Name),
@@ -426,12 +419,6 @@ namespace Simian
}
}
}
-
- if (dropAck.Count != 0)
- {
- for (int i = 0; i < dropAck.Count; i++)
- client.NeedAcks.Remove(dropAck[i]);
- }
}
}
@@ -470,6 +457,7 @@ namespace Simian
Agent agent;
if (CompleteAgentConnection(useCircuitCode.CircuitCode.Code, out agent))
{
+ // FIXME: Sanity check that the agent isn't already logged in here
AddClient(agent, address);
if (clients.TryGetValue(agent.AgentID, out client))
{
@@ -607,35 +595,20 @@ namespace Simian
}
}
- bool TryGetUnassociatedAgent(uint circuitCode, out Agent agent)
- {
- if (unassociatedAgents.TryGetValue(circuitCode, out agent))
- {
- lock (unassociatedAgents)
- unassociatedAgents.Remove(circuitCode);
-
- return true;
- }
- else
- {
- return false;
- }
- }
-
bool CompleteAgentConnection(uint circuitCode, out Agent agent)
{
- if (unassociatedAgents.TryGetValue(circuitCode, out agent))
+ lock (unassociatedAgents)
{
- lock (server.Agents)
- server.Agents[agent.AgentID] = agent;
- lock (unassociatedAgents)
+ if (unassociatedAgents.TryGetValue(circuitCode, out agent))
+ {
unassociatedAgents.Remove(circuitCode);
-
- return true;
- }
- else
- {
- return false;
+ lock (server.Agents) server.Agents[agent.AgentID] = agent;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
}
}
}
diff --git a/Programs/Simian/Interfaces/IUDPProvider.cs b/Programs/Simian/Interfaces/IUDPProvider.cs
index ced107f6..f7351c4e 100644
--- a/Programs/Simian/Interfaces/IUDPProvider.cs
+++ b/Programs/Simian/Interfaces/IUDPProvider.cs
@@ -36,7 +36,6 @@ namespace Simian
{
void AddClient(Agent agent, IPEndPoint endpoint);
bool RemoveClient(Agent agent);
- bool RemoveClient(Agent agent, IPEndPoint endpoint);
uint CreateCircuit(Agent agent);
void SendPacket(UUID agentID, Packet packet, PacketCategory category);
diff --git a/Programs/Simian/Simian.cs b/Programs/Simian/Simian.cs
index aac882b6..f06f6469 100644
--- a/Programs/Simian/Simian.cs
+++ b/Programs/Simian/Simian.cs
@@ -316,7 +316,8 @@ namespace Simian
// Get this machine's IP address
IPHostEntry addresses = Dns.GetHostByName(Dns.GetHostName());
- IPAddress simIP = addresses.AddressList.Length > 0 ? addresses.AddressList[0] : IPAddress.Loopback;
+ IPAddress simIP = addresses.AddressList.Length > 0 ?
+ addresses.AddressList[addresses.AddressList.Length - 1] :IPAddress.Loopback;
response.AgentID = agent.AgentID;
response.SecureSessionID = agent.SecureSessionID;
diff --git a/bin/Simian.ini b/bin/Simian.ini
index ec879e7f..42954ce0 100644
--- a/bin/Simian.ini
+++ b/bin/Simian.ini
@@ -5,7 +5,7 @@ UDPManager
; LLUDP connection management. Allows agents to connect and disconnect from a
; simulator, as well as keeping the UDP connection alive.
-ConnectionManager
+ConnectionManagement
; Creates an account for anyone who logs in. The account will be registered
; with the account provider so persistence between sessions is possible, but