aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Client/MXP/ClientStack/MXPClientView.cs17
-rw-r--r--OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs6
-rw-r--r--OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs7
-rw-r--r--OpenSim/Framework/ClientManager.cs258
-rw-r--r--OpenSim/Framework/Communications/GenericAsyncResult.cs1
-rw-r--r--OpenSim/Framework/Communications/RestClient.cs6
-rw-r--r--OpenSim/Framework/IClientAPI.cs4
-rw-r--r--OpenSim/Framework/IScene.cs1
-rw-r--r--OpenSim/Framework/LocklessQueue.cs130
-rw-r--r--OpenSim/Framework/Parallel.cs3
-rw-r--r--OpenSim/Framework/ThrottleOutPacketType.cs18
-rw-r--r--OpenSim/Region/Application/OpenSimBackground.cs1
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs611
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs50
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs85
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs282
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs394
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs481
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs9
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs18
-rw-r--r--OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs4
-rw-r--r--OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs7
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs26
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs115
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs28
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs15
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneBaseTests.cs5
-rw-r--r--OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/IRCStackModule.cs1
-rw-r--r--OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs8
-rw-r--r--OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs10
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs14
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs1
-rw-r--r--OpenSim/Region/Physics/Meshing/PrimMesher.cs2
-rw-r--r--OpenSim/Tests/Common/Mock/TestClient.cs7
-rw-r--r--ThirdPartyLicenses/BclExtras.txt60
-rw-r--r--ThirdPartyLicenses/CSJ2K.txt28
-rw-r--r--bin/BclExtras.dllbin0 -> 178688 bytes
-rw-r--r--prebuild.xml3
40 files changed, 1153 insertions, 1567 deletions
diff --git a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs
index bc1b2e5..bc02bc4 100644
--- a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs
+++ b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs
@@ -774,6 +774,11 @@ namespace OpenSim.Client.MXP.ClientStack
774 get { return m_sessionID.CRC(); } 774 get { return m_sessionID.CRC(); }
775 } 775 }
776 776
777 public IPEndPoint RemoteEndPoint
778 {
779 get { return Session.RemoteEndPoint; }
780 }
781
777 public void SetDebugPacketLevel(int newDebug) 782 public void SetDebugPacketLevel(int newDebug)
778 { 783 {
779 //m_debugLevel = newDebug; 784 //m_debugLevel = newDebug;
@@ -798,9 +803,9 @@ namespace OpenSim.Client.MXP.ClientStack
798 OnConnectionClosed(this); 803 OnConnectionClosed(this);
799 } 804 }
800 805
801 public void Close(bool ShutdownCircuit) 806 public void Close()
802 { 807 {
803 m_log.Info("[MXP ClientStack] Close Called with SC=" + ShutdownCircuit); 808 m_log.Info("[MXP ClientStack] Close Called");
804 809
805 // Tell the client to go 810 // Tell the client to go
806 SendLogoutPacket(); 811 SendLogoutPacket();
@@ -815,7 +820,7 @@ namespace OpenSim.Client.MXP.ClientStack
815 820
816 public void Kick(string message) 821 public void Kick(string message)
817 { 822 {
818 Close(false); 823 Close();
819 } 824 }
820 825
821 public void Start() 826 public void Start()
@@ -1448,7 +1453,7 @@ namespace OpenSim.Client.MXP.ClientStack
1448 1453
1449 public void Terminate() 1454 public void Terminate()
1450 { 1455 {
1451 Close(false); 1456 Close();
1452 } 1457 }
1453 1458
1454 public void SendSetFollowCamProperties(UUID objectID, SortedDictionary<int, float> parameters) 1459 public void SendSetFollowCamProperties(UUID objectID, SortedDictionary<int, float> parameters)
@@ -1615,12 +1620,12 @@ namespace OpenSim.Client.MXP.ClientStack
1615 public void Disconnect(string reason) 1620 public void Disconnect(string reason)
1616 { 1621 {
1617 Kick(reason); 1622 Kick(reason);
1618 Close(true); 1623 Close();
1619 } 1624 }
1620 1625
1621 public void Disconnect() 1626 public void Disconnect()
1622 { 1627 {
1623 Close(true); 1628 Close();
1624 } 1629 }
1625 1630
1626 #endregion 1631 #endregion
diff --git a/OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs b/OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs
index 4910ab1..ba9c653 100644
--- a/OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs
+++ b/OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs
@@ -339,12 +339,6 @@ namespace OpenSim.Client.MXP.PacketHandler
339 m_clients.Add(client); 339 m_clients.Add(client);
340 m_log.Debug("[MXP ClientStack]: Created ClientView."); 340 m_log.Debug("[MXP ClientStack]: Created ClientView.");
341 341
342
343 m_log.Debug("[MXP ClientStack]: Adding ClientView to Scene...");
344 scene.ClientManager.Add(client.CircuitCode, client);
345 m_log.Debug("[MXP ClientStack]: Added ClientView to Scene.");
346
347
348 client.MXPSendSynchronizationBegin(m_scenes[new UUID(joinRequestMessage.BubbleId)].SceneContents.GetTotalObjectsCount()); 342 client.MXPSendSynchronizationBegin(m_scenes[new UUID(joinRequestMessage.BubbleId)].SceneContents.GetTotalObjectsCount());
349 343
350 m_log.Debug("[MXP ClientStack]: Starting ClientView..."); 344 m_log.Debug("[MXP ClientStack]: Starting ClientView...");
diff --git a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs
index c649c5a..e3abcf5 100644
--- a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs
+++ b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs
@@ -207,6 +207,11 @@ namespace OpenSim.Client.VWoHTTP.ClientStack
207 get { throw new System.NotImplementedException(); } 207 get { throw new System.NotImplementedException(); }
208 } 208 }
209 209
210 public IPEndPoint RemoteEndPoint
211 {
212 get { throw new System.NotImplementedException(); }
213 }
214
210 public event GenericMessage OnGenericMessage = delegate { }; 215 public event GenericMessage OnGenericMessage = delegate { };
211 public event ImprovedInstantMessage OnInstantMessage = delegate { }; 216 public event ImprovedInstantMessage OnInstantMessage = delegate { };
212 public event ChatMessage OnChatFromClient = delegate { }; 217 public event ChatMessage OnChatFromClient = delegate { };
@@ -415,7 +420,7 @@ namespace OpenSim.Client.VWoHTTP.ClientStack
415 throw new System.NotImplementedException(); 420 throw new System.NotImplementedException();
416 } 421 }
417 422
418 public void Close(bool ShutdownCircuit) 423 public void Close()
419 { 424 {
420 throw new System.NotImplementedException(); 425 throw new System.NotImplementedException();
421 } 426 }
diff --git a/OpenSim/Framework/ClientManager.cs b/OpenSim/Framework/ClientManager.cs
index 094a3ff..367bc6a 100644
--- a/OpenSim/Framework/ClientManager.cs
+++ b/OpenSim/Framework/ClientManager.cs
@@ -28,193 +28,183 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using log4net; 31using System.Net;
32using BclExtras.Collections;
32using OpenMetaverse; 33using OpenMetaverse;
33using OpenMetaverse.Packets; 34using OpenMetaverse.Packets;
34 35
35namespace OpenSim.Framework 36namespace OpenSim.Framework
36{ 37{
37 public delegate void ForEachClientDelegate(IClientAPI client); 38 /// <summary>
38 39 /// Maps from client AgentID and RemoteEndPoint values to IClientAPI
40 /// references for all of the connected clients
41 /// </summary>
39 public class ClientManager 42 public class ClientManager
40 { 43 {
41 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 #region IComparers
42
43 private Dictionary<uint, IClientAPI> m_clients;
44 45
45 public ClientManager() 46 private sealed class UUIDComparer : IComparer<UUID>
46 { 47 {
47 m_clients = new Dictionary<uint, IClientAPI>(); 48 public int Compare(UUID x, UUID y)
48 }
49
50 public void ForEachClient(ForEachClientDelegate whatToDo)
51 {
52 IClientAPI[] LocalClients;
53 lock (m_clients)
54 {
55 LocalClients = new IClientAPI[m_clients.Count];
56 m_clients.Values.CopyTo(LocalClients, 0);
57 }
58
59 for (int i = 0; i < LocalClients.Length; i++)
60 { 49 {
61 try 50 return x.CompareTo(y);
62 {
63 whatToDo(LocalClients[i]);
64 }
65 catch (Exception e)
66 {
67 m_log.Warn("[CLIENT]: Unable to do ForEachClient for one of the clients" + "\n Reason: " + e.ToString());
68 }
69 } 51 }
70 } 52 }
71 53
72 public void Remove(uint id) 54 private sealed class IPEndPointComparer : IComparer<IPEndPoint>
73 { 55 {
74 lock (m_clients) 56 public int Compare(IPEndPoint x, IPEndPoint y)
75 { 57 {
76 m_clients.Remove(id); 58 if (x == null && y == null)
77 } 59 return 0;
78 } 60 else if (x == null)
61 return -1;
62 else if (y == null)
63 return 1;
79 64
80 public void Add(uint id, IClientAPI client) 65 int result = x.Address.Address.CompareTo(y.Address.Address);
81 { 66 if (result == 0) result = x.Port.CompareTo(y.Port);
82 lock (m_clients) 67
83 { 68 return result;
84 m_clients.Add(id, client);
85 } 69 }
86 } 70 }
87 71
72 #endregion IComparers
73
74 /// <summary>An immutable dictionary mapping from <seealso cref="UUID"/>
75 /// to <seealso cref="IClientAPI"/> references</summary>
76 private ImmutableMap<UUID, IClientAPI> m_dict;
77 /// <summary>An immutable dictionary mapping from <seealso cref="IPEndPoint"/>
78 /// to <seealso cref="IClientAPI"/> references</summary>
79 private ImmutableMap<IPEndPoint, IClientAPI> m_dict2;
80 /// <summary>Immutability grants thread safety for concurrent reads and
81 /// read-writes, but not concurrent writes</summary>
82 private object m_writeLock = new object();
83
84 /// <summary>Number of clients in the collection</summary>
85 public int Count { get { return m_dict.Count; } }
86
88 /// <summary> 87 /// <summary>
89 /// Pass incoming packet to client. 88 /// Default constructor
90 /// </summary> 89 /// </summary>
91 /// <param name="circuitCode">uint identifying the connection/client.</param> 90 public ClientManager()
92 /// <param name="packet">object containing the packet.</param>
93 public void InPacket(uint circuitCode, object packet)
94 { 91 {
95 IClientAPI client; 92 m_dict = new ImmutableMap<UUID, IClientAPI>(new UUIDComparer());
96 bool tryGetRet = false; 93 m_dict2 = new ImmutableMap<IPEndPoint, IClientAPI>(new IPEndPointComparer());
97
98 lock (m_clients)
99 tryGetRet = m_clients.TryGetValue(circuitCode, out client);
100
101 if (tryGetRet)
102 {
103 client.InPacket(packet);
104 }
105 } 94 }
106 95
107 public void CloseAllAgents(uint circuitCode) 96 /// <summary>
108 { 97 /// Add a client reference to the collection if it does not already
109 IClientAPI client; 98 /// exist
110 bool tryGetRet = false; 99 /// </summary>
111 lock (m_clients) 100 /// <param name="value">Reference to the client object</param>
112 tryGetRet = m_clients.TryGetValue(circuitCode, out client); 101 /// <returns>True if the client reference was successfully added,
113 if (tryGetRet) 102 /// otherwise false if the given key already existed in the collection</returns>
114 { 103 public bool Add(IClientAPI value)
115 CloseAllCircuits(client.AgentId);
116 }
117 }
118
119 public void CloseAllCircuits(UUID agentId)
120 { 104 {
121 uint[] circuits = GetAllCircuits(agentId); 105 lock (m_writeLock)
122 // We're using a for loop here so changes to the circuits don't cause it to completely fail.
123
124 for (int i = 0; i < circuits.Length; i++)
125 { 106 {
126 IClientAPI client; 107 if (!m_dict.ContainsKey(value.AgentId) && !m_dict2.ContainsKey(value.RemoteEndPoint))
127 try
128 { 108 {
129 bool tryGetRet = false; 109 m_dict = m_dict.Add(value.AgentId, value);
130 lock (m_clients) 110 m_dict2 = m_dict2.Add(value.RemoteEndPoint, value);
131 tryGetRet = m_clients.TryGetValue(circuits[i], out client); 111
132 if (tryGetRet) 112 return true;
133 {
134 Remove(client.CircuitCode);
135 client.Close(false);
136 }
137 } 113 }
138 catch (Exception e) 114 else
139 { 115 {
140 m_log.Error(string.Format("[CLIENT]: Unable to shutdown circuit for: {0}\n Reason: {1}", agentId, e)); 116 return false;
141 } 117 }
142 } 118 }
143 } 119 }
144 120
145 // [Obsolete("Using Obsolete to drive development is invalid. Obsolete presumes that something new has already been created to replace this.")] 121 /// <summary>
146 public uint[] GetAllCircuits(UUID agentId) 122 /// Remove a client from the collection
123 /// </summary>
124 /// <param name="key">UUID of the client to remove</param>
125 /// <returns>True if a client was removed, or false if the given UUID
126 /// was not present in the collection</returns>
127 public bool Remove(UUID key)
147 { 128 {
148 List<uint> circuits = new List<uint>(); 129 lock (m_writeLock)
149 // Wasteful, I know
150 IClientAPI[] LocalClients = new IClientAPI[0];
151 lock (m_clients)
152 { 130 {
153 LocalClients = new IClientAPI[m_clients.Count]; 131 IClientAPI client;
154 m_clients.Values.CopyTo(LocalClients, 0);
155 }
156 132
157 for (int i = 0; i < LocalClients.Length; i++) 133 if (m_dict.TryGetValue(key, out client))
158 {
159 if (LocalClients[i].AgentId == agentId)
160 { 134 {
161 circuits.Add(LocalClients[i].CircuitCode); 135 m_dict = m_dict.Delete(key);
136 m_dict2 = m_dict2.Delete(client.RemoteEndPoint);
137 return true;
138 }
139 else
140 {
141 return false;
162 } 142 }
163 } 143 }
164 return circuits.ToArray();
165 } 144 }
166 145
167 public List<uint> GetAllCircuitCodes() 146 /// <summary>
147 /// Resets the client collection
148 /// </summary>
149 public void Clear()
168 { 150 {
169 List<uint> circuits; 151 lock (m_writeLock)
170
171 lock (m_clients)
172 { 152 {
173 circuits = new List<uint>(m_clients.Keys); 153 m_dict = new ImmutableMap<UUID, IClientAPI>(new UUIDComparer());
154 m_dict2 = new ImmutableMap<IPEndPoint, IClientAPI>(new IPEndPointComparer());
174 } 155 }
156 }
175 157
176 return circuits; 158 /// <summary>
159 /// Checks if a UUID is in the collection
160 /// </summary>
161 /// <param name="key">UUID to check for</param>
162 /// <returns>True if the UUID was found in the collection, otherwise false</returns>
163 public bool ContainsKey(UUID key)
164 {
165 return m_dict.ContainsKey(key);
177 } 166 }
178 167
179 public void ViewerEffectHandler(IClientAPI sender, List<ViewerEffectEventHandlerArg> args) 168 /// <summary>
169 /// Checks if an endpoint is in the collection
170 /// </summary>
171 /// <param name="key">Endpoint to check for</param>
172 /// <returns>True if the endpoint was found in the collection, otherwise false</returns>
173 public bool ContainsKey(IPEndPoint key)
180 { 174 {
181 // TODO: don't create new blocks if recycling an old packet 175 return m_dict2.ContainsKey(key);
182 List<ViewerEffectPacket.EffectBlock> effectBlock = new List<ViewerEffectPacket.EffectBlock>(); 176 }
183 for (int i = 0; i < args.Count; i++)
184 {
185 ViewerEffectPacket.EffectBlock effect = new ViewerEffectPacket.EffectBlock();
186 effect.AgentID = args[i].AgentID;
187 effect.Color = args[i].Color;
188 effect.Duration = args[i].Duration;
189 effect.ID = args[i].ID;
190 effect.Type = args[i].Type;
191 effect.TypeData = args[i].TypeData;
192 effectBlock.Add(effect);
193 }
194 ViewerEffectPacket.EffectBlock[] effectBlockArray = effectBlock.ToArray();
195 177
196 IClientAPI[] LocalClients; 178 /// <summary>
197 lock (m_clients) 179 /// Attempts to fetch a value out of the collection
198 { 180 /// </summary>
199 LocalClients = new IClientAPI[m_clients.Count]; 181 /// <param name="key">UUID of the client to retrieve</param>
200 m_clients.Values.CopyTo(LocalClients, 0); 182 /// <param name="value">Retrieved client, or null on lookup failure</param>
201 } 183 /// <returns>True if the lookup succeeded, otherwise false</returns>
184 public bool TryGetValue(UUID key, out IClientAPI value)
185 {
186 return m_dict.TryGetValue(key, out value);
187 }
202 188
203 for (int i = 0; i < LocalClients.Length; i++) 189 /// <summary>
204 { 190 /// Attempts to fetch a value out of the collection
205 if (LocalClients[i].AgentId != sender.AgentId) 191 /// </summary>
206 { 192 /// <param name="key">Endpoint of the client to retrieve</param>
207 LocalClients[i].SendViewerEffect(effectBlockArray); 193 /// <param name="value">Retrieved client, or null on lookup failure</param>
208 } 194 /// <returns>True if the lookup succeeded, otherwise false</returns>
209 } 195 public bool TryGetValue(IPEndPoint key, out IClientAPI value)
196 {
197 return m_dict2.TryGetValue(key, out value);
210 } 198 }
211 199
212 public bool TryGetClient(uint circuitId, out IClientAPI user) 200 /// <summary>
201 /// Performs a given task in parallel for each of the elements in the
202 /// collection
203 /// </summary>
204 /// <param name="action">Action to perform on each element</param>
205 public void ForEach(Action<IClientAPI> action)
213 { 206 {
214 lock (m_clients) 207 Parallel.ForEach<IClientAPI>(m_dict.Values, action);
215 {
216 return m_clients.TryGetValue(circuitId, out user);
217 }
218 } 208 }
219 } 209 }
220} 210}
diff --git a/OpenSim/Framework/Communications/GenericAsyncResult.cs b/OpenSim/Framework/Communications/GenericAsyncResult.cs
index efd2f43..8e3f62b 100644
--- a/OpenSim/Framework/Communications/GenericAsyncResult.cs
+++ b/OpenSim/Framework/Communications/GenericAsyncResult.cs
@@ -146,6 +146,7 @@ namespace OpenSim.Framework.Communications
146 // If the operation isn't done, wait for it 146 // If the operation isn't done, wait for it
147 AsyncWaitHandle.WaitOne(); 147 AsyncWaitHandle.WaitOne();
148 AsyncWaitHandle.Close(); 148 AsyncWaitHandle.Close();
149 m_waitHandle.Close();
149 m_waitHandle = null; // Allow early GC 150 m_waitHandle = null; // Allow early GC
150 } 151 }
151 152
diff --git a/OpenSim/Framework/Communications/RestClient.cs b/OpenSim/Framework/Communications/RestClient.cs
index d98f47d..a74169e 100644
--- a/OpenSim/Framework/Communications/RestClient.cs
+++ b/OpenSim/Framework/Communications/RestClient.cs
@@ -105,7 +105,7 @@ namespace OpenSim.Framework.Communications
105 /// <summary> 105 /// <summary>
106 /// This flag will help block the main synchroneous method, in case we run in synchroneous mode 106 /// This flag will help block the main synchroneous method, in case we run in synchroneous mode
107 /// </summary> 107 /// </summary>
108 public static ManualResetEvent _allDone = new ManualResetEvent(false); 108 //public static ManualResetEvent _allDone = new ManualResetEvent(false);
109 109
110 /// <summary> 110 /// <summary>
111 /// Default time out period 111 /// Default time out period
@@ -282,12 +282,12 @@ namespace OpenSim.Framework.Communications
282 else 282 else
283 { 283 {
284 s.Close(); 284 s.Close();
285 _allDone.Set(); 285 //_allDone.Set();
286 } 286 }
287 } 287 }
288 catch (Exception e) 288 catch (Exception e)
289 { 289 {
290 _allDone.Set(); 290 //_allDone.Set();
291 _asyncException = e; 291 _asyncException = e;
292 } 292 }
293 } 293 }
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index d3bd9e7..29846f5 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -561,6 +561,8 @@ namespace OpenSim.Framework
561 // [Obsolete("LLClientView Specific - Circuits are unique to LLClientView")] 561 // [Obsolete("LLClientView Specific - Circuits are unique to LLClientView")]
562 uint CircuitCode { get; } 562 uint CircuitCode { get; }
563 563
564 IPEndPoint RemoteEndPoint { get; }
565
564 event GenericMessage OnGenericMessage; 566 event GenericMessage OnGenericMessage;
565 567
566 // [Obsolete("LLClientView Specific - Replace with more bare-bones arguments.")] 568 // [Obsolete("LLClientView Specific - Replace with more bare-bones arguments.")]
@@ -802,7 +804,7 @@ namespace OpenSim.Framework
802 804
803 void InPacket(object NewPack); 805 void InPacket(object NewPack);
804 void ProcessInPacket(Packet NewPack); 806 void ProcessInPacket(Packet NewPack);
805 void Close(bool ShutdownCircuit); 807 void Close();
806 void Kick(string message); 808 void Kick(string message);
807 809
808 /// <summary> 810 /// <summary>
diff --git a/OpenSim/Framework/IScene.cs b/OpenSim/Framework/IScene.cs
index 489653f..f34027d 100644
--- a/OpenSim/Framework/IScene.cs
+++ b/OpenSim/Framework/IScene.cs
@@ -71,7 +71,6 @@ namespace OpenSim.Framework
71 71
72 void AddNewClient(IClientAPI client); 72 void AddNewClient(IClientAPI client);
73 void RemoveClient(UUID agentID); 73 void RemoveClient(UUID agentID);
74 void CloseAllAgents(uint circuitcode);
75 74
76 void Restart(int seconds); 75 void Restart(int seconds);
77 //RegionInfo OtherRegionUp(RegionInfo thisRegion); 76 //RegionInfo OtherRegionUp(RegionInfo thisRegion);
diff --git a/OpenSim/Framework/LocklessQueue.cs b/OpenSim/Framework/LocklessQueue.cs
new file mode 100644
index 0000000..dd3d201
--- /dev/null
+++ b/OpenSim/Framework/LocklessQueue.cs
@@ -0,0 +1,130 @@
1/*
2 * Copyright (c) 2009, openmetaverse.org
3 * All rights reserved.
4 *
5 * - Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * - Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 * - Neither the name of the openmetaverse.org nor the names
11 * of its contributors may be used to endorse or promote products derived from
12 * this software without specific prior written permission.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE.
25 */
26
27using System;
28using System.Threading;
29
30namespace OpenSim.Framework
31{
32 public sealed class LocklessQueue<T>
33 {
34 private sealed class SingleLinkNode
35 {
36 public SingleLinkNode Next;
37 public T Item;
38 }
39
40 SingleLinkNode head;
41 SingleLinkNode tail;
42 int count;
43
44 public int Count { get { return count; } }
45
46 public LocklessQueue()
47 {
48 Init();
49 }
50
51 public void Enqueue(T item)
52 {
53 SingleLinkNode oldTail = null;
54 SingleLinkNode oldTailNext;
55
56 SingleLinkNode newNode = new SingleLinkNode();
57 newNode.Item = item;
58
59 bool newNodeWasAdded = false;
60
61 while (!newNodeWasAdded)
62 {
63 oldTail = tail;
64 oldTailNext = oldTail.Next;
65
66 if (tail == oldTail)
67 {
68 if (oldTailNext == null)
69 newNodeWasAdded = CAS(ref tail.Next, null, newNode);
70 else
71 CAS(ref tail, oldTail, oldTailNext);
72 }
73 }
74
75 CAS(ref tail, oldTail, newNode);
76 Interlocked.Increment(ref count);
77 }
78
79 public bool Dequeue(out T item)
80 {
81 item = default(T);
82 SingleLinkNode oldHead = null;
83 bool haveAdvancedHead = false;
84
85 while (!haveAdvancedHead)
86 {
87 oldHead = head;
88 SingleLinkNode oldTail = tail;
89 SingleLinkNode oldHeadNext = oldHead.Next;
90
91 if (oldHead == head)
92 {
93 if (oldHead == oldTail)
94 {
95 if (oldHeadNext == null)
96 return false;
97
98 CAS(ref tail, oldTail, oldHeadNext);
99 }
100 else
101 {
102 item = oldHeadNext.Item;
103 haveAdvancedHead = CAS(ref head, oldHead, oldHeadNext);
104 }
105 }
106 }
107
108 Interlocked.Decrement(ref count);
109 return true;
110 }
111
112 public void Clear()
113 {
114 Init();
115 }
116
117 private void Init()
118 {
119 count = 0;
120 head = tail = new SingleLinkNode();
121 }
122
123 private static bool CAS(ref SingleLinkNode location, SingleLinkNode comparand, SingleLinkNode newValue)
124 {
125 return
126 (object)comparand ==
127 (object)Interlocked.CompareExchange<SingleLinkNode>(ref location, newValue, comparand);
128 }
129 }
130} \ No newline at end of file
diff --git a/OpenSim/Framework/Parallel.cs b/OpenSim/Framework/Parallel.cs
index 74537ba..6efdad0 100644
--- a/OpenSim/Framework/Parallel.cs
+++ b/OpenSim/Framework/Parallel.cs
@@ -89,6 +89,7 @@ namespace OpenSim.Framework
89 } 89 }
90 90
91 threadFinishEvent.WaitOne(); 91 threadFinishEvent.WaitOne();
92 threadFinishEvent.Close();
92 93
93 if (exception != null) 94 if (exception != null)
94 throw new Exception(exception.Message, exception); 95 throw new Exception(exception.Message, exception);
@@ -148,6 +149,7 @@ namespace OpenSim.Framework
148 } 149 }
149 150
150 threadFinishEvent.WaitOne(); 151 threadFinishEvent.WaitOne();
152 threadFinishEvent.Close();
151 153
152 if (exception != null) 154 if (exception != null)
153 throw new Exception(exception.Message, exception); 155 throw new Exception(exception.Message, exception);
@@ -199,6 +201,7 @@ namespace OpenSim.Framework
199 } 201 }
200 202
201 threadFinishEvent.WaitOne(); 203 threadFinishEvent.WaitOne();
204 threadFinishEvent.Close();
202 205
203 if (exception != null) 206 if (exception != null)
204 throw new Exception(exception.Message, exception); 207 throw new Exception(exception.Message, exception);
diff --git a/OpenSim/Framework/ThrottleOutPacketType.cs b/OpenSim/Framework/ThrottleOutPacketType.cs
index fd490a5..eb42fea 100644
--- a/OpenSim/Framework/ThrottleOutPacketType.cs
+++ b/OpenSim/Framework/ThrottleOutPacketType.cs
@@ -31,13 +31,23 @@ namespace OpenSim.Framework
31{ 31{
32 public enum ThrottleOutPacketType : int 32 public enum ThrottleOutPacketType : int
33 { 33 {
34 Unknown = -1, // Also doubles as 'do not throttle' 34 /// <summary>Unthrottled packets</summary>
35 Unknown = -1,
36 /// <summary>Packets that are being resent</summary>
35 Resend = 0, 37 Resend = 0,
38 /// <summary>Terrain data</summary>
36 Land = 1, 39 Land = 1,
40 /// <summary>Wind data</summary>
37 Wind = 2, 41 Wind = 2,
42 /// <summary>Cloud data</summary>
38 Cloud = 3, 43 Cloud = 3,
39 Task = 4, 44 /// <summary>Texture assets</summary>
40 Texture = 5, 45 Texture = 4,
41 Asset = 6, 46 /// <summary>Non-texture assets</summary>
47 Asset = 5,
48 /// <summary>Avatar and primitive data</summary>
49 State = 6,
50 /// <summary>Any packets that do not fit into the other throttles</summary>
51 Task = 7,
42 } 52 }
43} 53}
diff --git a/OpenSim/Region/Application/OpenSimBackground.cs b/OpenSim/Region/Application/OpenSimBackground.cs
index ac5e241..008c6b0 100644
--- a/OpenSim/Region/Application/OpenSimBackground.cs
+++ b/OpenSim/Region/Application/OpenSimBackground.cs
@@ -58,6 +58,7 @@ namespace OpenSim
58 m_clientServers.Count.ToString(), m_clientServers.Count > 1 ? "s" : ""); 58 m_clientServers.Count.ToString(), m_clientServers.Count > 1 ? "s" : "");
59 59
60 WorldHasComeToAnEnd.WaitOne(); 60 WorldHasComeToAnEnd.WaitOne();
61 WorldHasComeToAnEnd.Close();
61 } 62 }
62 63
63 /// <summary> 64 /// <summary>
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index d64f655..cfc1ebc 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -59,6 +59,209 @@ namespace OpenSim.Region.ClientStack.LindenUDP
59 /// </summary> 59 /// </summary>
60 public class LLClientView : IClientAPI, IClientCore, IClientIM, IClientChat, IClientIPEndpoint, IStatsCollector 60 public class LLClientView : IClientAPI, IClientCore, IClientIM, IClientChat, IClientIPEndpoint, IStatsCollector
61 { 61 {
62 #region Events
63
64 public event GenericMessage OnGenericMessage;
65 public event BinaryGenericMessage OnBinaryGenericMessage;
66 public event Action<IClientAPI> OnLogout;
67 public event ObjectPermissions OnObjectPermissions;
68 public event Action<IClientAPI> OnConnectionClosed;
69 public event ViewerEffectEventHandler OnViewerEffect;
70 public event ImprovedInstantMessage OnInstantMessage;
71 public event ChatMessage OnChatFromClient;
72 public event TextureRequest OnRequestTexture;
73 public event RezObject OnRezObject;
74 public event DeRezObject OnDeRezObject;
75 public event ModifyTerrain OnModifyTerrain;
76 public event Action<IClientAPI> OnRegionHandShakeReply;
77 public event GenericCall2 OnRequestWearables;
78 public event SetAppearance OnSetAppearance;
79 public event AvatarNowWearing OnAvatarNowWearing;
80 public event RezSingleAttachmentFromInv OnRezSingleAttachmentFromInv;
81 public event RezMultipleAttachmentsFromInv OnRezMultipleAttachmentsFromInv;
82 public event UUIDNameRequest OnDetachAttachmentIntoInv;
83 public event ObjectAttach OnObjectAttach;
84 public event ObjectDeselect OnObjectDetach;
85 public event ObjectDrop OnObjectDrop;
86 public event GenericCall2 OnCompleteMovementToRegion;
87 public event UpdateAgent OnAgentUpdate;
88 public event AgentRequestSit OnAgentRequestSit;
89 public event AgentSit OnAgentSit;
90 public event AvatarPickerRequest OnAvatarPickerRequest;
91 public event StartAnim OnStartAnim;
92 public event StopAnim OnStopAnim;
93 public event Action<IClientAPI> OnRequestAvatarsData;
94 public event LinkObjects OnLinkObjects;
95 public event DelinkObjects OnDelinkObjects;
96 public event GrabObject OnGrabObject;
97 public event DeGrabObject OnDeGrabObject;
98 public event SpinStart OnSpinStart;
99 public event SpinStop OnSpinStop;
100 public event ObjectDuplicate OnObjectDuplicate;
101 public event ObjectDuplicateOnRay OnObjectDuplicateOnRay;
102 public event MoveObject OnGrabUpdate;
103 public event SpinObject OnSpinUpdate;
104 public event AddNewPrim OnAddPrim;
105 public event RequestGodlikePowers OnRequestGodlikePowers;
106 public event GodKickUser OnGodKickUser;
107 public event ObjectExtraParams OnUpdateExtraParams;
108 public event UpdateShape OnUpdatePrimShape;
109 public event ObjectRequest OnObjectRequest;
110 public event ObjectSelect OnObjectSelect;
111 public event ObjectDeselect OnObjectDeselect;
112 public event GenericCall7 OnObjectDescription;
113 public event GenericCall7 OnObjectName;
114 public event GenericCall7 OnObjectClickAction;
115 public event GenericCall7 OnObjectMaterial;
116 public event ObjectIncludeInSearch OnObjectIncludeInSearch;
117 public event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily;
118 public event UpdatePrimFlags OnUpdatePrimFlags;
119 public event UpdatePrimTexture OnUpdatePrimTexture;
120 public event UpdateVector OnUpdatePrimGroupPosition;
121 public event UpdateVector OnUpdatePrimSinglePosition;
122 public event UpdatePrimRotation OnUpdatePrimGroupRotation;
123 public event UpdatePrimSingleRotation OnUpdatePrimSingleRotation;
124 public event UpdatePrimSingleRotationPosition OnUpdatePrimSingleRotationPosition;
125 public event UpdatePrimGroupRotation OnUpdatePrimGroupMouseRotation;
126 public event UpdateVector OnUpdatePrimScale;
127 public event UpdateVector OnUpdatePrimGroupScale;
128 public event StatusChange OnChildAgentStatus;
129 public event GenericCall2 OnStopMovement;
130 public event Action<UUID> OnRemoveAvatar;
131 public event RequestMapBlocks OnRequestMapBlocks;
132 public event RequestMapName OnMapNameRequest;
133 public event TeleportLocationRequest OnTeleportLocationRequest;
134 public event TeleportLandmarkRequest OnTeleportLandmarkRequest;
135 public event DisconnectUser OnDisconnectUser;
136 public event RequestAvatarProperties OnRequestAvatarProperties;
137 public event SetAlwaysRun OnSetAlwaysRun;
138 public event FetchInventory OnAgentDataUpdateRequest;
139 public event TeleportLocationRequest OnSetStartLocationRequest;
140 public event UpdateAvatarProperties OnUpdateAvatarProperties;
141 public event CreateNewInventoryItem OnCreateNewInventoryItem;
142 public event CreateInventoryFolder OnCreateNewInventoryFolder;
143 public event UpdateInventoryFolder OnUpdateInventoryFolder;
144 public event MoveInventoryFolder OnMoveInventoryFolder;
145 public event FetchInventoryDescendents OnFetchInventoryDescendents;
146 public event PurgeInventoryDescendents OnPurgeInventoryDescendents;
147 public event FetchInventory OnFetchInventory;
148 public event RequestTaskInventory OnRequestTaskInventory;
149 public event UpdateInventoryItem OnUpdateInventoryItem;
150 public event CopyInventoryItem OnCopyInventoryItem;
151 public event MoveInventoryItem OnMoveInventoryItem;
152 public event RemoveInventoryItem OnRemoveInventoryItem;
153 public event RemoveInventoryFolder OnRemoveInventoryFolder;
154 public event UDPAssetUploadRequest OnAssetUploadRequest;
155 public event XferReceive OnXferReceive;
156 public event RequestXfer OnRequestXfer;
157 public event ConfirmXfer OnConfirmXfer;
158 public event AbortXfer OnAbortXfer;
159 public event RequestTerrain OnRequestTerrain;
160 public event RezScript OnRezScript;
161 public event UpdateTaskInventory OnUpdateTaskInventory;
162 public event MoveTaskInventory OnMoveTaskItem;
163 public event RemoveTaskInventory OnRemoveTaskItem;
164 public event RequestAsset OnRequestAsset;
165 public event UUIDNameRequest OnNameFromUUIDRequest;
166 public event ParcelAccessListRequest OnParcelAccessListRequest;
167 public event ParcelAccessListUpdateRequest OnParcelAccessListUpdateRequest;
168 public event ParcelPropertiesRequest OnParcelPropertiesRequest;
169 public event ParcelDivideRequest OnParcelDivideRequest;
170 public event ParcelJoinRequest OnParcelJoinRequest;
171 public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest;
172 public event ParcelSelectObjects OnParcelSelectObjects;
173 public event ParcelObjectOwnerRequest OnParcelObjectOwnerRequest;
174 public event ParcelAbandonRequest OnParcelAbandonRequest;
175 public event ParcelGodForceOwner OnParcelGodForceOwner;
176 public event ParcelReclaim OnParcelReclaim;
177 public event ParcelReturnObjectsRequest OnParcelReturnObjectsRequest;
178 public event ParcelDeedToGroup OnParcelDeedToGroup;
179 public event RegionInfoRequest OnRegionInfoRequest;
180 public event EstateCovenantRequest OnEstateCovenantRequest;
181 public event FriendActionDelegate OnApproveFriendRequest;
182 public event FriendActionDelegate OnDenyFriendRequest;
183 public event FriendshipTermination OnTerminateFriendship;
184 public event MoneyTransferRequest OnMoneyTransferRequest;
185 public event EconomyDataRequest OnEconomyDataRequest;
186 public event MoneyBalanceRequest OnMoneyBalanceRequest;
187 public event ParcelBuy OnParcelBuy;
188 public event UUIDNameRequest OnTeleportHomeRequest;
189 public event UUIDNameRequest OnUUIDGroupNameRequest;
190 public event ScriptAnswer OnScriptAnswer;
191 public event RequestPayPrice OnRequestPayPrice;
192 public event ObjectSaleInfo OnObjectSaleInfo;
193 public event ObjectBuy OnObjectBuy;
194 public event BuyObjectInventory OnBuyObjectInventory;
195 public event AgentSit OnUndo;
196 public event ForceReleaseControls OnForceReleaseControls;
197 public event GodLandStatRequest OnLandStatRequest;
198 public event RequestObjectPropertiesFamily OnObjectGroupRequest;
199 public event DetailedEstateDataRequest OnDetailedEstateDataRequest;
200 public event SetEstateFlagsRequest OnSetEstateFlagsRequest;
201 public event SetEstateTerrainBaseTexture OnSetEstateTerrainBaseTexture;
202 public event SetEstateTerrainDetailTexture OnSetEstateTerrainDetailTexture;
203 public event SetEstateTerrainTextureHeights OnSetEstateTerrainTextureHeights;
204 public event CommitEstateTerrainTextureRequest OnCommitEstateTerrainTextureRequest;
205 public event SetRegionTerrainSettings OnSetRegionTerrainSettings;
206 public event BakeTerrain OnBakeTerrain;
207 public event RequestTerrain OnUploadTerrain;
208 public event EstateChangeInfo OnEstateChangeInfo;
209 public event EstateRestartSimRequest OnEstateRestartSimRequest;
210 public event EstateChangeCovenantRequest OnEstateChangeCovenantRequest;
211 public event UpdateEstateAccessDeltaRequest OnUpdateEstateAccessDeltaRequest;
212 public event SimulatorBlueBoxMessageRequest OnSimulatorBlueBoxMessageRequest;
213 public event EstateBlueBoxMessageRequest OnEstateBlueBoxMessageRequest;
214 public event EstateDebugRegionRequest OnEstateDebugRegionRequest;
215 public event EstateTeleportOneUserHomeRequest OnEstateTeleportOneUserHomeRequest;
216 public event EstateTeleportAllUsersHomeRequest OnEstateTeleportAllUsersHomeRequest;
217 public event RegionHandleRequest OnRegionHandleRequest;
218 public event ParcelInfoRequest OnParcelInfoRequest;
219 public event ScriptReset OnScriptReset;
220 public event GetScriptRunning OnGetScriptRunning;
221 public event SetScriptRunning OnSetScriptRunning;
222 public event UpdateVector OnAutoPilotGo;
223 public event TerrainUnacked OnUnackedTerrain;
224 public event ActivateGesture OnActivateGesture;
225 public event DeactivateGesture OnDeactivateGesture;
226 public event ObjectOwner OnObjectOwner;
227 public event DirPlacesQuery OnDirPlacesQuery;
228 public event DirFindQuery OnDirFindQuery;
229 public event DirLandQuery OnDirLandQuery;
230 public event DirPopularQuery OnDirPopularQuery;
231 public event DirClassifiedQuery OnDirClassifiedQuery;
232 public event EventInfoRequest OnEventInfoRequest;
233 public event ParcelSetOtherCleanTime OnParcelSetOtherCleanTime;
234 public event MapItemRequest OnMapItemRequest;
235 public event OfferCallingCard OnOfferCallingCard;
236 public event AcceptCallingCard OnAcceptCallingCard;
237 public event DeclineCallingCard OnDeclineCallingCard;
238 public event SoundTrigger OnSoundTrigger;
239 public event StartLure OnStartLure;
240 public event TeleportLureRequest OnTeleportLureRequest;
241 public event NetworkStats OnNetworkStatsUpdate;
242 public event ClassifiedInfoRequest OnClassifiedInfoRequest;
243 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate;
244 public event ClassifiedDelete OnClassifiedDelete;
245 public event ClassifiedDelete OnClassifiedGodDelete;
246 public event EventNotificationAddRequest OnEventNotificationAddRequest;
247 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest;
248 public event EventGodDelete OnEventGodDelete;
249 public event ParcelDwellRequest OnParcelDwellRequest;
250 public event UserInfoRequest OnUserInfoRequest;
251 public event UpdateUserInfo OnUpdateUserInfo;
252 public event RetrieveInstantMessages OnRetrieveInstantMessages;
253 public event PickDelete OnPickDelete;
254 public event PickGodDelete OnPickGodDelete;
255 public event PickInfoUpdate OnPickInfoUpdate;
256 public event AvatarNotesUpdate OnAvatarNotesUpdate;
257 public event MuteListRequest OnMuteListRequest;
258 public event AvatarInterestUpdate OnAvatarInterestUpdate;
259 public event PlacesQuery OnPlacesQuery;
260
261 #endregion Events
262
263 #region Class Members
264
62 // LLClientView Only 265 // LLClientView Only
63 public delegate void BinaryGenericMessage(Object sender, string method, byte[][] args); 266 public delegate void BinaryGenericMessage(Object sender, string method, byte[][] args);
64 267
@@ -115,13 +318,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
115 protected int m_textureDataLimit = 10; 318 protected int m_textureDataLimit = 10;
116 protected int m_avatarTerseUpdateRate = 50; 319 protected int m_avatarTerseUpdateRate = 50;
117 protected int m_avatarTerseUpdatesPerPacket = 5; 320 protected int m_avatarTerseUpdatesPerPacket = 5;
118 protected int m_packetMTU = 1400;
119 protected IAssetService m_assetService; 321 protected IAssetService m_assetService;
120 private IHyperAssetService m_hyperAssets; 322 private IHyperAssetService m_hyperAssets;
121 323
122 324
325 #endregion Class Members
326
123 #region Properties 327 #region Properties
124 328
329 public LLUDPClient UDPClient { get { return m_udpClient; } }
330 public IPEndPoint RemoteEndPoint { get { return m_udpClient.RemoteEndPoint; } }
125 public UUID SecureSessionId { get { return m_secureSessionId; } } 331 public UUID SecureSessionId { get { return m_secureSessionId; } }
126 public IScene Scene { get { return m_scene; } } 332 public IScene Scene { get { return m_scene; } }
127 public UUID SessionId { get { return m_sessionId; } } 333 public UUID SessionId { get { return m_sessionId; } }
@@ -202,51 +408,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
202 #region Client Methods 408 #region Client Methods
203 409
204 /// <summary> 410 /// <summary>
205 /// Close down the client view. This *must* be the last method called, since the last # 411 /// Shut down the client view
206 /// statement of CloseCleanup() aborts the thread.
207 /// </summary> 412 /// </summary>
208 /// <param name="shutdownCircuit"></param> 413 public void Close()
209 public void Close(bool shutdownCircuit)
210 { 414 {
211 m_log.DebugFormat( 415 m_log.DebugFormat(
212 "[CLIENT]: Close has been called with shutdownCircuit = {0} for {1} attached to scene {2}", 416 "[CLIENT]: Close has been called for {0} attached to scene {1}",
213 shutdownCircuit, Name, m_scene.RegionInfo.RegionName); 417 Name, m_scene.RegionInfo.RegionName);
214 418
419 // Send the STOP packet
420 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator);
421 OutPacket(disable, ThrottleOutPacketType.Unknown);
422
423 IsActive = false;
424
425 // Shutdown the image manager
215 if (m_imageManager != null) 426 if (m_imageManager != null)
216 m_imageManager.Close(); 427 m_imageManager.Close();
217 428
429 // Fire the callback for this connection closing
430 if (OnConnectionClosed != null)
431 OnConnectionClosed(this);
432
433 // Flush all of the packets out of the UDP server for this client
218 if (m_udpServer != null) 434 if (m_udpServer != null)
219 m_udpServer.Flush(); 435 m_udpServer.Flush(m_udpClient);
220
221 // raise an event on the packet server to Shutdown the circuit
222 // Now, if we raise the event then the packet server will call this method itself, so don't try cleanup
223 // here otherwise we'll end up calling it twice.
224 // FIXME: In truth, I might be wrong but this whole business of calling this method twice (with different args) looks
225 // horribly tangly. Hopefully it should be possible to greatly simplify it.
226 if (shutdownCircuit)
227 {
228 if (OnConnectionClosed != null)
229 OnConnectionClosed(this);
230 }
231 else
232 {
233 CloseCleanup(shutdownCircuit);
234 }
235 }
236 436
237 private void CloseCleanup(bool shutdownCircuit) 437 // Remove ourselves from the scene
238 {
239 m_scene.RemoveClient(AgentId); 438 m_scene.RemoveClient(AgentId);
240 439
241 //m_log.InfoFormat("[CLIENTVIEW] Memory pre GC {0}", System.GC.GetTotalMemory(false));
242 //m_log.InfoFormat("[CLIENTVIEW] Memory post GC {0}", System.GC.GetTotalMemory(true));
243
244 // Send the STOP packet
245 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator);
246 OutPacket(disable, ThrottleOutPacketType.Unknown);
247
248 Thread.Sleep(2000);
249
250 // Shut down timers. Thread Context of this method is murky. Lock all timers 440 // Shut down timers. Thread Context of this method is murky. Lock all timers
251 if (m_avatarTerseUpdateTimer.Enabled) 441 if (m_avatarTerseUpdateTimer.Enabled)
252 lock (m_avatarTerseUpdateTimer) 442 lock (m_avatarTerseUpdateTimer)
@@ -258,43 +448,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
258 lock (m_primFullUpdateTimer) 448 lock (m_primFullUpdateTimer)
259 m_primFullUpdateTimer.Stop(); 449 m_primFullUpdateTimer.Stop();
260 450
261 // This is just to give the client a reasonable chance of
262 // flushing out all it's packets. There should probably
263 // be a better mechanism here
264
265 // We can't reach into other scenes and close the connection 451 // We can't reach into other scenes and close the connection
266 // We need to do this over grid communications 452 // We need to do this over grid communications
267 //m_scene.CloseAllAgents(CircuitCode); 453 //m_scene.CloseAllAgents(CircuitCode);
268 454
269 // If we're not shutting down the circuit, then this is the last time we'll go here. 455 m_avatarTerseUpdateTimer.Dispose();
270 // If we are shutting down the circuit, the UDP Server will come back here with 456 m_primTerseUpdateTimer.Dispose();
271 // ShutDownCircuit = false 457 m_primFullUpdateTimer.Dispose();
272 if (!(shutdownCircuit))
273 {
274 GC.Collect();
275 m_imageManager = null;
276 // Sends a KillPacket object, with which, the
277 // blockingqueue dequeues and sees it's a killpacket
278 // and terminates within the context of the client thread.
279 // This ensures that it's done from within the context
280 // of the client thread regardless of where Close() is called.
281 KillEndDone();
282 }
283
284 IsActive = false;
285
286 m_avatarTerseUpdateTimer.Close();
287 m_primTerseUpdateTimer.Close();
288 m_primFullUpdateTimer.Close();
289 458
290 //m_udpServer.OnPacketStats -= PopulateStats; 459 // Disable UDP handling for this client
291 m_udpClient.Shutdown(); 460 m_udpClient.Shutdown();
292 461
293 // wait for thread stoped 462 //m_log.InfoFormat("[CLIENTVIEW] Memory pre GC {0}", System.GC.GetTotalMemory(false));
294 // m_clientThread.Join(); 463 //GC.Collect();
295 464 //m_log.InfoFormat("[CLIENTVIEW] Memory post GC {0}", System.GC.GetTotalMemory(true));
296 // delete circuit code
297 //m_networkServer.CloseClient(this);
298 } 465 }
299 466
300 public void Kick(string message) 467 public void Kick(string message)
@@ -416,43 +583,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
416 return result; 583 return result;
417 } 584 }
418 585
419 /*protected void DebugPacket(string direction, Packet packet)
420 {
421 string info;
422
423 if (m_debugPacketLevel < 255 && packet.Type == PacketType.AgentUpdate)
424 return;
425 if (m_debugPacketLevel < 254 && packet.Type == PacketType.ViewerEffect)
426 return;
427 if (m_debugPacketLevel < 253 && (
428 packet.Type == PacketType.CompletePingCheck ||
429 packet.Type == PacketType.StartPingCheck
430 ))
431 return;
432 if (m_debugPacketLevel < 252 && packet.Type == PacketType.PacketAck)
433 return;
434
435 if (m_debugPacketLevel > 1)
436 {
437 info = packet.ToString();
438 }
439 else
440 {
441 info = packet.Type.ToString();
442 }
443
444 Console.WriteLine(m_circuitCode + ":" + direction + ": " + info);
445 }*/
446
447 #endregion Packet Handling 586 #endregion Packet Handling
448 587
449 # region Setup 588 # region Setup
450 589
451 /// <summary> 590 public virtual void Start()
452 /// Starts up the timers to check the client and resend unacked packets
453 /// Adds the client to the OpenSim.Region.Framework.Scenes.Scene
454 /// </summary>
455 protected virtual void InitNewClient()
456 { 591 {
457 m_avatarTerseUpdateTimer = new Timer(m_avatarTerseUpdateRate); 592 m_avatarTerseUpdateTimer = new Timer(m_avatarTerseUpdateRate);
458 m_avatarTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessAvatarTerseUpdates); 593 m_avatarTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessAvatarTerseUpdates);
@@ -471,262 +606,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
471 RefreshGroupMembership(); 606 RefreshGroupMembership();
472 } 607 }
473 608
474 public virtual void Start()
475 {
476 // This sets up all the timers
477 InitNewClient();
478 }
479
480 /// <summary>
481 /// Run a user session. This method lies at the base of the entire client thread.
482 /// </summary>
483 protected void RunUserSession()
484 {
485 try
486 {
487
488 }
489 catch (Exception e)
490 {
491 if (e is ThreadAbortException)
492 throw;
493
494 if (StatsManager.SimExtraStats != null)
495 StatsManager.SimExtraStats.AddAbnormalClientThreadTermination();
496
497 // Don't let a failure in an individual client thread crash the whole sim.
498 m_log.ErrorFormat(
499 "[CLIENT]: Client thread for {0} {1} crashed. Logging them out.", Name, AgentId);
500 m_log.Error(e.ToString());
501
502 try
503 {
504 // Make an attempt to alert the user that their session has crashed
505 AgentAlertMessagePacket packet
506 = BuildAgentAlertPacket(
507 "Unfortunately the session for this client on the server has crashed.\n"
508 + "Any further actions taken will not be processed.\n"
509 + "Please relog", true);
510
511 m_udpServer.SendPacket(m_agentId, packet, ThrottleOutPacketType.Unknown, false);
512
513 // There may be a better way to do this. Perhaps kick? Not sure this propogates notifications to
514 // listeners yet, though.
515 Logout(this);
516 }
517 catch (Exception e2)
518 {
519 if (e2 is ThreadAbortException)
520 throw;
521
522 m_log.ErrorFormat("[CLIENT]: Further exception thrown on forced session logout. {0}", e2);
523 }
524 }
525 }
526
527 # endregion 609 # endregion
528 610
529 #region Events
530
531 public event GenericMessage OnGenericMessage;
532 public event BinaryGenericMessage OnBinaryGenericMessage;
533 public event Action<IClientAPI> OnLogout;
534 public event ObjectPermissions OnObjectPermissions;
535 public event Action<IClientAPI> OnConnectionClosed;
536 public event ViewerEffectEventHandler OnViewerEffect;
537 public event ImprovedInstantMessage OnInstantMessage;
538 public event ChatMessage OnChatFromClient;
539 public event TextureRequest OnRequestTexture;
540 public event RezObject OnRezObject;
541 public event DeRezObject OnDeRezObject;
542 public event ModifyTerrain OnModifyTerrain;
543 public event Action<IClientAPI> OnRegionHandShakeReply;
544 public event GenericCall2 OnRequestWearables;
545 public event SetAppearance OnSetAppearance;
546 public event AvatarNowWearing OnAvatarNowWearing;
547 public event RezSingleAttachmentFromInv OnRezSingleAttachmentFromInv;
548 public event RezMultipleAttachmentsFromInv OnRezMultipleAttachmentsFromInv;
549 public event UUIDNameRequest OnDetachAttachmentIntoInv;
550 public event ObjectAttach OnObjectAttach;
551 public event ObjectDeselect OnObjectDetach;
552 public event ObjectDrop OnObjectDrop;
553 public event GenericCall2 OnCompleteMovementToRegion;
554 public event UpdateAgent OnAgentUpdate;
555 public event AgentRequestSit OnAgentRequestSit;
556 public event AgentSit OnAgentSit;
557 public event AvatarPickerRequest OnAvatarPickerRequest;
558 public event StartAnim OnStartAnim;
559 public event StopAnim OnStopAnim;
560 public event Action<IClientAPI> OnRequestAvatarsData;
561 public event LinkObjects OnLinkObjects;
562 public event DelinkObjects OnDelinkObjects;
563 public event GrabObject OnGrabObject;
564 public event DeGrabObject OnDeGrabObject;
565 public event SpinStart OnSpinStart;
566 public event SpinStop OnSpinStop;
567 public event ObjectDuplicate OnObjectDuplicate;
568 public event ObjectDuplicateOnRay OnObjectDuplicateOnRay;
569 public event MoveObject OnGrabUpdate;
570 public event SpinObject OnSpinUpdate;
571 public event AddNewPrim OnAddPrim;
572 public event RequestGodlikePowers OnRequestGodlikePowers;
573 public event GodKickUser OnGodKickUser;
574 public event ObjectExtraParams OnUpdateExtraParams;
575 public event UpdateShape OnUpdatePrimShape;
576 public event ObjectRequest OnObjectRequest;
577 public event ObjectSelect OnObjectSelect;
578 public event ObjectDeselect OnObjectDeselect;
579 public event GenericCall7 OnObjectDescription;
580 public event GenericCall7 OnObjectName;
581 public event GenericCall7 OnObjectClickAction;
582 public event GenericCall7 OnObjectMaterial;
583 public event ObjectIncludeInSearch OnObjectIncludeInSearch;
584 public event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily;
585 public event UpdatePrimFlags OnUpdatePrimFlags;
586 public event UpdatePrimTexture OnUpdatePrimTexture;
587 public event UpdateVector OnUpdatePrimGroupPosition;
588 public event UpdateVector OnUpdatePrimSinglePosition;
589 public event UpdatePrimRotation OnUpdatePrimGroupRotation;
590 public event UpdatePrimSingleRotation OnUpdatePrimSingleRotation;
591 public event UpdatePrimSingleRotationPosition OnUpdatePrimSingleRotationPosition;
592 public event UpdatePrimGroupRotation OnUpdatePrimGroupMouseRotation;
593 public event UpdateVector OnUpdatePrimScale;
594 public event UpdateVector OnUpdatePrimGroupScale;
595 public event StatusChange OnChildAgentStatus;
596 public event GenericCall2 OnStopMovement;
597 public event Action<UUID> OnRemoveAvatar;
598 public event RequestMapBlocks OnRequestMapBlocks;
599 public event RequestMapName OnMapNameRequest;
600 public event TeleportLocationRequest OnTeleportLocationRequest;
601 public event TeleportLandmarkRequest OnTeleportLandmarkRequest;
602 public event DisconnectUser OnDisconnectUser;
603 public event RequestAvatarProperties OnRequestAvatarProperties;
604 public event SetAlwaysRun OnSetAlwaysRun;
605 public event FetchInventory OnAgentDataUpdateRequest;
606 public event TeleportLocationRequest OnSetStartLocationRequest;
607 public event UpdateAvatarProperties OnUpdateAvatarProperties;
608 public event CreateNewInventoryItem OnCreateNewInventoryItem;
609 public event CreateInventoryFolder OnCreateNewInventoryFolder;
610 public event UpdateInventoryFolder OnUpdateInventoryFolder;
611 public event MoveInventoryFolder OnMoveInventoryFolder;
612 public event FetchInventoryDescendents OnFetchInventoryDescendents;
613 public event PurgeInventoryDescendents OnPurgeInventoryDescendents;
614 public event FetchInventory OnFetchInventory;
615 public event RequestTaskInventory OnRequestTaskInventory;
616 public event UpdateInventoryItem OnUpdateInventoryItem;
617 public event CopyInventoryItem OnCopyInventoryItem;
618 public event MoveInventoryItem OnMoveInventoryItem;
619 public event RemoveInventoryItem OnRemoveInventoryItem;
620 public event RemoveInventoryFolder OnRemoveInventoryFolder;
621 public event UDPAssetUploadRequest OnAssetUploadRequest;
622 public event XferReceive OnXferReceive;
623 public event RequestXfer OnRequestXfer;
624 public event ConfirmXfer OnConfirmXfer;
625 public event AbortXfer OnAbortXfer;
626 public event RequestTerrain OnRequestTerrain;
627 public event RezScript OnRezScript;
628 public event UpdateTaskInventory OnUpdateTaskInventory;
629 public event MoveTaskInventory OnMoveTaskItem;
630 public event RemoveTaskInventory OnRemoveTaskItem;
631 public event RequestAsset OnRequestAsset;
632 public event UUIDNameRequest OnNameFromUUIDRequest;
633 public event ParcelAccessListRequest OnParcelAccessListRequest;
634 public event ParcelAccessListUpdateRequest OnParcelAccessListUpdateRequest;
635 public event ParcelPropertiesRequest OnParcelPropertiesRequest;
636 public event ParcelDivideRequest OnParcelDivideRequest;
637 public event ParcelJoinRequest OnParcelJoinRequest;
638 public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest;
639 public event ParcelSelectObjects OnParcelSelectObjects;
640 public event ParcelObjectOwnerRequest OnParcelObjectOwnerRequest;
641 public event ParcelAbandonRequest OnParcelAbandonRequest;
642 public event ParcelGodForceOwner OnParcelGodForceOwner;
643 public event ParcelReclaim OnParcelReclaim;
644 public event ParcelReturnObjectsRequest OnParcelReturnObjectsRequest;
645 public event ParcelDeedToGroup OnParcelDeedToGroup;
646 public event RegionInfoRequest OnRegionInfoRequest;
647 public event EstateCovenantRequest OnEstateCovenantRequest;
648 public event FriendActionDelegate OnApproveFriendRequest;
649 public event FriendActionDelegate OnDenyFriendRequest;
650 public event FriendshipTermination OnTerminateFriendship;
651 public event MoneyTransferRequest OnMoneyTransferRequest;
652 public event EconomyDataRequest OnEconomyDataRequest;
653 public event MoneyBalanceRequest OnMoneyBalanceRequest;
654 public event ParcelBuy OnParcelBuy;
655 public event UUIDNameRequest OnTeleportHomeRequest;
656 public event UUIDNameRequest OnUUIDGroupNameRequest;
657 public event ScriptAnswer OnScriptAnswer;
658 public event RequestPayPrice OnRequestPayPrice;
659 public event ObjectSaleInfo OnObjectSaleInfo;
660 public event ObjectBuy OnObjectBuy;
661 public event BuyObjectInventory OnBuyObjectInventory;
662 public event AgentSit OnUndo;
663 public event ForceReleaseControls OnForceReleaseControls;
664 public event GodLandStatRequest OnLandStatRequest;
665 public event RequestObjectPropertiesFamily OnObjectGroupRequest;
666 public event DetailedEstateDataRequest OnDetailedEstateDataRequest;
667 public event SetEstateFlagsRequest OnSetEstateFlagsRequest;
668 public event SetEstateTerrainBaseTexture OnSetEstateTerrainBaseTexture;
669 public event SetEstateTerrainDetailTexture OnSetEstateTerrainDetailTexture;
670 public event SetEstateTerrainTextureHeights OnSetEstateTerrainTextureHeights;
671 public event CommitEstateTerrainTextureRequest OnCommitEstateTerrainTextureRequest;
672 public event SetRegionTerrainSettings OnSetRegionTerrainSettings;
673 public event BakeTerrain OnBakeTerrain;
674 public event RequestTerrain OnUploadTerrain;
675 public event EstateChangeInfo OnEstateChangeInfo;
676 public event EstateRestartSimRequest OnEstateRestartSimRequest;
677 public event EstateChangeCovenantRequest OnEstateChangeCovenantRequest;
678 public event UpdateEstateAccessDeltaRequest OnUpdateEstateAccessDeltaRequest;
679 public event SimulatorBlueBoxMessageRequest OnSimulatorBlueBoxMessageRequest;
680 public event EstateBlueBoxMessageRequest OnEstateBlueBoxMessageRequest;
681 public event EstateDebugRegionRequest OnEstateDebugRegionRequest;
682 public event EstateTeleportOneUserHomeRequest OnEstateTeleportOneUserHomeRequest;
683 public event EstateTeleportAllUsersHomeRequest OnEstateTeleportAllUsersHomeRequest;
684 public event RegionHandleRequest OnRegionHandleRequest;
685 public event ParcelInfoRequest OnParcelInfoRequest;
686 public event ScriptReset OnScriptReset;
687 public event GetScriptRunning OnGetScriptRunning;
688 public event SetScriptRunning OnSetScriptRunning;
689 public event UpdateVector OnAutoPilotGo;
690 public event TerrainUnacked OnUnackedTerrain;
691 public event ActivateGesture OnActivateGesture;
692 public event DeactivateGesture OnDeactivateGesture;
693 public event ObjectOwner OnObjectOwner;
694 public event DirPlacesQuery OnDirPlacesQuery;
695 public event DirFindQuery OnDirFindQuery;
696 public event DirLandQuery OnDirLandQuery;
697 public event DirPopularQuery OnDirPopularQuery;
698 public event DirClassifiedQuery OnDirClassifiedQuery;
699 public event EventInfoRequest OnEventInfoRequest;
700 public event ParcelSetOtherCleanTime OnParcelSetOtherCleanTime;
701 public event MapItemRequest OnMapItemRequest;
702 public event OfferCallingCard OnOfferCallingCard;
703 public event AcceptCallingCard OnAcceptCallingCard;
704 public event DeclineCallingCard OnDeclineCallingCard;
705 public event SoundTrigger OnSoundTrigger;
706 public event StartLure OnStartLure;
707 public event TeleportLureRequest OnTeleportLureRequest;
708 public event NetworkStats OnNetworkStatsUpdate;
709 public event ClassifiedInfoRequest OnClassifiedInfoRequest;
710 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate;
711 public event ClassifiedDelete OnClassifiedDelete;
712 public event ClassifiedDelete OnClassifiedGodDelete;
713 public event EventNotificationAddRequest OnEventNotificationAddRequest;
714 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest;
715 public event EventGodDelete OnEventGodDelete;
716 public event ParcelDwellRequest OnParcelDwellRequest;
717 public event UserInfoRequest OnUserInfoRequest;
718 public event UpdateUserInfo OnUpdateUserInfo;
719 public event RetrieveInstantMessages OnRetrieveInstantMessages;
720 public event PickDelete OnPickDelete;
721 public event PickGodDelete OnPickGodDelete;
722 public event PickInfoUpdate OnPickInfoUpdate;
723 public event AvatarNotesUpdate OnAvatarNotesUpdate;
724 public event MuteListRequest OnMuteListRequest;
725 public event AvatarInterestUpdate OnAvatarInterestUpdate;
726 public event PlacesQuery OnPlacesQuery;
727
728 #endregion Events
729
730 public void ActivateGesture(UUID assetId, UUID gestureId) 611 public void ActivateGesture(UUID assetId, UUID gestureId)
731 { 612 {
732 } 613 }
@@ -1346,7 +1227,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1346 kill.ObjectData[0].ID = localID; 1227 kill.ObjectData[0].ID = localID;
1347 kill.Header.Reliable = true; 1228 kill.Header.Reliable = true;
1348 kill.Header.Zerocoded = true; 1229 kill.Header.Zerocoded = true;
1349 OutPacket(kill, ThrottleOutPacketType.Task); 1230 OutPacket(kill, ThrottleOutPacketType.State);
1350 } 1231 }
1351 1232
1352 /// <summary> 1233 /// <summary>
@@ -1940,7 +1821,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1940 sendXfer.XferID.ID = xferID; 1821 sendXfer.XferID.ID = xferID;
1941 sendXfer.XferID.Packet = packet; 1822 sendXfer.XferID.Packet = packet;
1942 sendXfer.DataPacket.Data = data; 1823 sendXfer.DataPacket.Data = data;
1943 OutPacket(sendXfer, ThrottleOutPacketType.Task); 1824 OutPacket(sendXfer, ThrottleOutPacketType.Asset);
1944 } 1825 }
1945 1826
1946 public void SendEconomyData(float EnergyEfficiency, int ObjectCapacity, int ObjectCount, int PriceEnergyUnit, 1827 public void SendEconomyData(float EnergyEfficiency, int ObjectCapacity, int ObjectCount, int PriceEnergyUnit,
@@ -2222,7 +2103,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2222 packet.AgentData.SessionID = SessionId; 2103 packet.AgentData.SessionID = SessionId;
2223 packet.Header.Reliable = false; 2104 packet.Header.Reliable = false;
2224 packet.Header.Zerocoded = true; 2105 packet.Header.Zerocoded = true;
2225 OutPacket(packet, ThrottleOutPacketType.Task); 2106 OutPacket(packet, ThrottleOutPacketType.State);
2226 } 2107 }
2227 2108
2228 public void SendAvatarProperties(UUID avatarID, string aboutText, string bornOn, Byte[] charterMember, 2109 public void SendAvatarProperties(UUID avatarID, string aboutText, string bornOn, Byte[] charterMember,
@@ -3245,7 +3126,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3245 3126
3246 avp.Sender.IsTrial = false; 3127 avp.Sender.IsTrial = false;
3247 avp.Sender.ID = agentID; 3128 avp.Sender.ID = agentID;
3248 OutPacket(avp, ThrottleOutPacketType.Task); 3129 OutPacket(avp, ThrottleOutPacketType.State);
3249 } 3130 }
3250 3131
3251 public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs) 3132 public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs)
@@ -3370,7 +3251,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3370 int length = 0; 3251 int length = 0;
3371 m_avatarTerseUpdates[count].ToBytes(blockbuffer, ref length); 3252 m_avatarTerseUpdates[count].ToBytes(blockbuffer, ref length);
3372 length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); 3253 length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer);
3373 if (size + length > m_packetMTU) 3254 if (size + length > Packet.MTU)
3374 break; 3255 break;
3375 size += length; 3256 size += length;
3376 } 3257 }
@@ -3385,6 +3266,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3385 3266
3386 terse.Header.Reliable = false; 3267 terse.Header.Reliable = false;
3387 terse.Header.Zerocoded = true; 3268 terse.Header.Zerocoded = true;
3269 // FIXME: Move this to ThrottleOutPacketType.State when the real prioritization code is committed
3388 OutPacket(terse, ThrottleOutPacketType.Task); 3270 OutPacket(terse, ThrottleOutPacketType.Task);
3389 3271
3390 if (m_avatarTerseUpdates.Count == 0) 3272 if (m_avatarTerseUpdates.Count == 0)
@@ -3614,7 +3496,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3614 int length = 0; 3496 int length = 0;
3615 m_primFullUpdates[count].ToBytes(blockbuffer, ref length); 3497 m_primFullUpdates[count].ToBytes(blockbuffer, ref length);
3616 length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); 3498 length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer);
3617 if (size + length > m_packetMTU) 3499 if (size + length > Packet.MTU)
3618 break; 3500 break;
3619 size += length; 3501 size += length;
3620 } 3502 }
@@ -3629,7 +3511,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3629 } 3511 }
3630 3512
3631 outPacket.Header.Zerocoded = true; 3513 outPacket.Header.Zerocoded = true;
3632 OutPacket(outPacket, ThrottleOutPacketType.Task); 3514 OutPacket(outPacket, ThrottleOutPacketType.State);
3633 3515
3634 if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled) 3516 if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled)
3635 lock (m_primFullUpdateTimer) 3517 lock (m_primFullUpdateTimer)
@@ -3702,7 +3584,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3702 int length = 0; 3584 int length = 0;
3703 m_primTerseUpdates[count].ToBytes(blockbuffer, ref length); 3585 m_primTerseUpdates[count].ToBytes(blockbuffer, ref length);
3704 length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); 3586 length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer);
3705 if (size + length > m_packetMTU) 3587 if (size + length > Packet.MTU)
3706 break; 3588 break;
3707 size += length; 3589 size += length;
3708 } 3590 }
@@ -3719,7 +3601,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3719 3601
3720 outPacket.Header.Reliable = false; 3602 outPacket.Header.Reliable = false;
3721 outPacket.Header.Zerocoded = true; 3603 outPacket.Header.Zerocoded = true;
3722 OutPacket(outPacket, ThrottleOutPacketType.Task); 3604 OutPacket(outPacket, ThrottleOutPacketType.State);
3723 3605
3724 if (m_primTerseUpdates.Count == 0) 3606 if (m_primTerseUpdates.Count == 0)
3725 lock (m_primTerseUpdateTimer) 3607 lock (m_primTerseUpdateTimer)
@@ -4805,7 +4687,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4805 4687
4806 public bool HandleObjectGroupRequest(IClientAPI sender, Packet Pack) 4688 public bool HandleObjectGroupRequest(IClientAPI sender, Packet Pack)
4807 { 4689 {
4808
4809 ObjectGroupPacket ogpack = (ObjectGroupPacket)Pack; 4690 ObjectGroupPacket ogpack = (ObjectGroupPacket)Pack;
4810 if (ogpack.AgentData.SessionID != SessionId) return false; 4691 if (ogpack.AgentData.SessionID != SessionId) return false;
4811 4692
@@ -10252,7 +10133,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10252 10133
10253 public void KillEndDone() 10134 public void KillEndDone()
10254 { 10135 {
10255 m_udpClient.Shutdown();
10256 } 10136 }
10257 10137
10258 #region IClientCore 10138 #region IClientCore
@@ -10295,15 +10175,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10295 { 10175 {
10296 Kick(reason); 10176 Kick(reason);
10297 Thread.Sleep(1000); 10177 Thread.Sleep(1000);
10298 Close(true); 10178 Close();
10299 } 10179 }
10300 10180
10301 public void Disconnect() 10181 public void Disconnect()
10302 { 10182 {
10303 Close(true); 10183 Close();
10304 } 10184 }
10305 10185
10306
10307 #endregion 10186 #endregion
10308 10187
10309 public void RefreshGroupMembership() 10188 public void RefreshGroupMembership()
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs b/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs
index 56d34e6..681562b 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs
@@ -172,39 +172,39 @@ namespace OpenSim.Region.ClientStack.LindenUDP
172 J2KImage imagereq; 172 J2KImage imagereq;
173 int numCollected = 0; 173 int numCollected = 0;
174 174
175 //lock (m_syncRoot) 175 m_lastloopprocessed = DateTime.Now.Ticks;
176 //{ 176
177 m_lastloopprocessed = DateTime.Now.Ticks; 177 // This can happen during Close()
178 178 if (m_client == null)
179 // This can happen during Close() 179 return false;
180 if (m_client == null) 180
181 return false; 181 while ((imagereq = GetHighestPriorityImage()) != null)
182 182 {
183 while ((imagereq = GetHighestPriorityImage()) != null) 183 if (imagereq.IsDecoded == true)
184 { 184 {
185 if (imagereq.IsDecoded == true) 185 ++numCollected;
186 {
187 ++numCollected;
188 186
189 if (imagereq.SendPackets(m_client, maxpack)) 187 if (imagereq.SendPackets(m_client, maxpack))
190 { 188 {
191 // Send complete. Destroy any knowledge of this transfer 189 // Send complete. Destroy any knowledge of this transfer
192 RemoveImageFromQueue(imagereq); 190 RemoveImageFromQueue(imagereq);
193 }
194 } 191 }
195
196 if (numCollected == count)
197 break;
198 } 192 }
199 //} 193
194 if (numCollected == count)
195 break;
196 }
200 197
201 return m_priorityQueue.Count > 0; 198 return m_priorityQueue.Count > 0;
202 } 199 }
203 200
204 //Faux destructor 201 /// <summary>
202 /// Faux destructor
203 /// </summary>
205 public void Close() 204 public void Close()
206 { 205 {
207 m_shuttingdown = true; 206 m_shuttingdown = true;
207 m_priorityQueue = null;
208 m_j2kDecodeModule = null; 208 m_j2kDecodeModule = null;
209 m_assetCache = null; 209 m_assetCache = null;
210 m_client = null; 210 m_client = null;
@@ -218,13 +218,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
218 218
219 lock (m_syncRoot) 219 lock (m_syncRoot)
220 { 220 {
221
222 if (m_priorityQueue.Count > 0) 221 if (m_priorityQueue.Count > 0)
223 { 222 {
224 try 223 try { image = m_priorityQueue.FindMax(); }
225 {
226 image = m_priorityQueue.FindMax();
227 }
228 catch (Exception) { } 224 catch (Exception) { }
229 } 225 }
230 } 226 }
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index 871e8e8..e7707a9 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
@@ -59,9 +59,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
59 /// </summary> 59 /// </summary>
60 public sealed class LLUDPClient 60 public sealed class LLUDPClient
61 { 61 {
62 // FIXME: Make this a config setting
63 /// <summary>Percentage of the task throttle category that is allocated to avatar and prim
64 /// state updates</summary>
65 const float STATE_TASK_PERCENTAGE = 0.8f;
66
62 /// <summary>The number of packet categories to throttle on. If a throttle category is added 67 /// <summary>The number of packet categories to throttle on. If a throttle category is added
63 /// or removed, this number must also change</summary> 68 /// or removed, this number must also change</summary>
64 const int THROTTLE_CATEGORY_COUNT = 7; 69 const int THROTTLE_CATEGORY_COUNT = 8;
65 70
66 /// <summary>Fired when updated networking stats are produced for this client</summary> 71 /// <summary>Fired when updated networking stats are produced for this client</summary>
67 public event PacketStats OnPacketStats; 72 public event PacketStats OnPacketStats;
@@ -80,10 +85,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
80 /// <summary>Packets we have sent that need to be ACKed by the client</summary> 85 /// <summary>Packets we have sent that need to be ACKed by the client</summary>
81 public readonly UnackedPacketCollection NeedAcks = new UnackedPacketCollection(); 86 public readonly UnackedPacketCollection NeedAcks = new UnackedPacketCollection();
82 /// <summary>ACKs that are queued up, waiting to be sent to the client</summary> 87 /// <summary>ACKs that are queued up, waiting to be sent to the client</summary>
83 public readonly LocklessQueue<uint> PendingAcks = new LocklessQueue<uint>(); 88 public readonly OpenSim.Framework.LocklessQueue<uint> PendingAcks = new OpenSim.Framework.LocklessQueue<uint>();
84 89
85 /// <summary>Reference to the IClientAPI for this client</summary>
86 public LLClientView ClientAPI;
87 /// <summary>Current packet sequence number</summary> 90 /// <summary>Current packet sequence number</summary>
88 public int CurrentSequence; 91 public int CurrentSequence;
89 /// <summary>Current ping sequence number</summary> 92 /// <summary>Current ping sequence number</summary>
@@ -129,7 +132,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
129 /// <summary>Throttle rate defaults and limits</summary> 132 /// <summary>Throttle rate defaults and limits</summary>
130 private readonly ThrottleRates defaultThrottleRates; 133 private readonly ThrottleRates defaultThrottleRates;
131 /// <summary>Outgoing queues for throttled packets</summary> 134 /// <summary>Outgoing queues for throttled packets</summary>
132 private readonly LocklessQueue<OutgoingPacket>[] packetOutboxes = new LocklessQueue<OutgoingPacket>[THROTTLE_CATEGORY_COUNT]; 135 private readonly OpenSim.Framework.LocklessQueue<OutgoingPacket>[] packetOutboxes = new OpenSim.Framework.LocklessQueue<OutgoingPacket>[THROTTLE_CATEGORY_COUNT];
133 /// <summary>A container that can hold one packet for each outbox, used to store 136 /// <summary>A container that can hold one packet for each outbox, used to store
134 /// dequeued packets that are being held for throttling</summary> 137 /// dequeued packets that are being held for throttling</summary>
135 private readonly OutgoingPacket[] nextPackets = new OutgoingPacket[THROTTLE_CATEGORY_COUNT]; 138 private readonly OutgoingPacket[] nextPackets = new OutgoingPacket[THROTTLE_CATEGORY_COUNT];
@@ -158,7 +161,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
158 defaultThrottleRates = rates; 161 defaultThrottleRates = rates;
159 162
160 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) 163 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
161 packetOutboxes[i] = new LocklessQueue<OutgoingPacket>(); 164 packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>();
162 165
163 throttle = new TokenBucket(parentThrottle, 0, 0); 166 throttle = new TokenBucket(parentThrottle, 0, 0);
164 throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; 167 throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT];
@@ -166,9 +169,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
166 throttleCategories[(int)ThrottleOutPacketType.Land] = new TokenBucket(throttle, rates.LandLimit, rates.Land); 169 throttleCategories[(int)ThrottleOutPacketType.Land] = new TokenBucket(throttle, rates.LandLimit, rates.Land);
167 throttleCategories[(int)ThrottleOutPacketType.Wind] = new TokenBucket(throttle, rates.WindLimit, rates.Wind); 170 throttleCategories[(int)ThrottleOutPacketType.Wind] = new TokenBucket(throttle, rates.WindLimit, rates.Wind);
168 throttleCategories[(int)ThrottleOutPacketType.Cloud] = new TokenBucket(throttle, rates.CloudLimit, rates.Cloud); 171 throttleCategories[(int)ThrottleOutPacketType.Cloud] = new TokenBucket(throttle, rates.CloudLimit, rates.Cloud);
169 throttleCategories[(int)ThrottleOutPacketType.Task] = new TokenBucket(throttle, rates.TaskLimit, rates.Task);
170 throttleCategories[(int)ThrottleOutPacketType.Texture] = new TokenBucket(throttle, rates.TextureLimit, rates.Texture); 172 throttleCategories[(int)ThrottleOutPacketType.Texture] = new TokenBucket(throttle, rates.TextureLimit, rates.Texture);
171 throttleCategories[(int)ThrottleOutPacketType.Asset] = new TokenBucket(throttle, rates.AssetLimit, rates.Asset); 173 throttleCategories[(int)ThrottleOutPacketType.Asset] = new TokenBucket(throttle, rates.AssetLimit, rates.Asset);
174 // State and Transaction are actually sub-categories of the LLUDP generic "Task" category
175 TokenBucket stateBucket = new TokenBucket(throttle, (int)((float)rates.TaskLimit * STATE_TASK_PERCENTAGE), (int)((float)rates.Task * STATE_TASK_PERCENTAGE));
176 throttleCategories[(int)ThrottleOutPacketType.State] = stateBucket;
177 throttleCategories[(int)ThrottleOutPacketType.Task] = new TokenBucket(throttle, rates.TaskLimit - stateBucket.MaxBurst, rates.Task - stateBucket.DripRate);
172 178
173 // Set the granularity variable used for retransmission calculations to 179 // Set the granularity variable used for retransmission calculations to
174 // the measured resolution of Environment.TickCount 180 // the measured resolution of Environment.TickCount
@@ -176,6 +182,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
176 182
177 // Default the retransmission timeout to three seconds 183 // Default the retransmission timeout to three seconds
178 RTO = 3000; 184 RTO = 3000;
185
186 // Initialize this to a sane value to prevent early disconnects
187 TickLastPacketReceived = Environment.TickCount;
179 } 188 }
180 189
181 /// <summary> 190 /// <summary>
@@ -183,8 +192,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
183 /// </summary> 192 /// </summary>
184 public void Shutdown() 193 public void Shutdown()
185 { 194 {
186 // TODO: Do we need to invalidate the circuit?
187 IsConnected = false; 195 IsConnected = false;
196 NeedAcks.Clear();
197 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
198 {
199 packetOutboxes[i].Clear();
200 nextPackets[i] = null;
201 }
202 OnPacketStats = null;
203 OnQueueEmpty = null;
188 } 204 }
189 205
190 /// <summary> 206 /// <summary>
@@ -204,7 +220,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
204 info.landThrottle = throttleCategories[(int)ThrottleOutPacketType.Land].DripRate; 220 info.landThrottle = throttleCategories[(int)ThrottleOutPacketType.Land].DripRate;
205 info.windThrottle = throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate; 221 info.windThrottle = throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate;
206 info.cloudThrottle = throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate; 222 info.cloudThrottle = throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate;
207 info.taskThrottle = throttleCategories[(int)ThrottleOutPacketType.Task].DripRate; 223 info.taskThrottle = throttleCategories[(int)ThrottleOutPacketType.State].DripRate + throttleCategories[(int)ThrottleOutPacketType.Task].DripRate;
208 info.assetThrottle = throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate; 224 info.assetThrottle = throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate;
209 info.textureThrottle = throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate; 225 info.textureThrottle = throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate;
210 info.totalThrottle = info.resendThrottle + info.landThrottle + info.windThrottle + info.cloudThrottle + 226 info.totalThrottle = info.resendThrottle + info.landThrottle + info.windThrottle + info.cloudThrottle +
@@ -301,7 +317,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
301 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Land].DripRate), 0, data, i, 4); i += 4; 317 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Land].DripRate), 0, data, i, 4); i += 4;
302 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate), 0, data, i, 4); i += 4; 318 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate), 0, data, i, 4); i += 4;
303 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate), 0, data, i, 4); i += 4; 319 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate), 0, data, i, 4); i += 4;
304 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Task].DripRate), 0, data, i, 4); i += 4; 320 Buffer.BlockCopy(Utils.FloatToBytes((float)(throttleCategories[(int)ThrottleOutPacketType.Task].DripRate) +
321 throttleCategories[(int)ThrottleOutPacketType.State].DripRate), 0, data, i, 4); i += 4;
305 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate), 0, data, i, 4); i += 4; 322 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate), 0, data, i, 4); i += 4;
306 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate), 0, data, i, 4); i += 4; 323 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate), 0, data, i, 4); i += 4;
307 324
@@ -310,12 +327,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
310 327
311 public void SetThrottle(ThrottleOutPacketType category, int rate) 328 public void SetThrottle(ThrottleOutPacketType category, int rate)
312 { 329 {
313 int i = (int)category; 330 if (category == ThrottleOutPacketType.Task)
314 if (i >= 0 && i < throttleCategories.Length)
315 { 331 {
316 TokenBucket bucket = throttleCategories[(int)category]; 332 TokenBucket stateBucket = throttleCategories[(int)ThrottleOutPacketType.State];
317 bucket.MaxBurst = rate; 333 TokenBucket taskBucket = throttleCategories[(int)ThrottleOutPacketType.Task];
318 bucket.DripRate = rate; 334
335 stateBucket.MaxBurst = (int)((float)rate * STATE_TASK_PERCENTAGE);
336 stateBucket.DripRate = (int)((float)rate * STATE_TASK_PERCENTAGE);
337
338 taskBucket.MaxBurst = rate - stateBucket.MaxBurst;
339 taskBucket.DripRate = rate - stateBucket.DripRate;
340 }
341 else
342 {
343 int i = (int)category;
344 if (i >= 0 && i < throttleCategories.Length)
345 {
346 TokenBucket bucket = throttleCategories[(int)category];
347 bucket.MaxBurst = rate;
348 bucket.DripRate = rate;
349 }
319 } 350 }
320 } 351 }
321 352
@@ -325,7 +356,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
325 356
326 if (category >= 0 && category < packetOutboxes.Length) 357 if (category >= 0 && category < packetOutboxes.Length)
327 { 358 {
328 LocklessQueue<OutgoingPacket> queue = packetOutboxes[category]; 359 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = packetOutboxes[category];
329 TokenBucket bucket = throttleCategories[category]; 360 TokenBucket bucket = throttleCategories[category];
330 361
331 if (throttleCategories[category].RemoveTokens(packet.Buffer.DataLength)) 362 if (throttleCategories[category].RemoveTokens(packet.Buffer.DataLength))
@@ -357,7 +388,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
357 public bool DequeueOutgoing() 388 public bool DequeueOutgoing()
358 { 389 {
359 OutgoingPacket packet; 390 OutgoingPacket packet;
360 LocklessQueue<OutgoingPacket> queue; 391 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue;
361 TokenBucket bucket; 392 TokenBucket bucket;
362 bool packetSent = false; 393 bool packetSent = false;
363 394
@@ -400,13 +431,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
400 nextPackets[i] = packet; 431 nextPackets[i] = packet;
401 nextPacketLengths[i] = packet.Buffer.DataLength; 432 nextPacketLengths[i] = packet.Buffer.DataLength;
402 } 433 }
434
435 // If the queue is empty after this dequeue, fire the queue
436 // empty callback now so it has a chance to fill before we
437 // get back here
438 if (queue.Count == 0)
439 FireQueueEmpty(i);
403 } 440 }
404 else 441 else
405 { 442 {
406 // No packets in this queue. Fire the queue empty callback 443 // No packets in this queue. Fire the queue empty callback
407 QueueEmpty callback = OnQueueEmpty; 444 // if it has not been called recently
408 if (callback != null) 445 FireQueueEmpty(i);
409 callback((ThrottleOutPacketType)i);
410 } 446 }
411 } 447 }
412 } 448 }
@@ -435,8 +471,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
435 471
436 // Always round retransmission timeout up to two seconds 472 // Always round retransmission timeout up to two seconds
437 RTO = Math.Max(2000, (int)(SRTT + Math.Max(G, K * RTTVAR))); 473 RTO = Math.Max(2000, (int)(SRTT + Math.Max(G, K * RTTVAR)));
438 //Logger.Debug("Setting agent " + this.Agent.FullName + "'s RTO to " + RTO + "ms with an RTTVAR of " + 474 //m_log.Debug("[LLUDPCLIENT]: Setting agent " + this.Agent.FullName + "'s RTO to " + RTO + "ms with an RTTVAR of " +
439 // RTTVAR + " based on new RTT of " + r + "ms"); 475 // RTTVAR + " based on new RTT of " + r + "ms");
440 } 476 }
477
478 private void FireQueueEmpty(int queueIndex)
479 {
480 QueueEmpty callback = OnQueueEmpty;
481 if (callback != null)
482 Util.FireAndForget(delegate(object o) { callback((ThrottleOutPacketType)(int)o); }, queueIndex);
483 }
441 } 484 }
442} 485}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs
deleted file mode 100644
index dbb9861..0000000
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs
+++ /dev/null
@@ -1,282 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Net;
31using OpenSim.Framework;
32using OpenMetaverse;
33
34using ReaderWriterLockImpl = OpenMetaverse.ReaderWriterLockSlim;
35
36namespace OpenSim.Region.ClientStack.LindenUDP
37{
38 public sealed class UDPClientCollection
39 {
40 Dictionary<UUID, LLUDPClient> Dictionary1;
41 Dictionary<IPEndPoint, LLUDPClient> Dictionary2;
42 LLUDPClient[] Array;
43 ReaderWriterLockImpl rwLock = new ReaderWriterLockImpl();
44 object m_sync = new object();
45
46 public UDPClientCollection()
47 {
48 Dictionary1 = new Dictionary<UUID, LLUDPClient>();
49 Dictionary2 = new Dictionary<IPEndPoint, LLUDPClient>();
50 Array = new LLUDPClient[0];
51 }
52
53 public UDPClientCollection(int capacity)
54 {
55 Dictionary1 = new Dictionary<UUID, LLUDPClient>(capacity);
56 Dictionary2 = new Dictionary<IPEndPoint, LLUDPClient>(capacity);
57 Array = new LLUDPClient[0];
58 }
59
60 public void Add(UUID key1, IPEndPoint key2, LLUDPClient value)
61 {
62 //rwLock.EnterWriteLock();
63
64 //try
65 //{
66 // if (Dictionary1.ContainsKey(key1))
67 // {
68 // if (!Dictionary2.ContainsKey(key2))
69 // throw new ArgumentException("key1 exists in the dictionary but not key2");
70 // }
71 // else if (Dictionary2.ContainsKey(key2))
72 // {
73 // if (!Dictionary1.ContainsKey(key1))
74 // throw new ArgumentException("key2 exists in the dictionary but not key1");
75 // }
76
77 // Dictionary1[key1] = value;
78 // Dictionary2[key2] = value;
79
80 // LLUDPClient[] oldArray = Array;
81 // int oldLength = oldArray.Length;
82
83 // LLUDPClient[] newArray = new LLUDPClient[oldLength + 1];
84 // for (int i = 0; i < oldLength; i++)
85 // newArray[i] = oldArray[i];
86 // newArray[oldLength] = value;
87
88 // Array = newArray;
89 //}
90 //finally { rwLock.ExitWriteLock(); }
91
92 lock (m_sync)
93 {
94 if (Dictionary1.ContainsKey(key1))
95 {
96 if (!Dictionary2.ContainsKey(key2))
97 throw new ArgumentException("key1 exists in the dictionary but not key2");
98 }
99 else if (Dictionary2.ContainsKey(key2))
100 {
101 if (!Dictionary1.ContainsKey(key1))
102 throw new ArgumentException("key2 exists in the dictionary but not key1");
103 }
104
105 Dictionary1[key1] = value;
106 Dictionary2[key2] = value;
107
108 LLUDPClient[] oldArray = Array;
109 int oldLength = oldArray.Length;
110
111 LLUDPClient[] newArray = new LLUDPClient[oldLength + 1];
112 for (int i = 0; i < oldLength; i++)
113 newArray[i] = oldArray[i];
114 newArray[oldLength] = value;
115
116 Array = newArray;
117 }
118
119 }
120
121 public bool Remove(UUID key1, IPEndPoint key2)
122 {
123 //rwLock.EnterWriteLock();
124
125 //try
126 //{
127 // LLUDPClient value;
128 // if (Dictionary1.TryGetValue(key1, out value))
129 // {
130 // Dictionary1.Remove(key1);
131 // Dictionary2.Remove(key2);
132
133 // LLUDPClient[] oldArray = Array;
134 // int oldLength = oldArray.Length;
135
136 // LLUDPClient[] newArray = new LLUDPClient[oldLength - 1];
137 // int j = 0;
138 // for (int i = 0; i < oldLength; i++)
139 // {
140 // if (oldArray[i] != value)
141 // newArray[j++] = oldArray[i];
142 // }
143
144 // Array = newArray;
145 // return true;
146 // }
147 //}
148 //finally { rwLock.ExitWriteLock(); }
149
150 //return false;
151
152 lock (m_sync)
153 {
154 LLUDPClient value;
155 if (Dictionary1.TryGetValue(key1, out value))
156 {
157 Dictionary1.Remove(key1);
158 Dictionary2.Remove(key2);
159
160 LLUDPClient[] oldArray = Array;
161 int oldLength = oldArray.Length;
162
163 LLUDPClient[] newArray = new LLUDPClient[oldLength - 1];
164 int j = 0;
165 for (int i = 0; i < oldLength; i++)
166 {
167 if (oldArray[i] != value)
168 newArray[j++] = oldArray[i];
169 }
170
171 Array = newArray;
172 return true;
173 }
174 }
175
176 return false;
177
178 }
179
180 public void Clear()
181 {
182 //rwLock.EnterWriteLock();
183
184 //try
185 //{
186 // Dictionary1.Clear();
187 // Dictionary2.Clear();
188 // Array = new LLUDPClient[0];
189 //}
190 //finally { rwLock.ExitWriteLock(); }
191
192 lock (m_sync)
193 {
194 Dictionary1.Clear();
195 Dictionary2.Clear();
196 Array = new LLUDPClient[0];
197 }
198
199 }
200
201 public int Count
202 {
203 get { return Array.Length; }
204 }
205
206 public bool ContainsKey(UUID key)
207 {
208 return Dictionary1.ContainsKey(key);
209 }
210
211 public bool ContainsKey(IPEndPoint key)
212 {
213 return Dictionary2.ContainsKey(key);
214 }
215
216 public bool TryGetValue(UUID key, out LLUDPClient value)
217 {
218 ////bool success;
219 ////bool doLock = !rwLock.IsUpgradeableReadLockHeld;
220 ////if (doLock) rwLock.EnterReadLock();
221
222 ////try { success = Dictionary1.TryGetValue(key, out value); }
223 ////finally { if (doLock) rwLock.ExitReadLock(); }
224
225 ////return success;
226
227 lock (m_sync)
228 return Dictionary1.TryGetValue(key, out value);
229
230 //try
231 //{
232 // return Dictionary1.TryGetValue(key, out value);
233 //}
234 //catch { }
235 //value = null;
236 //return false;
237 }
238
239 public bool TryGetValue(IPEndPoint key, out LLUDPClient value)
240 {
241 ////bool success;
242 ////bool doLock = !rwLock.IsUpgradeableReadLockHeld;
243 ////if (doLock) rwLock.EnterReadLock();
244
245 ////try { success = Dictionary2.TryGetValue(key, out value); }
246 ////finally { if (doLock) rwLock.ExitReadLock(); }
247
248 ////return success;
249
250 lock (m_sync)
251 return Dictionary2.TryGetValue(key, out value);
252
253 //try
254 //{
255 // return Dictionary2.TryGetValue(key, out value);
256 //}
257 //catch { }
258 //value = null;
259 //return false;
260
261 }
262
263 public void ForEach(Action<LLUDPClient> action)
264 {
265 //bool doLock = !rwLock.IsUpgradeableReadLockHeld;
266 //if (doLock) rwLock.EnterUpgradeableReadLock();
267
268 //try { Parallel.ForEach<LLUDPClient>(Array, action); }
269 //finally { if (doLock) rwLock.ExitUpgradeableReadLock(); }
270
271 LLUDPClient[] localArray = null;
272 lock (m_sync)
273 {
274 localArray = new LLUDPClient[Array.Length];
275 Array.CopyTo(localArray, 0);
276 }
277
278 Parallel.ForEach<LLUDPClient>(localArray, action);
279
280 }
281 }
282}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index c356f02..57fee59 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -96,7 +96,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
96 /// <summary>Incoming packets that are awaiting handling</summary> 96 /// <summary>Incoming packets that are awaiting handling</summary>
97 private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>(); 97 private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>();
98 /// <summary></summary> 98 /// <summary></summary>
99 private UDPClientCollection clients = new UDPClientCollection(); 99 //private UDPClientCollection m_clients = new UDPClientCollection();
100 /// <summary>Bandwidth throttle for this UDP server</summary> 100 /// <summary>Bandwidth throttle for this UDP server</summary>
101 private TokenBucket m_throttle; 101 private TokenBucket m_throttle;
102 /// <summary>Bandwidth throttle rates for this UDP server</summary> 102 /// <summary>Bandwidth throttle rates for this UDP server</summary>
@@ -115,7 +115,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
115 public Socket Server { get { return null; } } 115 public Socket Server { get { return null; } }
116 116
117 public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager) 117 public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager)
118 : base((int)port) 118 : base(listenIP, (int)port)
119 { 119 {
120 #region Environment.TickCount Measurement 120 #region Environment.TickCount Measurement
121 121
@@ -143,7 +143,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
143 public new void Start() 143 public new void Start()
144 { 144 {
145 if (m_scene == null) 145 if (m_scene == null)
146 throw new InvalidOperationException("Cannot LLUDPServer.Start() without an IScene reference"); 146 throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference");
147 147
148 base.Start(); 148 base.Start();
149 149
@@ -181,24 +181,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
181 return x == m_location; 181 return x == m_location;
182 } 182 }
183 183
184 public void RemoveClient(IClientAPI client)
185 {
186 m_scene.ClientManager.Remove(client.CircuitCode);
187 client.Close(false);
188
189 LLUDPClient udpClient;
190 if (clients.TryGetValue(client.AgentId, out udpClient))
191 {
192 m_log.Debug("[LLUDPSERVER]: Removing LLUDPClient for " + client.Name + " in " + m_scene.RegionInfo.RegionName);
193 udpClient.Shutdown();
194 clients.Remove(client.AgentId, udpClient.RemoteEndPoint);
195 }
196 else
197 {
198 m_log.Warn("[LLUDPSERVER]: Failed to remove LLUDPClient for " + client.Name);
199 }
200 }
201
202 public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents, bool allowSplitting) 184 public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents, bool allowSplitting)
203 { 185 {
204 // CoarseLocationUpdate packets cannot be split in an automated way 186 // CoarseLocationUpdate packets cannot be split in an automated way
@@ -216,30 +198,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP
216 for (int i = 0; i < packetCount; i++) 198 for (int i = 0; i < packetCount; i++)
217 { 199 {
218 byte[] data = datas[i]; 200 byte[] data = datas[i];
219 clients.ForEach( 201 m_scene.ClientManager.ForEach(
220 delegate(LLUDPClient client) 202 delegate(IClientAPI client)
221 { SendPacketData(client, data, data.Length, packet.Type, packet.Header.Zerocoded, category); }); 203 {
204 if (client is LLClientView)
205 SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category);
206 }
207 );
222 } 208 }
223 } 209 }
224 else 210 else
225 { 211 {
226 byte[] data = packet.ToBytes(); 212 byte[] data = packet.ToBytes();
227 clients.ForEach( 213 m_scene.ClientManager.ForEach(
228 delegate(LLUDPClient client) 214 delegate(IClientAPI client)
229 { SendPacketData(client, data, data.Length, packet.Type, packet.Header.Zerocoded, category); }); 215 {
216 if (client is LLClientView)
217 SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category);
218 }
219 );
230 } 220 }
231 } 221 }
232 222
233 public void SendPacket(UUID agentID, Packet packet, ThrottleOutPacketType category, bool allowSplitting) 223 public void SendPacket(LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting)
234 {
235 LLUDPClient client;
236 if (clients.TryGetValue(agentID, out client))
237 SendPacket(client, packet, category, allowSplitting);
238 else
239 m_log.Warn("[LLUDPSERVER]: Attempted to send a packet to unknown agentID " + agentID);
240 }
241
242 public void SendPacket(LLUDPClient client, Packet packet, ThrottleOutPacketType category, bool allowSplitting)
243 { 224 {
244 // CoarseLocationUpdate packets cannot be split in an automated way 225 // CoarseLocationUpdate packets cannot be split in an automated way
245 if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting) 226 if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting)
@@ -256,25 +237,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP
256 for (int i = 0; i < packetCount; i++) 237 for (int i = 0; i < packetCount; i++)
257 { 238 {
258 byte[] data = datas[i]; 239 byte[] data = datas[i];
259 SendPacketData(client, data, data.Length, packet.Type, packet.Header.Zerocoded, category); 240 SendPacketData(udpClient, data, packet.Type, category);
260 } 241 }
261 } 242 }
262 else 243 else
263 { 244 {
264 byte[] data = packet.ToBytes(); 245 byte[] data = packet.ToBytes();
265 SendPacketData(client, data, data.Length, packet.Type, packet.Header.Zerocoded, category); 246 SendPacketData(udpClient, data, packet.Type, category);
266 } 247 }
267 } 248 }
268 249
269 public void SendPacketData(LLUDPClient client, byte[] data, int dataLength, PacketType type, bool doZerocode, ThrottleOutPacketType category) 250 public void SendPacketData(LLUDPClient udpClient, byte[] data, PacketType type, ThrottleOutPacketType category)
270 { 251 {
252 int dataLength = data.Length;
253 bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0;
254
271 // Frequency analysis of outgoing packet sizes shows a large clump of packets at each end of the spectrum. 255 // Frequency analysis of outgoing packet sizes shows a large clump of packets at each end of the spectrum.
272 // The vast majority of packets are less than 200 bytes, although due to asset transfers and packet splitting 256 // The vast majority of packets are less than 200 bytes, although due to asset transfers and packet splitting
273 // there are a decent number of packets in the 1000-1140 byte range. We allocate one of two sizes of data here 257 // there are a decent number of packets in the 1000-1140 byte range. We allocate one of two sizes of data here
274 // to accomodate for both common scenarios and provide ample room for ACK appending in both 258 // to accomodate for both common scenarios and provide ample room for ACK appending in both
275 int bufferSize = (dataLength > 180) ? Packet.MTU : 200; 259 int bufferSize = (dataLength > 180) ? Packet.MTU : 200;
276 260
277 UDPPacketBuffer buffer = new UDPPacketBuffer(client.RemoteEndPoint, bufferSize); 261 UDPPacketBuffer buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize);
278 262
279 // Zerocode if needed 263 // Zerocode if needed
280 if (doZerocode) 264 if (doZerocode)
@@ -285,17 +269,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
285 // The packet grew larger than the bufferSize while zerocoding. 269 // The packet grew larger than the bufferSize while zerocoding.
286 // Remove the MSG_ZEROCODED flag and send the unencoded data 270 // Remove the MSG_ZEROCODED flag and send the unencoded data
287 // instead 271 // instead
288 m_log.Info("[LLUDPSERVER]: Packet exceeded buffer size during zerocoding. Removing MSG_ZEROCODED flag"); 272 m_log.Debug("[LLUDPSERVER]: Packet exceeded buffer size during zerocoding for " + type + ". Removing MSG_ZEROCODED flag");
289 data[0] = (byte)(data[0] & ~Helpers.MSG_ZEROCODED); 273 data[0] = (byte)(data[0] & ~Helpers.MSG_ZEROCODED);
290 //
291 buffer = new UDPPacketBuffer(client.RemoteEndPoint, dataLength);
292 //
293 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength); 274 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
294 } 275 }
295 } 276 }
296 else 277 else
297 { 278 {
298 // ??? will it fit?
299 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength); 279 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
300 } 280 }
301 buffer.DataLength = dataLength; 281 buffer.DataLength = dataLength;
@@ -303,7 +283,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
303 #region Queue or Send 283 #region Queue or Send
304 284
305 // Look up the UDPClient this is going to 285 // Look up the UDPClient this is going to
306 OutgoingPacket outgoingPacket = new OutgoingPacket(client, buffer, category); 286 OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category);
307 287
308 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket)) 288 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket))
309 SendPacketFinal(outgoingPacket); 289 SendPacketFinal(outgoingPacket);
@@ -311,18 +291,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
311 #endregion Queue or Send 291 #endregion Queue or Send
312 } 292 }
313 293
314 public void SendAcks(LLUDPClient client) 294 public void SendAcks(LLUDPClient udpClient)
315 { 295 {
316 uint ack; 296 uint ack;
317 297
318 if (client.PendingAcks.Dequeue(out ack)) 298 if (udpClient.PendingAcks.Dequeue(out ack))
319 { 299 {
320 List<PacketAckPacket.PacketsBlock> blocks = new List<PacketAckPacket.PacketsBlock>(); 300 List<PacketAckPacket.PacketsBlock> blocks = new List<PacketAckPacket.PacketsBlock>();
321 PacketAckPacket.PacketsBlock block = new PacketAckPacket.PacketsBlock(); 301 PacketAckPacket.PacketsBlock block = new PacketAckPacket.PacketsBlock();
322 block.ID = ack; 302 block.ID = ack;
323 blocks.Add(block); 303 blocks.Add(block);
324 304
325 while (client.PendingAcks.Dequeue(out ack)) 305 while (udpClient.PendingAcks.Dequeue(out ack))
326 { 306 {
327 block = new PacketAckPacket.PacketsBlock(); 307 block = new PacketAckPacket.PacketsBlock();
328 block.ID = ack; 308 block.ID = ack;
@@ -333,22 +313,39 @@ namespace OpenSim.Region.ClientStack.LindenUDP
333 packet.Header.Reliable = false; 313 packet.Header.Reliable = false;
334 packet.Packets = blocks.ToArray(); 314 packet.Packets = blocks.ToArray();
335 315
336 SendPacket(client, packet, ThrottleOutPacketType.Unknown, true); 316 SendPacket(udpClient, packet, ThrottleOutPacketType.Unknown, true);
337 } 317 }
338 } 318 }
339 319
340 public void SendPing(LLUDPClient client) 320 public void SendPing(LLUDPClient udpClient)
341 { 321 {
342 IClientAPI api = client.ClientAPI; 322 StartPingCheckPacket pc = (StartPingCheckPacket)PacketPool.Instance.GetPacket(PacketType.StartPingCheck);
343 if (api != null) 323 pc.Header.Reliable = false;
344 api.SendStartPingCheck(client.CurrentPingSequence++); 324
325 OutgoingPacket oldestPacket = udpClient.NeedAcks.GetOldest();
326
327 pc.PingID.PingID = (byte)udpClient.CurrentPingSequence++;
328 pc.PingID.OldestUnacked = (oldestPacket != null) ? oldestPacket.SequenceNumber : 0;
329
330 SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false);
345 } 331 }
346 332
347 public void ResendUnacked(LLUDPClient client) 333 public void ResendUnacked(LLUDPClient udpClient)
348 { 334 {
349 if (client.NeedAcks.Count > 0) 335 if (udpClient.IsConnected && udpClient.NeedAcks.Count > 0)
350 { 336 {
351 List<OutgoingPacket> expiredPackets = client.NeedAcks.GetExpiredPackets(client.RTO); 337 // Disconnect an agent if no packets are received for some time
338 //FIXME: Make 60 an .ini setting
339 if (Environment.TickCount - udpClient.TickLastPacketReceived > 1000 * 60)
340 {
341 m_log.Warn("[LLUDPSERVER]: Ack timeout, disconnecting " + udpClient.AgentID);
342
343 RemoveClient(udpClient);
344 return;
345 }
346
347 // Get a list of all of the packets that have been sitting unacked longer than udpClient.RTO
348 List<OutgoingPacket> expiredPackets = udpClient.NeedAcks.GetExpiredPackets(udpClient.RTO);
352 349
353 if (expiredPackets != null) 350 if (expiredPackets != null)
354 { 351 {
@@ -357,54 +354,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
357 { 354 {
358 OutgoingPacket outgoingPacket = expiredPackets[i]; 355 OutgoingPacket outgoingPacket = expiredPackets[i];
359 356
360 // FIXME: Make this an .ini setting 357 //m_log.DebugFormat("[LLUDPSERVER]: Resending packet #{0} (attempt {1}), {2}ms have passed",
361 if (outgoingPacket.ResendCount < 3) 358 // outgoingPacket.SequenceNumber, outgoingPacket.ResendCount, Environment.TickCount - outgoingPacket.TickCount);
362 {
363 //Logger.Debug(String.Format("Resending packet #{0} (attempt {1}), {2}ms have passed",
364 // outgoingPacket.SequenceNumber, outgoingPacket.ResendCount, Environment.TickCount - outgoingPacket.TickCount));
365
366 // Set the resent flag
367 outgoingPacket.Buffer.Data[0] = (byte)(outgoingPacket.Buffer.Data[0] | Helpers.MSG_RESENT);
368 outgoingPacket.Category = ThrottleOutPacketType.Resend;
369
370 // The TickCount will be set to the current time when the packet
371 // is actually sent out again
372 outgoingPacket.TickCount = 0;
373
374 // Bump up the resend count on this packet
375 Interlocked.Increment(ref outgoingPacket.ResendCount);
376 //Interlocked.Increment(ref Stats.ResentPackets);
377
378 // Queue or (re)send the packet
379 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket))
380 SendPacketFinal(outgoingPacket);
381 }
382 else
383 {
384 m_log.DebugFormat("[LLUDPSERVER]: Dropping packet #{0} for agent {1} after {2} failed attempts",
385 outgoingPacket.SequenceNumber, outgoingPacket.Client.RemoteEndPoint, outgoingPacket.ResendCount);
386 359
387 lock (client.NeedAcks.SyncRoot) 360 // Set the resent flag
388 client.NeedAcks.RemoveUnsafe(outgoingPacket.SequenceNumber); 361 outgoingPacket.Buffer.Data[0] = (byte)(outgoingPacket.Buffer.Data[0] | Helpers.MSG_RESENT);
362 outgoingPacket.Category = ThrottleOutPacketType.Resend;
389 363
390 //Interlocked.Increment(ref Stats.DroppedPackets); 364 // The TickCount will be set to the current time when the packet
365 // is actually sent out again
366 outgoingPacket.TickCount = 0;
391 367
392 // Disconnect an agent if no packets are received for some time 368 // Bump up the resend count on this packet
393 //FIXME: Make 60 an .ini setting 369 Interlocked.Increment(ref outgoingPacket.ResendCount);
394 if (Environment.TickCount - client.TickLastPacketReceived > 1000 * 60) 370 //Interlocked.Increment(ref Stats.ResentPackets);
395 {
396 m_log.Warn("[LLUDPSERVER]: Ack timeout, disconnecting " + client.ClientAPI.Name);
397 371
398 RemoveClient(client.ClientAPI); 372 // Requeue or resend the packet
399 return; 373 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket))
400 } 374 SendPacketFinal(outgoingPacket);
401 }
402 } 375 }
403 } 376 }
404 } 377 }
405 } 378 }
406 379
407 public void Flush() 380 public void Flush(LLUDPClient udpClient)
408 { 381 {
409 // FIXME: Implement? 382 // FIXME: Implement?
410 } 383 }
@@ -415,7 +388,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
415 byte flags = buffer.Data[0]; 388 byte flags = buffer.Data[0];
416 bool isResend = (flags & Helpers.MSG_RESENT) != 0; 389 bool isResend = (flags & Helpers.MSG_RESENT) != 0;
417 bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0; 390 bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0;
418 LLUDPClient client = outgoingPacket.Client; 391 LLUDPClient udpClient = outgoingPacket.Client;
392
393 if (!udpClient.IsConnected)
394 return;
419 395
420 // Keep track of when this packet was sent out (right now) 396 // Keep track of when this packet was sent out (right now)
421 outgoingPacket.TickCount = Environment.TickCount; 397 outgoingPacket.TickCount = Environment.TickCount;
@@ -424,11 +400,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
424 400
425 int dataLength = buffer.DataLength; 401 int dataLength = buffer.DataLength;
426 402
427 // Keep appending ACKs until there is no room left in the packet or there are 403 // Keep appending ACKs until there is no room left in the buffer or there are
428 // no more ACKs to append 404 // no more ACKs to append
429 uint ackCount = 0; 405 uint ackCount = 0;
430 uint ack; 406 uint ack;
431 while (dataLength + 5 < buffer.Data.Length && client.PendingAcks.Dequeue(out ack)) 407 while (dataLength + 5 < buffer.Data.Length && udpClient.PendingAcks.Dequeue(out ack))
432 { 408 {
433 Utils.UIntToBytesBig(ack, buffer.Data, dataLength); 409 Utils.UIntToBytesBig(ack, buffer.Data, dataLength);
434 dataLength += 4; 410 dataLength += 4;
@@ -447,24 +423,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP
447 423
448 #endregion ACK Appending 424 #endregion ACK Appending
449 425
426 #region Sequence Number Assignment
427
450 if (!isResend) 428 if (!isResend)
451 { 429 {
452 // Not a resend, assign a new sequence number 430 // Not a resend, assign a new sequence number
453 uint sequenceNumber = (uint)Interlocked.Increment(ref client.CurrentSequence); 431 uint sequenceNumber = (uint)Interlocked.Increment(ref udpClient.CurrentSequence);
454 Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1); 432 Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1);
455 outgoingPacket.SequenceNumber = sequenceNumber; 433 outgoingPacket.SequenceNumber = sequenceNumber;
456 434
457 if (isReliable) 435 if (isReliable)
458 { 436 {
459 // Add this packet to the list of ACK responses we are waiting on from the server 437 // Add this packet to the list of ACK responses we are waiting on from the server
460 client.NeedAcks.Add(outgoingPacket); 438 udpClient.NeedAcks.Add(outgoingPacket);
461 } 439 }
462 } 440 }
463 441
442 #endregion Sequence Number Assignment
443
464 // Stats tracking 444 // Stats tracking
465 Interlocked.Increment(ref client.PacketsSent); 445 Interlocked.Increment(ref udpClient.PacketsSent);
466 if (isReliable) 446 if (isReliable)
467 Interlocked.Add(ref client.UnackedBytes, outgoingPacket.Buffer.DataLength); 447 Interlocked.Add(ref udpClient.UnackedBytes, outgoingPacket.Buffer.DataLength);
468 448
469 // Put the UDP payload on the wire 449 // Put the UDP payload on the wire
470 AsyncBeginSend(buffer); 450 AsyncBeginSend(buffer);
@@ -473,10 +453,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
473 protected override void PacketReceived(UDPPacketBuffer buffer) 453 protected override void PacketReceived(UDPPacketBuffer buffer)
474 { 454 {
475 // Debugging/Profiling 455 // Debugging/Profiling
476 //try { Thread.CurrentThread.Name = "PacketReceived (" + scene.RegionName + ")"; } 456 //try { Thread.CurrentThread.Name = "PacketReceived (" + m_scene.RegionInfo.RegionName + ")"; }
477 //catch (Exception) { } 457 //catch (Exception) { }
478 458
479 LLUDPClient client = null; 459 LLUDPClient udpClient = null;
480 Packet packet = null; 460 Packet packet = null;
481 int packetEnd = buffer.DataLength - 1; 461 int packetEnd = buffer.DataLength - 1;
482 IPEndPoint address = (IPEndPoint)buffer.RemoteEndPoint; 462 IPEndPoint address = (IPEndPoint)buffer.RemoteEndPoint;
@@ -491,61 +471,59 @@ namespace OpenSim.Region.ClientStack.LindenUDP
491 } 471 }
492 catch (MalformedDataException) 472 catch (MalformedDataException)
493 { 473 {
494 m_log.ErrorFormat("[LLUDPSERVER]: Malformed data, cannot parse packet:\n{0}", 474 m_log.ErrorFormat("[LLUDPSERVER]: Malformed data, cannot parse packet from {0}:\n{1}",
495 Utils.BytesToHexString(buffer.Data, buffer.DataLength, null)); 475 buffer.RemoteEndPoint, Utils.BytesToHexString(buffer.Data, buffer.DataLength, null));
496 } 476 }
497 477
498 // Fail-safe check 478 // Fail-safe check
499 if (packet == null) 479 if (packet == null)
500 { 480 {
501 m_log.Warn("[LLUDPSERVER]: Couldn't build a message from the incoming data"); 481 m_log.Warn("[LLUDPSERVER]: Couldn't build a message from incoming data " + buffer.DataLength +
482 " bytes long from " + buffer.RemoteEndPoint);
502 return; 483 return;
503 } 484 }
504 485
505 //Stats.RecvBytes += (ulong)buffer.DataLength;
506 //++Stats.RecvPackets;
507
508 #endregion Decoding 486 #endregion Decoding
509 487
510 #region UseCircuitCode Handling 488 #region Packet to Client Mapping
511 489
490 // UseCircuitCode handling
512 if (packet.Type == PacketType.UseCircuitCode) 491 if (packet.Type == PacketType.UseCircuitCode)
513 { 492 {
514 UseCircuitCodePacket useCircuitCode = (UseCircuitCodePacket)packet; 493 AddNewClient((UseCircuitCodePacket)packet, (IPEndPoint)buffer.RemoteEndPoint);
515 IClientAPI newuser;
516 uint circuitCode = useCircuitCode.CircuitCode.Code;
517
518 // Check if the client is already established
519 if (!m_scene.ClientManager.TryGetClient(circuitCode, out newuser))
520 {
521 AddNewClient(useCircuitCode, (IPEndPoint)buffer.RemoteEndPoint);
522 }
523 } 494 }
524 495
525 // Determine which agent this packet came from 496 // Determine which agent this packet came from
526 if (!clients.TryGetValue(address, out client)) 497 IClientAPI client;
498 if (!m_scene.ClientManager.TryGetValue(address, out client) || !(client is LLClientView))
527 { 499 {
528 m_log.Warn("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); 500 m_log.Warn("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address +
501 " in " + m_scene.RegionInfo.RegionName + ", currently tracking " + m_scene.ClientManager.Count + " clients");
529 return; 502 return;
530 } 503 }
531 504
532 #endregion UseCircuitCode Handling 505 udpClient = ((LLClientView)client).UDPClient;
506
507 if (!udpClient.IsConnected)
508 return;
509
510 #endregion Packet to Client Mapping
533 511
534 // Stats tracking 512 // Stats tracking
535 Interlocked.Increment(ref client.PacketsReceived); 513 Interlocked.Increment(ref udpClient.PacketsReceived);
536 514
537 #region ACK Receiving 515 #region ACK Receiving
538 516
539 int now = Environment.TickCount; 517 int now = Environment.TickCount;
540 client.TickLastPacketReceived = now; 518 udpClient.TickLastPacketReceived = now;
541 519
542 // Handle appended ACKs 520 // Handle appended ACKs
543 if (packet.Header.AppendedAcks && packet.Header.AckList != null) 521 if (packet.Header.AppendedAcks && packet.Header.AckList != null)
544 { 522 {
545 lock (client.NeedAcks.SyncRoot) 523 lock (udpClient.NeedAcks.SyncRoot)
546 { 524 {
547 for (int i = 0; i < packet.Header.AckList.Length; i++) 525 for (int i = 0; i < packet.Header.AckList.Length; i++)
548 AcknowledgePacket(client, packet.Header.AckList[i], now, packet.Header.Resent); 526 AcknowledgePacket(udpClient, packet.Header.AckList[i], now, packet.Header.Resent);
549 } 527 }
550 } 528 }
551 529
@@ -554,10 +532,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
554 { 532 {
555 PacketAckPacket ackPacket = (PacketAckPacket)packet; 533 PacketAckPacket ackPacket = (PacketAckPacket)packet;
556 534
557 lock (client.NeedAcks.SyncRoot) 535 lock (udpClient.NeedAcks.SyncRoot)
558 { 536 {
559 for (int i = 0; i < ackPacket.Packets.Length; i++) 537 for (int i = 0; i < ackPacket.Packets.Length; i++)
560 AcknowledgePacket(client, ackPacket.Packets[i].ID, now, packet.Header.Resent); 538 AcknowledgePacket(udpClient, ackPacket.Packets[i].ID, now, packet.Header.Resent);
561 } 539 }
562 } 540 }
563 541
@@ -566,27 +544,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP
566 #region ACK Sending 544 #region ACK Sending
567 545
568 if (packet.Header.Reliable) 546 if (packet.Header.Reliable)
569 client.PendingAcks.Enqueue((uint)packet.Header.Sequence); 547 udpClient.PendingAcks.Enqueue(packet.Header.Sequence);
570 548
571 // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out, 549 // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out,
572 // add the current received bytes to it, test if 2*MTU bytes have been sent, if so remove 550 // add the current received bytes to it, test if 2*MTU bytes have been sent, if so remove
573 // 2*MTU bytes from the value and send ACKs, and finally add the local value back to 551 // 2*MTU bytes from the value and send ACKs, and finally add the local value back to
574 // client.BytesSinceLastACK. Lockless thread safety 552 // client.BytesSinceLastACK. Lockless thread safety
575 int bytesSinceLastACK = Interlocked.Exchange(ref client.BytesSinceLastACK, 0); 553 int bytesSinceLastACK = Interlocked.Exchange(ref udpClient.BytesSinceLastACK, 0);
576 bytesSinceLastACK += buffer.DataLength; 554 bytesSinceLastACK += buffer.DataLength;
577 if (bytesSinceLastACK > Packet.MTU * 2) 555 if (bytesSinceLastACK > Packet.MTU * 2)
578 { 556 {
579 bytesSinceLastACK -= Packet.MTU * 2; 557 bytesSinceLastACK -= Packet.MTU * 2;
580 SendAcks(client); 558 SendAcks(udpClient);
581 } 559 }
582 Interlocked.Add(ref client.BytesSinceLastACK, bytesSinceLastACK); 560 Interlocked.Add(ref udpClient.BytesSinceLastACK, bytesSinceLastACK);
583 561
584 #endregion ACK Sending 562 #endregion ACK Sending
585 563
586 #region Incoming Packet Accounting 564 #region Incoming Packet Accounting
587 565
588 // Check the archive of received reliable packet IDs to see whether we already received this packet 566 // Check the archive of received reliable packet IDs to see whether we already received this packet
589 if (packet.Header.Reliable && !client.PacketArchive.TryEnqueue(packet.Header.Sequence)) 567 if (packet.Header.Reliable && !udpClient.PacketArchive.TryEnqueue(packet.Header.Sequence))
590 { 568 {
591 if (packet.Header.Resent) 569 if (packet.Header.Resent)
592 m_log.Debug("[LLUDPSERVER]: Received a resend of already processed packet #" + packet.Header.Sequence + ", type: " + packet.Type); 570 m_log.Debug("[LLUDPSERVER]: Received a resend of already processed packet #" + packet.Header.Sequence + ", type: " + packet.Type);
@@ -603,7 +581,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
603 if (packet.Type != PacketType.PacketAck) 581 if (packet.Type != PacketType.PacketAck)
604 { 582 {
605 // Inbox insertion 583 // Inbox insertion
606 packetInbox.Enqueue(new IncomingPacket(client, packet)); 584 packetInbox.Enqueue(new IncomingPacket(udpClient, packet));
607 } 585 }
608 } 586 }
609 587
@@ -623,53 +601,59 @@ namespace OpenSim.Region.ClientStack.LindenUDP
623 601
624 private void AddNewClient(UseCircuitCodePacket useCircuitCode, IPEndPoint remoteEndPoint) 602 private void AddNewClient(UseCircuitCodePacket useCircuitCode, IPEndPoint remoteEndPoint)
625 { 603 {
626 //Slave regions don't accept new clients 604 UUID agentID = useCircuitCode.CircuitCode.ID;
605 UUID sessionID = useCircuitCode.CircuitCode.SessionID;
606 uint circuitCode = useCircuitCode.CircuitCode.Code;
607
627 if (m_scene.RegionStatus != RegionStatus.SlaveScene) 608 if (m_scene.RegionStatus != RegionStatus.SlaveScene)
628 { 609 {
629 AuthenticateResponse sessionInfo; 610 AuthenticateResponse sessionInfo;
630 bool isNewCircuit = !clients.ContainsKey(remoteEndPoint); 611 if (IsClientAuthorized(useCircuitCode, out sessionInfo))
631
632 if (!IsClientAuthorized(useCircuitCode, out sessionInfo))
633 { 612 {
634 m_log.WarnFormat( 613 AddClient(circuitCode, agentID, sessionID, remoteEndPoint, sessionInfo);
635 "[CONNECTION FAILURE]: Connection request for client {0} connecting with unnotified circuit code {1} from {2}",
636 useCircuitCode.CircuitCode.ID, useCircuitCode.CircuitCode.Code, remoteEndPoint);
637 return;
638 } 614 }
639 615 else
640 if (isNewCircuit)
641 { 616 {
642 UUID agentID = useCircuitCode.CircuitCode.ID; 617 // Don't create circuits for unauthorized clients
643 UUID sessionID = useCircuitCode.CircuitCode.SessionID; 618 m_log.WarnFormat(
644 uint circuitCode = useCircuitCode.CircuitCode.Code; 619 "[LLUDPSERVER]: Connection request for client {0} connecting with unnotified circuit code {1} from {2}",
645 620 useCircuitCode.CircuitCode.ID, useCircuitCode.CircuitCode.Code, remoteEndPoint);
646 AddClient(circuitCode, agentID, sessionID, remoteEndPoint, sessionInfo);
647 } 621 }
648 } 622 }
623 else
624 {
625 // Slave regions don't accept new clients
626 m_log.Debug("[LLUDPSERVER]: Slave region " + m_scene.RegionInfo.RegionName + " ignoring UseCircuitCode packet");
627 }
649 } 628 }
650 629
651 private void AddClient(uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo) 630 private void AddClient(uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo)
652 { 631 {
653 // Create the LLUDPClient 632 // Create the LLUDPClient
654 LLUDPClient client = new LLUDPClient(this, m_throttleRates, m_throttle, circuitCode, agentID, remoteEndPoint); 633 LLUDPClient udpClient = new LLUDPClient(this, m_throttleRates, m_throttle, circuitCode, agentID, remoteEndPoint);
655 634
656 // Create the LLClientView 635 if (!m_scene.ClientManager.ContainsKey(agentID))
657 LLClientView clientApi = new LLClientView(remoteEndPoint, m_scene, this, client, sessionInfo, agentID, sessionID, circuitCode); 636 {
658 clientApi.OnViewerEffect += m_scene.ClientManager.ViewerEffectHandler; 637 // Create the LLClientView
659 clientApi.OnLogout += LogoutHandler; 638 LLClientView client = new LLClientView(remoteEndPoint, m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
660 clientApi.OnConnectionClosed += RemoveClient; 639 client.OnLogout += LogoutHandler;
661
662 // Start the IClientAPI
663 m_scene.ClientManager.Add(circuitCode, clientApi);
664 clientApi.Start();
665
666 // Give LLUDPClient a reference to IClientAPI
667 client.ClientAPI = clientApi;
668 640
669 // Add the new client to our list of tracked clients 641 // Start the IClientAPI
670 clients.Add(agentID, client.RemoteEndPoint, client); 642 client.Start();
643 }
644 else
645 {
646 m_log.WarnFormat("[LLUDPSERVER]: Ignoring a repeated UseCircuitCode from {0} at {1} for circuit {2}",
647 udpClient.AgentID, remoteEndPoint, circuitCode);
648 }
649 }
671 650
672 m_log.DebugFormat("[LLUDPSERVER]: Added new client {0} to region {1}", agentID, m_scene.RegionInfo.RegionName); 651 private void RemoveClient(LLUDPClient udpClient)
652 {
653 // Remove this client from the scene
654 IClientAPI client;
655 if (m_scene.ClientManager.TryGetValue(udpClient.AgentID, out client))
656 client.Close();
673 } 657 }
674 658
675 private void AcknowledgePacket(LLUDPClient client, uint ack, int currentTime, bool fromResend) 659 private void AcknowledgePacket(LLUDPClient client, uint ack, int currentTime, bool fromResend)
@@ -747,20 +731,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP
747 elapsed500MS = 0; 731 elapsed500MS = 0;
748 } 732 }
749 733
750 clients.ForEach( 734 m_scene.ClientManager.ForEach(
751 delegate(LLUDPClient client) 735 delegate(IClientAPI client)
752 { 736 {
753 if (client.DequeueOutgoing()) 737 if (client is LLClientView)
754 packetSent = true;
755 if (resendUnacked)
756 ResendUnacked(client);
757 if (sendAcks)
758 { 738 {
759 SendAcks(client); 739 LLUDPClient udpClient = ((LLClientView)client).UDPClient;
760 client.SendPacketStats(); 740
741 if (udpClient.IsConnected)
742 {
743 if (udpClient.DequeueOutgoing())
744 packetSent = true;
745 if (resendUnacked)
746 ResendUnacked(udpClient);
747 if (sendAcks)
748 {
749 SendAcks(udpClient);
750 udpClient.SendPacketStats();
751 }
752 if (sendPings)
753 SendPing(udpClient);
754 }
761 } 755 }
762 if (sendPings)
763 SendPing(client);
764 } 756 }
765 ); 757 );
766 758
@@ -773,38 +765,46 @@ namespace OpenSim.Region.ClientStack.LindenUDP
773 { 765 {
774 IncomingPacket incomingPacket = (IncomingPacket)state; 766 IncomingPacket incomingPacket = (IncomingPacket)state;
775 Packet packet = incomingPacket.Packet; 767 Packet packet = incomingPacket.Packet;
776 LLUDPClient client = incomingPacket.Client; 768 LLUDPClient udpClient = incomingPacket.Client;
769 IClientAPI client;
777 770
778 // Sanity check 771 // Sanity check
779 if (packet == null || client == null || client.ClientAPI == null) 772 if (packet == null || udpClient == null)
780 { 773 {
781 m_log.WarnFormat("[LLUDPSERVER]: Processing a packet with incomplete state. Packet=\"{0}\", Client=\"{1}\", Client.ClientAPI=\"{2}\"", 774 m_log.WarnFormat("[LLUDPSERVER]: Processing a packet with incomplete state. Packet=\"{0}\", UDPClient=\"{1}\"",
782 packet, client, (client != null) ? client.ClientAPI : null); 775 packet, udpClient);
783 } 776 }
784 777
785 try 778 // Make sure this client is still alive
786 { 779 if (m_scene.ClientManager.TryGetValue(udpClient.AgentID, out client))
787 // Process this packet
788 client.ClientAPI.ProcessInPacket(packet);
789 }
790 catch (ThreadAbortException)
791 { 780 {
792 // If something is trying to abort the packet processing thread, take that as a hint that it's time to shut down 781 try
793 m_log.Info("[LLUDPSERVER]: Caught a thread abort, shutting down the LLUDP server"); 782 {
794 Stop(); 783 // Process this packet
784 client.ProcessInPacket(packet);
785 }
786 catch (ThreadAbortException)
787 {
788 // If something is trying to abort the packet processing thread, take that as a hint that it's time to shut down
789 m_log.Info("[LLUDPSERVER]: Caught a thread abort, shutting down the LLUDP server");
790 Stop();
791 }
792 catch (Exception e)
793 {
794 // Don't let a failure in an individual client thread crash the whole sim.
795 m_log.ErrorFormat("[LLUDPSERVER]: Client packet handler for {0} for packet {1} threw an exception", udpClient.AgentID, packet.Type);
796 m_log.Error(e.Message, e);
797 }
795 } 798 }
796 catch (Exception e) 799 else
797 { 800 {
798 // Don't let a failure in an individual client thread crash the whole sim. 801 m_log.DebugFormat("[LLUDPSERVER]: Dropping incoming {0} packet for dead client {1}", packet.Type, udpClient.AgentID);
799 m_log.ErrorFormat("[LLUDPSERVER]: Client packet handler for {0} for packet {1} threw an exception", client.AgentID, packet.Type);
800 m_log.Error(e.Message, e);
801 } 802 }
802 } 803 }
803 804
804 private void LogoutHandler(IClientAPI client) 805 private void LogoutHandler(IClientAPI client)
805 { 806 {
806 client.SendLogoutPacket(); 807 client.SendLogoutPacket();
807 RemoveClient(client);
808 } 808 }
809 } 809 }
810} 810}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs
index 43a68ec..fad2ea8 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs
@@ -1,402 +1,100 @@
1//--------- Modified Version ------------------- 1/*
2///* 2 * Copyright (c) 2006, Clutch, Inc.
3// * Copyright (c) 2006, Clutch, Inc. 3 * Original Author: Jeff Cesnik
4// * Original Author: Jeff Cesnik 4 * All rights reserved.
5// * All rights reserved. 5 *
6// * 6 * - Redistribution and use in source and binary forms, with or without
7// * - Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met:
8// * modification, are permitted provided that the following conditions are met: 8 *
9// * 9 * - Redistributions of source code must retain the above copyright notice, this
10// * - Redistributions of source code must retain the above copyright notice, this 10 * list of conditions and the following disclaimer.
11// * list of conditions and the following disclaimer. 11 * - Neither the name of the openmetaverse.org nor the names
12// * - Neither the name of the openmetaverse.org nor the names 12 * of its contributors may be used to endorse or promote products derived from
13// * of its contributors may be used to endorse or promote products derived from 13 * this software without specific prior written permission.
14// * this software without specific prior written permission. 14 *
15// * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16// * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17// * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18// * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19// * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20// * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21// * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22// * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23// * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24// * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25// * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE.
26// * POSSIBILITY OF SUCH DAMAGE. 26 */
27// */
28 27
29using System; 28using System;
30using System.Net; 29using System.Net;
31using System.Net.Sockets; 30using System.Net.Sockets;
32using System.Threading; 31using System.Threading;
33using OpenMetaverse; 32using log4net;
34 33
35//namespace OpenSim.Region.ClientStack.LindenUDP 34namespace OpenMetaverse
36//{
37// /// <summary>
38// ///
39// /// </summary>
40// public abstract class OpenSimUDPBase
41// {
42// // these abstract methods must be implemented in a derived class to actually do
43// // something with the packets that are sent and received.
44// protected abstract void PacketReceived(UDPPacketBuffer buffer);
45// protected abstract void PacketSent(UDPPacketBuffer buffer, int bytesSent);
46
47// // the port to listen on
48// internal int udpPort;
49
50// // the UDP socket
51// private Socket udpSocket;
52
53// // the ReaderWriterLock is used solely for the purposes of shutdown (Stop()).
54// // since there are potentially many "reader" threads in the internal .NET IOCP
55// // thread pool, this is a cheaper synchronization primitive than using
56// // a Mutex object. This allows many UDP socket "reads" concurrently - when
57// // Stop() is called, it attempts to obtain a writer lock which will then
58// // wait until all outstanding operations are completed before shutting down.
59// // this avoids the problem of closing the socket with outstanding operations
60// // and trying to catch the inevitable ObjectDisposedException.
61// private ReaderWriterLock rwLock = new ReaderWriterLock();
62
63// // number of outstanding operations. This is a reference count
64// // which we use to ensure that the threads exit cleanly. Note that
65// // we need this because the threads will potentially still need to process
66// // data even after the socket is closed.
67// private int rwOperationCount = 0;
68
69// // the all important shutdownFlag. This is synchronized through the ReaderWriterLock.
70// private volatile bool shutdownFlag = true;
71
72// // the remote endpoint to communicate with
73// protected IPEndPoint remoteEndPoint = null;
74
75
76// /// <summary>
77// /// Initialize the UDP packet handler in server mode
78// /// </summary>
79// /// <param name="port">Port to listening for incoming UDP packets on</param>
80// public OpenSimUDPBase(int port)
81// {
82// udpPort = port;
83// }
84
85// /// <summary>
86// /// Initialize the UDP packet handler in client mode
87// /// </summary>
88// /// <param name="endPoint">Remote UDP server to connect to</param>
89// public OpenSimUDPBase(IPEndPoint endPoint)
90// {
91// remoteEndPoint = endPoint;
92// udpPort = 0;
93// }
94
95// /// <summary>
96// ///
97// /// </summary>
98// public void Start()
99// {
100// if (shutdownFlag)
101// {
102// if (remoteEndPoint == null)
103// {
104// // Server mode
105
106// // create and bind the socket
107// IPEndPoint ipep = new IPEndPoint(Settings.BIND_ADDR, udpPort);
108// udpSocket = new Socket(
109// AddressFamily.InterNetwork,
110// SocketType.Dgram,
111// ProtocolType.Udp);
112// udpSocket.Bind(ipep);
113// }
114// else
115// {
116// // Client mode
117// IPEndPoint ipep = new IPEndPoint(Settings.BIND_ADDR, udpPort);
118// udpSocket = new Socket(
119// AddressFamily.InterNetwork,
120// SocketType.Dgram,
121// ProtocolType.Udp);
122// udpSocket.Bind(ipep);
123// //udpSocket.Connect(remoteEndPoint);
124// }
125
126// // we're not shutting down, we're starting up
127// shutdownFlag = false;
128
129// // kick off an async receive. The Start() method will return, the
130// // actual receives will occur asynchronously and will be caught in
131// // AsyncEndRecieve().
132// AsyncBeginReceive();
133// }
134// }
135
136// /// <summary>
137// ///
138// /// </summary>
139// public void Stop()
140// {
141// if (!shutdownFlag)
142// {
143// // wait indefinitely for a writer lock. Once this is called, the .NET runtime
144// // will deny any more reader locks, in effect blocking all other send/receive
145// // threads. Once we have the lock, we set shutdownFlag to inform the other
146// // threads that the socket is closed.
147// rwLock.AcquireWriterLock(-1);
148// shutdownFlag = true;
149// udpSocket.Close();
150// rwLock.ReleaseWriterLock();
151
152// // wait for any pending operations to complete on other
153// // threads before exiting.
154// const int FORCE_STOP = 100;
155// int i = 0;
156// while (rwOperationCount > 0 && i < FORCE_STOP)
157// {
158// Thread.Sleep(10);
159// ++i;
160// }
161
162// if (i >= FORCE_STOP)
163// {
164// Logger.Log("UDPBase.Stop() forced shutdown while waiting on pending operations",
165// Helpers.LogLevel.Warning);
166// }
167// }
168// }
169
170// /// <summary>
171// ///
172// /// </summary>
173// public bool IsRunning
174// {
175// get { return !shutdownFlag; }
176// }
177
178// private void AsyncBeginReceive()
179// {
180// // this method actually kicks off the async read on the socket.
181// // we aquire a reader lock here to ensure that no other thread
182// // is trying to set shutdownFlag and close the socket.
183// rwLock.AcquireReaderLock(-1);
184
185// if (!shutdownFlag)
186// {
187// // increment the count of pending operations
188// Interlocked.Increment(ref rwOperationCount);
189
190// // allocate a packet buffer
191// //WrappedObject<UDPPacketBuffer> wrappedBuffer = Pool.CheckOut();
192// UDPPacketBuffer buf = new UDPPacketBuffer();
193
194// try
195// {
196// // kick off an async read
197// udpSocket.BeginReceiveFrom(
198// //wrappedBuffer.Instance.Data,
199// buf.Data,
200// 0,
201// UDPPacketBuffer.BUFFER_SIZE,
202// SocketFlags.None,
203// //ref wrappedBuffer.Instance.RemoteEndPoint,
204// ref buf.RemoteEndPoint,
205// new AsyncCallback(AsyncEndReceive),
206// //wrappedBuffer);
207// buf);
208// }
209// catch (SocketException)
210// {
211// // something bad happened
212// //Logger.Log(
213// // "A SocketException occurred in UDPServer.AsyncBeginReceive()",
214// // Helpers.LogLevel.Error, se);
215
216// // an error occurred, therefore the operation is void. Decrement the reference count.
217// Interlocked.Decrement(ref rwOperationCount);
218// }
219// }
220
221// // we're done with the socket for now, release the reader lock.
222// rwLock.ReleaseReaderLock();
223// }
224
225// private void AsyncEndReceive(IAsyncResult iar)
226// {
227// // Asynchronous receive operations will complete here through the call
228// // to AsyncBeginReceive
229
230// // aquire a reader lock
231// rwLock.AcquireReaderLock(-1);
232
233// if (!shutdownFlag)
234// {
235// // get the buffer that was created in AsyncBeginReceive
236// // this is the received data
237// //WrappedObject<UDPPacketBuffer> wrappedBuffer = (WrappedObject<UDPPacketBuffer>)iar.AsyncState;
238// //UDPPacketBuffer buffer = wrappedBuffer.Instance;
239// UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState;
240
241// try
242// {
243// // get the length of data actually read from the socket, store it with the
244// // buffer
245// buffer.DataLength = udpSocket.EndReceiveFrom(iar, ref buffer.RemoteEndPoint);
246
247// // this operation is now complete, decrement the reference count
248// Interlocked.Decrement(ref rwOperationCount);
249
250// // we're done with the socket, release the reader lock
251// rwLock.ReleaseReaderLock();
252
253// // call the abstract method PacketReceived(), passing the buffer that
254// // has just been filled from the socket read.
255// PacketReceived(buffer);
256// }
257// catch (SocketException)
258// {
259// // an error occurred, therefore the operation is void. Decrement the reference count.
260// Interlocked.Decrement(ref rwOperationCount);
261
262// // we're done with the socket for now, release the reader lock.
263// rwLock.ReleaseReaderLock();
264// }
265// finally
266// {
267// // start another receive - this keeps the server going!
268// AsyncBeginReceive();
269
270// //wrappedBuffer.Dispose();
271// }
272// }
273// else
274// {
275// // nothing bad happened, but we are done with the operation
276// // decrement the reference count and release the reader lock
277// Interlocked.Decrement(ref rwOperationCount);
278// rwLock.ReleaseReaderLock();
279// }
280// }
281
282// public void AsyncBeginSend(UDPPacketBuffer buf)
283// {
284// rwLock.AcquireReaderLock(-1);
285
286// if (!shutdownFlag)
287// {
288// try
289// {
290// Interlocked.Increment(ref rwOperationCount);
291// udpSocket.BeginSendTo(
292// buf.Data,
293// 0,
294// buf.DataLength,
295// SocketFlags.None,
296// buf.RemoteEndPoint,
297// new AsyncCallback(AsyncEndSend),
298// buf);
299// }
300// catch (SocketException)
301// {
302// //Logger.Log(
303// // "A SocketException occurred in UDPServer.AsyncBeginSend()",
304// // Helpers.LogLevel.Error, se);
305// }
306// }
307
308// rwLock.ReleaseReaderLock();
309// }
310
311// private void AsyncEndSend(IAsyncResult iar)
312// {
313// rwLock.AcquireReaderLock(-1);
314
315// if (!shutdownFlag)
316// {
317// UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState;
318
319// try
320// {
321// int bytesSent = udpSocket.EndSendTo(iar);
322
323// // note that call to the abstract PacketSent() method - we are passing the number
324// // of bytes sent in a separate parameter, since we can't use buffer.DataLength which
325// // is the number of bytes to send (or bytes received depending upon whether this
326// // buffer was part of a send or a receive).
327// PacketSent(buffer, bytesSent);
328// }
329// catch (SocketException)
330// {
331// //Logger.Log(
332// // "A SocketException occurred in UDPServer.AsyncEndSend()",
333// // Helpers.LogLevel.Error, se);
334// }
335// }
336
337// Interlocked.Decrement(ref rwOperationCount);
338// rwLock.ReleaseReaderLock();
339// }
340// }
341//}
342
343//--------- Original Version -------------------
344
345
346namespace OpenSim.Region.ClientStack.LindenUDP
347{ 35{
348 /// <summary> 36 /// <summary>
349 /// 37 /// Base UDP server
350 /// </summary> 38 /// </summary>
351 public abstract class OpenSimUDPBase 39 public abstract class OpenSimUDPBase
352 { 40 {
353 // these abstract methods must be implemented in a derived class to actually do 41 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
354 // something with the packets that are sent and received. 42
43 /// <summary>
44 /// This method is called when an incoming packet is received
45 /// </summary>
46 /// <param name="buffer">Incoming packet buffer</param>
355 protected abstract void PacketReceived(UDPPacketBuffer buffer); 47 protected abstract void PacketReceived(UDPPacketBuffer buffer);
48
49 /// <summary>
50 /// This method is called when an outgoing packet is sent
51 /// </summary>
52 /// <param name="buffer">Outgoing packet buffer</param>
53 /// <param name="bytesSent">Number of bytes written to the wire</param>
356 protected abstract void PacketSent(UDPPacketBuffer buffer, int bytesSent); 54 protected abstract void PacketSent(UDPPacketBuffer buffer, int bytesSent);
357 55
358 // the port to listen on 56 /// <summary>UDP port to bind to in server mode</summary>
359 internal int udpPort; 57 protected int m_udpPort;
360 58
361 // the UDP socket 59 /// <summary>Local IP address to bind to in server mode</summary>
362 private Socket udpSocket; 60 protected IPAddress m_localBindAddress;
363 61
364 // the all important shutdownFlag. 62 /// <summary>UDP socket, used in either client or server mode</summary>
365 private volatile bool shutdownFlag = true; 63 private Socket m_udpSocket;
366 64
367 // the remote endpoint to communicate with 65 /// <summary>The all important shutdown flag</summary>
368 protected IPEndPoint remoteEndPoint = null; 66 private volatile bool m_shutdownFlag = true;
369 67
370 /// <summary> 68 /// <summary>Returns true if the server is currently listening, otherwise false</summary>
371 /// Initialize the UDP packet handler in server mode 69 public bool IsRunning { get { return !m_shutdownFlag; } }
372 /// </summary>
373 /// <param name="port">Port to listening for incoming UDP packets on</param>
374 public OpenSimUDPBase(int port)
375 {
376 udpPort = port;
377 }
378 70
379 /// <summary> 71 /// <summary>
380 /// Initialize the UDP packet handler in client mode 72 /// Default constructor
381 /// </summary> 73 /// </summary>
382 /// <param name="endPoint">Remote UDP server to connect to</param> 74 /// <param name="bindAddress">Local IP address to bind the server to</param>
383 public OpenSimUDPBase(IPEndPoint endPoint) 75 /// <param name="port">Port to listening for incoming UDP packets on</param>
76 public OpenSimUDPBase(IPAddress bindAddress, int port)
384 { 77 {
385 remoteEndPoint = endPoint; 78 m_localBindAddress = bindAddress;
386 udpPort = 0; 79 m_udpPort = port;
387 } 80 }
388 81
389 /// <summary> 82 /// <summary>
390 /// 83 /// Start the UDP server
391 /// </summary> 84 /// </summary>
85 /// <remarks>This method will attempt to set the SIO_UDP_CONNRESET flag
86 /// on the socket to get newer versions of Windows to behave in a sane
87 /// manner (not throwing an exception when the remote side resets the
88 /// connection). This call is ignored on Mono where the flag is not
89 /// necessary</remarks>
392 public void Start() 90 public void Start()
393 { 91 {
394 if (shutdownFlag) 92 if (m_shutdownFlag)
395 { 93 {
396 const int SIO_UDP_CONNRESET = -1744830452; 94 const int SIO_UDP_CONNRESET = -1744830452;
397 95
398 IPEndPoint ipep = new IPEndPoint(Settings.BIND_ADDR, udpPort); 96 IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort);
399 udpSocket = new Socket( 97 m_udpSocket = new Socket(
400 AddressFamily.InterNetwork, 98 AddressFamily.InterNetwork,
401 SocketType.Dgram, 99 SocketType.Dgram,
402 ProtocolType.Udp); 100 ProtocolType.Udp);
@@ -404,16 +102,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
404 { 102 {
405 // this udp socket flag is not supported under mono, 103 // this udp socket flag is not supported under mono,
406 // so we'll catch the exception and continue 104 // so we'll catch the exception and continue
407 udpSocket.IOControl(SIO_UDP_CONNRESET, new byte[] { 0 }, null); 105 m_udpSocket.IOControl(SIO_UDP_CONNRESET, new byte[] { 0 }, null);
106 m_log.Debug("[UDPBASE]: SIO_UDP_CONNRESET flag set");
408 } 107 }
409 catch (SocketException) 108 catch (SocketException)
410 { 109 {
411 Logger.DebugLog("UDP SIO_UDP_CONNRESET flag not supported on this platform"); 110 m_log.Debug("[UDPBASE]: SIO_UDP_CONNRESET flag not supported on this platform, ignoring");
412 } 111 }
413 udpSocket.Bind(ipep); 112 m_udpSocket.Bind(ipep);
414 113
415 // we're not shutting down, we're starting up 114 // we're not shutting down, we're starting up
416 shutdownFlag = false; 115 m_shutdownFlag = false;
417 116
418 // kick off an async receive. The Start() method will return, the 117 // kick off an async receive. The Start() method will return, the
419 // actual receives will occur asynchronously and will be caught in 118 // actual receives will occur asynchronously and will be caught in
@@ -423,41 +122,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP
423 } 122 }
424 123
425 /// <summary> 124 /// <summary>
426 /// 125 /// Stops the UDP server
427 /// </summary> 126 /// </summary>
428 public void Stop() 127 public void Stop()
429 { 128 {
430 if (!shutdownFlag) 129 if (!m_shutdownFlag)
431 { 130 {
432 // wait indefinitely for a writer lock. Once this is called, the .NET runtime 131 // wait indefinitely for a writer lock. Once this is called, the .NET runtime
433 // will deny any more reader locks, in effect blocking all other send/receive 132 // will deny any more reader locks, in effect blocking all other send/receive
434 // threads. Once we have the lock, we set shutdownFlag to inform the other 133 // threads. Once we have the lock, we set shutdownFlag to inform the other
435 // threads that the socket is closed. 134 // threads that the socket is closed.
436 shutdownFlag = true; 135 m_shutdownFlag = true;
437 udpSocket.Close(); 136 m_udpSocket.Close();
438 } 137 }
439 } 138 }
440 139
441 /// <summary>
442 ///
443 /// </summary>
444 public bool IsRunning
445 {
446 get { return !shutdownFlag; }
447 }
448
449 private void AsyncBeginReceive() 140 private void AsyncBeginReceive()
450 { 141 {
451 // allocate a packet buffer 142 // allocate a packet buffer
452 //WrappedObject<UDPPacketBuffer> wrappedBuffer = Pool.CheckOut(); 143 //WrappedObject<UDPPacketBuffer> wrappedBuffer = Pool.CheckOut();
453 UDPPacketBuffer buf = new UDPPacketBuffer(); 144 UDPPacketBuffer buf = new UDPPacketBuffer();
454 145
455 if (!shutdownFlag) 146 if (!m_shutdownFlag)
456 { 147 {
457 try 148 try
458 { 149 {
459 // kick off an async read 150 // kick off an async read
460 udpSocket.BeginReceiveFrom( 151 m_udpSocket.BeginReceiveFrom(
461 //wrappedBuffer.Instance.Data, 152 //wrappedBuffer.Instance.Data,
462 buf.Data, 153 buf.Data,
463 0, 154 0,
@@ -472,13 +163,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
472 { 163 {
473 if (e.SocketErrorCode == SocketError.ConnectionReset) 164 if (e.SocketErrorCode == SocketError.ConnectionReset)
474 { 165 {
475 Logger.Log("SIO_UDP_CONNRESET was ignored, attempting to salvage the UDP listener on port " + udpPort, Helpers.LogLevel.Error); 166 m_log.Warn("[UDPBASE]: SIO_UDP_CONNRESET was ignored, attempting to salvage the UDP listener on port " + m_udpPort);
476 bool salvaged = false; 167 bool salvaged = false;
477 while (!salvaged) 168 while (!salvaged)
478 { 169 {
479 try 170 try
480 { 171 {
481 udpSocket.BeginReceiveFrom( 172 m_udpSocket.BeginReceiveFrom(
482 //wrappedBuffer.Instance.Data, 173 //wrappedBuffer.Instance.Data,
483 buf.Data, 174 buf.Data,
484 0, 175 0,
@@ -494,7 +185,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
494 catch (ObjectDisposedException) { return; } 185 catch (ObjectDisposedException) { return; }
495 } 186 }
496 187
497 Logger.Log("Salvaged the UDP listener on port " + udpPort, Helpers.LogLevel.Info); 188 m_log.Warn("[UDPBASE]: Salvaged the UDP listener on port " + m_udpPort);
498 } 189 }
499 } 190 }
500 catch (ObjectDisposedException) { } 191 catch (ObjectDisposedException) { }
@@ -505,7 +196,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
505 { 196 {
506 // Asynchronous receive operations will complete here through the call 197 // Asynchronous receive operations will complete here through the call
507 // to AsyncBeginReceive 198 // to AsyncBeginReceive
508 if (!shutdownFlag) 199 if (!m_shutdownFlag)
509 { 200 {
510 // start another receive - this keeps the server going! 201 // start another receive - this keeps the server going!
511 AsyncBeginReceive(); 202 AsyncBeginReceive();
@@ -520,7 +211,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
520 { 211 {
521 // get the length of data actually read from the socket, store it with the 212 // get the length of data actually read from the socket, store it with the
522 // buffer 213 // buffer
523 buffer.DataLength = udpSocket.EndReceiveFrom(iar, ref buffer.RemoteEndPoint); 214 buffer.DataLength = m_udpSocket.EndReceiveFrom(iar, ref buffer.RemoteEndPoint);
524 215
525 // call the abstract method PacketReceived(), passing the buffer that 216 // call the abstract method PacketReceived(), passing the buffer that
526 // has just been filled from the socket read. 217 // has just been filled from the socket read.
@@ -529,16 +220,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
529 catch (SocketException) { } 220 catch (SocketException) { }
530 catch (ObjectDisposedException) { } 221 catch (ObjectDisposedException) { }
531 //finally { wrappedBuffer.Dispose(); } 222 //finally { wrappedBuffer.Dispose(); }
223
532 } 224 }
533 } 225 }
534 226
535 public void AsyncBeginSend(UDPPacketBuffer buf) 227 public void AsyncBeginSend(UDPPacketBuffer buf)
536 { 228 {
537 if (!shutdownFlag) 229 if (!m_shutdownFlag)
538 { 230 {
539 try 231 try
540 { 232 {
541 udpSocket.BeginSendTo( 233 m_udpSocket.BeginSendTo(
542 buf.Data, 234 buf.Data,
543 0, 235 0,
544 buf.DataLength, 236 buf.DataLength,
@@ -557,7 +249,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
557 try 249 try
558 { 250 {
559 UDPPacketBuffer buf = (UDPPacketBuffer)result.AsyncState; 251 UDPPacketBuffer buf = (UDPPacketBuffer)result.AsyncState;
560 int bytesSent = udpSocket.EndSendTo(result); 252 int bytesSent = m_udpSocket.EndSendTo(result);
561 253
562 PacketSent(buf, bytesSent); 254 PacketSent(buf, bytesSent);
563 } 255 }
@@ -566,4 +258,3 @@ namespace OpenSim.Region.ClientStack.LindenUDP
566 } 258 }
567 } 259 }
568} 260}
569
diff --git a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs
index 195ca57..f3242c1 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs
@@ -103,6 +103,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
103 } 103 }
104 104
105 /// <summary> 105 /// <summary>
106 /// Removes all elements from the collection
107 /// </summary>
108 public void Clear()
109 {
110 lock (SyncRoot)
111 packets.Clear();
112 }
113
114 /// <summary>
106 /// Gets the packet with the lowest sequence number 115 /// Gets the packet with the lowest sequence number
107 /// </summary> 116 /// </summary>
108 /// <returns>The packet with the lowest sequence number, or null if the 117 /// <returns>The packet with the lowest sequence number, or null if the
diff --git a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
index f941728..7855862 100644
--- a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
@@ -36,6 +36,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
36{ 36{
37 public class GodsModule : IRegionModule, IGodsModule 37 public class GodsModule : IRegionModule, IGodsModule
38 { 38 {
39 /// <summary>Special UUID for actions that apply to all agents</summary>
40 private static readonly UUID ALL_AGENTS = new UUID("44e87126-e794-4ded-05b3-7c42da3d5cdb");
41
39 protected Scene m_scene; 42 protected Scene m_scene;
40 protected IDialogModule m_dialogModule; 43 protected IDialogModule m_dialogModule;
41 44
@@ -99,8 +102,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
99 /// <param name="reason">The message to send to the user after it's been turned into a field</param> 102 /// <param name="reason">The message to send to the user after it's been turned into a field</param>
100 public void KickUser(UUID godID, UUID sessionID, UUID agentID, uint kickflags, byte[] reason) 103 public void KickUser(UUID godID, UUID sessionID, UUID agentID, uint kickflags, byte[] reason)
101 { 104 {
102 // For some reason the client sends this seemingly hard coded UUID for kicking everyone. Dun-know. 105 UUID kickUserID = ALL_AGENTS;
103 UUID kickUserID = new UUID("44e87126e7944ded05b37c42da3d5cdb");
104 106
105 ScenePresence sp = m_scene.GetScenePresence(agentID); 107 ScenePresence sp = m_scene.GetScenePresence(agentID);
106 108
@@ -110,15 +112,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
110 { 112 {
111 if (agentID == kickUserID) 113 if (agentID == kickUserID)
112 { 114 {
113 m_scene.ClientManager.ForEachClient( 115 string reasonStr = Utils.BytesToString(reason);
116
117 m_scene.ClientManager.ForEach(
114 delegate(IClientAPI controller) 118 delegate(IClientAPI controller)
115 { 119 {
116 if (controller.AgentId != godID) 120 if (controller.AgentId != godID)
117 controller.Kick(Utils.BytesToString(reason)); 121 controller.Kick(reasonStr);
118 } 122 }
119 ); 123 );
120 124
121 // This is a bit crude. It seems the client will be null before it actually stops the thread 125 // This is a bit crude. It seems the client will be null before it actually stops the thread
122 // The thread will kill itself eventually :/ 126 // The thread will kill itself eventually :/
123 // Is there another way to make sure *all* clients get this 'inter region' message? 127 // Is there another way to make sure *all* clients get this 'inter region' message?
124 m_scene.ForEachScenePresence( 128 m_scene.ForEachScenePresence(
@@ -128,7 +132,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
128 { 132 {
129 // Possibly this should really be p.Close() though that method doesn't send a close 133 // Possibly this should really be p.Close() though that method doesn't send a close
130 // to the client 134 // to the client
131 p.ControllingClient.Close(true); 135 p.ControllingClient.Close();
132 } 136 }
133 } 137 }
134 ); 138 );
@@ -138,7 +142,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
138 m_scene.SceneGraph.removeUserCount(!sp.IsChildAgent); 142 m_scene.SceneGraph.removeUserCount(!sp.IsChildAgent);
139 143
140 sp.ControllingClient.Kick(Utils.BytesToString(reason)); 144 sp.ControllingClient.Kick(Utils.BytesToString(reason));
141 sp.ControllingClient.Close(true); 145 sp.ControllingClient.Close();
142 } 146 }
143 } 147 }
144 else 148 else
diff --git a/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs b/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs
index 7d6f150..d636b1c 100644
--- a/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs
+++ b/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs
@@ -1267,7 +1267,7 @@ namespace OpenSim.Region.CoreModules.InterGrid
1267 if (avToBeKilled.IsChildAgent) 1267 if (avToBeKilled.IsChildAgent)
1268 { 1268 {
1269 m_mod.DeleteOGPState(avUUID); 1269 m_mod.DeleteOGPState(avUUID);
1270 avToBeKilled.ControllingClient.Close(true); 1270 avToBeKilled.ControllingClient.Close();
1271 } 1271 }
1272 } 1272 }
1273 } 1273 }
diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
index b885420..9b565ed 100644
--- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
@@ -57,7 +57,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
57 public string body; 57 public string body;
58 public int responseCode; 58 public int responseCode;
59 public string responseBody; 59 public string responseBody;
60 public ManualResetEvent ev; 60 //public ManualResetEvent ev;
61 public bool requestDone; 61 public bool requestDone;
62 public int startTime; 62 public int startTime;
63 public string uri; 63 public string uri;
@@ -456,7 +456,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
456 requestData.headers["x-query-string"] = queryString; 456 requestData.headers["x-query-string"] = queryString;
457 requestData.headers["x-script-url"] = url.url; 457 requestData.headers["x-script-url"] = url.url;
458 458
459 requestData.ev = new ManualResetEvent(false); 459 //requestData.ev = new ManualResetEvent(false);
460 lock (url.requests) 460 lock (url.requests)
461 { 461 {
462 url.requests.Add(requestID, requestData); 462 url.requests.Add(requestID, requestData);
diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
index 8ad4844..d651fd4 100644
--- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
+++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
@@ -813,7 +813,7 @@ namespace OpenSim.Region.Examples.SimpleModule
813 { 813 {
814 } 814 }
815 815
816 public void Close(bool ShutdownCircuit) 816 public void Close()
817 { 817 {
818 } 818 }
819 819
@@ -833,6 +833,11 @@ namespace OpenSim.Region.Examples.SimpleModule
833 set { m_circuitCode = value; } 833 set { m_circuitCode = value; }
834 } 834 }
835 835
836 public IPEndPoint RemoteEndPoint
837 {
838 get { return new IPEndPoint(IPAddress.Loopback, (ushort)m_circuitCode); }
839 }
840
836 public void SendBlueBoxMessage(UUID FromAvatarID, String FromAvatarName, String Message) 841 public void SendBlueBoxMessage(UUID FromAvatarID, String FromAvatarName, String Message)
837 { 842 {
838 843
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index 4ae4dc3..ac89f7b 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -390,6 +390,32 @@ namespace OpenSim.Region.Framework.Scenes
390 EventManager.TriggerScriptReset(part.LocalId, itemID); 390 EventManager.TriggerScriptReset(part.LocalId, itemID);
391 } 391 }
392 } 392 }
393
394 void ProcessViewerEffect(IClientAPI remoteClient, List<ViewerEffectEventHandlerArg> args)
395 {
396 // TODO: don't create new blocks if recycling an old packet
397 List<ViewerEffectPacket.EffectBlock> effectBlock = new List<ViewerEffectPacket.EffectBlock>();
398 for (int i = 0; i < args.Count; i++)
399 {
400 ViewerEffectPacket.EffectBlock effect = new ViewerEffectPacket.EffectBlock();
401 effect.AgentID = args[i].AgentID;
402 effect.Color = args[i].Color;
403 effect.Duration = args[i].Duration;
404 effect.ID = args[i].ID;
405 effect.Type = args[i].Type;
406 effect.TypeData = args[i].TypeData;
407 effectBlock.Add(effect);
408 }
409 ViewerEffectPacket.EffectBlock[] effectBlockArray = effectBlock.ToArray();
410
411 ClientManager.ForEach(
412 delegate(IClientAPI client)
413 {
414 if (client.AgentId != remoteClient.AgentId)
415 client.SendViewerEffect(effectBlockArray);
416 }
417 );
418 }
393 419
394 /// <summary> 420 /// <summary>
395 /// Handle a fetch inventory request from the client 421 /// Handle a fetch inventory request from the client
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 0f351ce..9f14761 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -117,6 +117,8 @@ namespace OpenSim.Region.Framework.Scenes
117 private volatile bool m_backingup = false; 117 private volatile bool m_backingup = false;
118 118
119 private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>(); 119 private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>();
120
121 private Dictionary<UUID, SceneObjectGroup> m_groupsWithTargets = new Dictionary<UUID, SceneObjectGroup>();
120 122
121 protected string m_simulatorVersion = "OpenSimulator Server"; 123 protected string m_simulatorVersion = "OpenSimulator Server";
122 124
@@ -246,8 +248,7 @@ namespace OpenSim.Region.Framework.Scenes
246 248
247 private int m_update_physics = 1; 249 private int m_update_physics = 1;
248 private int m_update_entitymovement = 1; 250 private int m_update_entitymovement = 1;
249 private int m_update_entities = 1; // Run through all objects checking for updates 251 private int m_update_objects = 1; // Update objects which have scheduled themselves for updates
250 private int m_update_entitiesquick = 200; // Run through objects that have scheduled updates checking for updates
251 private int m_update_presences = 1; // Update scene presence movements 252 private int m_update_presences = 1; // Update scene presence movements
252 private int m_update_events = 1; 253 private int m_update_events = 1;
253 private int m_update_backup = 200; 254 private int m_update_backup = 200;
@@ -867,7 +868,7 @@ namespace OpenSim.Region.Framework.Scenes
867 Thread.Sleep(500); 868 Thread.Sleep(500);
868 869
869 // Stop all client threads. 870 // Stop all client threads.
870 ForEachScenePresence(delegate(ScenePresence avatar) { avatar.ControllingClient.Close(true); }); 871 ForEachScenePresence(delegate(ScenePresence avatar) { avatar.ControllingClient.Close(); });
871 872
872 // Stop updating the scene objects and agents. 873 // Stop updating the scene objects and agents.
873 //m_heartbeatTimer.Close(); 874 //m_heartbeatTimer.Close();
@@ -979,28 +980,7 @@ namespace OpenSim.Region.Framework.Scenes
979 maintc = Environment.TickCount; 980 maintc = Environment.TickCount;
980 981
981 TimeSpan SinceLastFrame = DateTime.Now - m_lastupdate; 982 TimeSpan SinceLastFrame = DateTime.Now - m_lastupdate;
982 // Aquire a lock so only one update call happens at once
983 //updateLock.WaitOne();
984 float physicsFPS = 0; 983 float physicsFPS = 0;
985 //m_log.Info("sadfadf" + m_neighbours.Count.ToString());
986 int agentsInScene = m_sceneGraph.GetRootAgentCount() + m_sceneGraph.GetChildAgentCount();
987
988 if (agentsInScene > 21)
989 {
990 if (m_update_entities == 1)
991 {
992 m_update_entities = 5;
993 StatsReporter.SetUpdateMS(6000);
994 }
995 }
996 else
997 {
998 if (m_update_entities == 5)
999 {
1000 m_update_entities = 1;
1001 StatsReporter.SetUpdateMS(3000);
1002 }
1003 }
1004 984
1005 frameMS = Environment.TickCount; 985 frameMS = Environment.TickCount;
1006 try 986 try
@@ -1013,30 +993,17 @@ namespace OpenSim.Region.Framework.Scenes
1013 m_frame = 0; 993 m_frame = 0;
1014 994
1015 otherMS = Environment.TickCount; 995 otherMS = Environment.TickCount;
1016 // run through all entities looking for updates (slow)
1017 if (m_frame % m_update_entities == 0)
1018 {
1019 /* // Adam Experimental
1020 if (m_updateEntitiesThread == null)
1021 {
1022 m_updateEntitiesThread = new Thread(m_sceneGraph.UpdateEntities);
1023
1024 ThreadTracker.Add(m_updateEntitiesThread);
1025 }
1026
1027 if (m_updateEntitiesThread.ThreadState == ThreadState.Stopped)
1028 m_updateEntitiesThread.Start();
1029 */
1030 996
1031 m_sceneGraph.UpdateEntities(); 997 // Check if any objects have reached their targets
1032 } 998 CheckAtTargets();
999
1000 // Update SceneObjectGroups that have scheduled themselves for updates
1001 // Objects queue their updates onto all scene presences
1002 if (m_frame % m_update_objects == 0)
1003 m_sceneGraph.UpdateObjectGroups();
1033 1004
1034 // run through entities that have scheduled themselves for 1005 // Run through all ScenePresences looking for updates
1035 // updates looking for updates(faster) 1006 // Presence updates and queued object updates for each presence are sent to clients
1036 if (m_frame % m_update_entitiesquick == 0)
1037 m_sceneGraph.ProcessUpdates();
1038
1039 // Run through scenepresences looking for updates
1040 if (m_frame % m_update_presences == 0) 1007 if (m_frame % m_update_presences == 0)
1041 m_sceneGraph.UpdatePresences(); 1008 m_sceneGraph.UpdatePresences();
1042 1009
@@ -1140,6 +1107,31 @@ namespace OpenSim.Region.Framework.Scenes
1140 } 1107 }
1141 } 1108 }
1142 1109
1110
1111 public void AddGroupTarget(SceneObjectGroup grp)
1112 {
1113 lock(m_groupsWithTargets)
1114 m_groupsWithTargets[grp.UUID] = grp;
1115 }
1116
1117 public void RemoveGroupTarget(SceneObjectGroup grp)
1118 {
1119 lock(m_groupsWithTargets)
1120 m_groupsWithTargets.Remove(grp.UUID);
1121 }
1122
1123 private void CheckAtTargets()
1124 {
1125 lock (m_groupsWithTargets)
1126 {
1127 foreach (KeyValuePair<UUID, SceneObjectGroup> kvp in m_groupsWithTargets)
1128 {
1129 kvp.Value.checkAtTargets();
1130 }
1131 }
1132 }
1133
1134
1143 /// <summary> 1135 /// <summary>
1144 /// Send out simstats data to all clients 1136 /// Send out simstats data to all clients
1145 /// </summary> 1137 /// </summary>
@@ -1186,10 +1178,10 @@ namespace OpenSim.Region.Framework.Scenes
1186 if (!m_backingup) 1178 if (!m_backingup)
1187 { 1179 {
1188 m_backingup = true; 1180 m_backingup = true;
1189 Thread backupthread = new Thread(Backup); 1181
1190 backupthread.Name = "BackupWriter"; 1182 System.ComponentModel.BackgroundWorker backupWorker = new System.ComponentModel.BackgroundWorker();
1191 backupthread.IsBackground = true; 1183 backupWorker.DoWork += delegate(object sender, System.ComponentModel.DoWorkEventArgs e) { Backup(); };
1192 backupthread.Start(); 1184 backupWorker.RunWorkerAsync();
1193 } 1185 }
1194 } 1186 }
1195 1187
@@ -2435,6 +2427,8 @@ namespace OpenSim.Region.Framework.Scenes
2435 /// <param name="client"></param> 2427 /// <param name="client"></param>
2436 public override void AddNewClient(IClientAPI client) 2428 public override void AddNewClient(IClientAPI client)
2437 { 2429 {
2430 ClientManager.Add(client);
2431
2438 CheckHeartbeat(); 2432 CheckHeartbeat();
2439 SubscribeToClientEvents(client); 2433 SubscribeToClientEvents(client);
2440 ScenePresence presence; 2434 ScenePresence presence;
@@ -2644,6 +2638,7 @@ namespace OpenSim.Region.Framework.Scenes
2644 public virtual void SubscribeToClientNetworkEvents(IClientAPI client) 2638 public virtual void SubscribeToClientNetworkEvents(IClientAPI client)
2645 { 2639 {
2646 client.OnNetworkStatsUpdate += StatsReporter.AddPacketsStats; 2640 client.OnNetworkStatsUpdate += StatsReporter.AddPacketsStats;
2641 client.OnViewerEffect += ProcessViewerEffect;
2647 } 2642 }
2648 2643
2649 protected virtual void UnsubscribeToClientEvents(IClientAPI client) 2644 protected virtual void UnsubscribeToClientEvents(IClientAPI client)
@@ -2798,11 +2793,9 @@ namespace OpenSim.Region.Framework.Scenes
2798 public virtual void UnSubscribeToClientNetworkEvents(IClientAPI client) 2793 public virtual void UnSubscribeToClientNetworkEvents(IClientAPI client)
2799 { 2794 {
2800 client.OnNetworkStatsUpdate -= StatsReporter.AddPacketsStats; 2795 client.OnNetworkStatsUpdate -= StatsReporter.AddPacketsStats;
2796 client.OnViewerEffect -= ProcessViewerEffect;
2801 } 2797 }
2802 2798
2803
2804
2805
2806 /// <summary> 2799 /// <summary>
2807 /// Teleport an avatar to their home region 2800 /// Teleport an avatar to their home region
2808 /// </summary> 2801 /// </summary>
@@ -3075,7 +3068,9 @@ namespace OpenSim.Region.Framework.Scenes
3075 agentTransactions.RemoveAgentAssetTransactions(agentID); 3068 agentTransactions.RemoveAgentAssetTransactions(agentID);
3076 } 3069 }
3077 3070
3071 // Remove the avatar from the scene
3078 m_sceneGraph.RemoveScenePresence(agentID); 3072 m_sceneGraph.RemoveScenePresence(agentID);
3073 ClientManager.Remove(agentID);
3079 3074
3080 try 3075 try
3081 { 3076 {
@@ -3125,16 +3120,6 @@ namespace OpenSim.Region.Framework.Scenes
3125 } 3120 }
3126 3121
3127 /// <summary> 3122 /// <summary>
3128 /// Closes all endpoints with the circuitcode provided.
3129 /// </summary>
3130 /// <param name="circuitcode">Circuit Code of the endpoint to close</param>
3131 public override void CloseAllAgents(uint circuitcode)
3132 {
3133 // Called by ClientView to kill all circuit codes
3134 ClientManager.CloseAllAgents(circuitcode);
3135 }
3136
3137 /// <summary>
3138 /// Inform all other ScenePresences on this Scene that someone else has changed position on the minimap. 3123 /// Inform all other ScenePresences on this Scene that someone else has changed position on the minimap.
3139 /// </summary> 3124 /// </summary>
3140 public void NotifyMyCoarseLocationChange() 3125 public void NotifyMyCoarseLocationChange()
@@ -3455,7 +3440,7 @@ namespace OpenSim.Region.Framework.Scenes
3455 loggingOffUser.ControllingClient.Kick(message); 3440 loggingOffUser.ControllingClient.Kick(message);
3456 // Give them a second to receive the message! 3441 // Give them a second to receive the message!
3457 Thread.Sleep(1000); 3442 Thread.Sleep(1000);
3458 loggingOffUser.ControllingClient.Close(true); 3443 loggingOffUser.ControllingClient.Close();
3459 } 3444 }
3460 else 3445 else
3461 { 3446 {
@@ -3626,7 +3611,7 @@ namespace OpenSim.Region.Framework.Scenes
3626 presence.ControllingClient.SendShutdownConnectionNotice(); 3611 presence.ControllingClient.SendShutdownConnectionNotice();
3627 } 3612 }
3628 3613
3629 presence.ControllingClient.Close(true); 3614 presence.ControllingClient.Close();
3630 return true; 3615 return true;
3631 } 3616 }
3632 3617
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index 0ac4ed4..cf5c3c8 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -196,8 +196,6 @@ namespace OpenSim.Region.Framework.Scenes
196 /// <param name="agentID"></param> 196 /// <param name="agentID"></param>
197 public abstract void RemoveClient(UUID agentID); 197 public abstract void RemoveClient(UUID agentID);
198 198
199 public abstract void CloseAllAgents(uint circuitcode);
200
201 #endregion 199 #endregion
202 200
203 /// <summary> 201 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 54ac792..9cd2247 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -77,7 +77,7 @@ namespace OpenSim.Region.Framework.Scenes
77 77
78 protected RegionInfo m_regInfo; 78 protected RegionInfo m_regInfo;
79 protected Scene m_parentScene; 79 protected Scene m_parentScene;
80 protected Dictionary<UUID, EntityBase> m_updateList = new Dictionary<UUID, EntityBase>(); 80 protected Dictionary<UUID, SceneObjectGroup> m_updateList = new Dictionary<UUID, SceneObjectGroup>();
81 protected int m_numRootAgents = 0; 81 protected int m_numRootAgents = 0;
82 protected int m_numPrim = 0; 82 protected int m_numPrim = 0;
83 protected int m_numChildAgents = 0; 83 protected int m_numChildAgents = 0;
@@ -155,16 +155,6 @@ namespace OpenSim.Region.Framework.Scenes
155 } 155 }
156 } 156 }
157 157
158 protected internal void UpdateEntities()
159 {
160 List<EntityBase> updateEntities = GetEntities();
161
162 foreach (EntityBase entity in updateEntities)
163 {
164 entity.Update();
165 }
166 }
167
168 protected internal void UpdatePresences() 158 protected internal void UpdatePresences()
169 { 159 {
170 List<ScenePresence> updateScenePresences = GetScenePresences(); 160 List<ScenePresence> updateScenePresences = GetScenePresences();
@@ -365,12 +355,12 @@ namespace OpenSim.Region.Framework.Scenes
365 } 355 }
366 356
367 /// <summary> 357 /// <summary>
368 /// Add an entity to the list of prims to process on the next update 358 /// Add an object to the list of prims to process on the next update
369 /// </summary> 359 /// </summary>
370 /// <param name="obj"> 360 /// <param name="obj">
371 /// A <see cref="EntityBase"/> 361 /// A <see cref="SceneObjectGroup"/>
372 /// </param> 362 /// </param>
373 protected internal void AddToUpdateList(EntityBase obj) 363 protected internal void AddToUpdateList(SceneObjectGroup obj)
374 { 364 {
375 lock (m_updateList) 365 lock (m_updateList)
376 { 366 {
@@ -381,18 +371,18 @@ namespace OpenSim.Region.Framework.Scenes
381 /// <summary> 371 /// <summary>
382 /// Process all pending updates 372 /// Process all pending updates
383 /// </summary> 373 /// </summary>
384 protected internal void ProcessUpdates() 374 protected internal void UpdateObjectGroups()
385 { 375 {
386 Dictionary<UUID, EntityBase> updates; 376 Dictionary<UUID, SceneObjectGroup> updates;
387 // Some updates add more updates to the updateList. 377 // Some updates add more updates to the updateList.
388 // Get the current list of updates and clear the list before iterating 378 // Get the current list of updates and clear the list before iterating
389 lock (m_updateList) 379 lock (m_updateList)
390 { 380 {
391 updates = new Dictionary<UUID, EntityBase>(m_updateList); 381 updates = new Dictionary<UUID, SceneObjectGroup>(m_updateList);
392 m_updateList.Clear(); 382 m_updateList.Clear();
393 } 383 }
394 // Go through all timers 384 // Go through all updates
395 foreach (KeyValuePair<UUID, EntityBase> kvp in updates) 385 foreach (KeyValuePair<UUID, SceneObjectGroup> kvp in updates)
396 { 386 {
397 // Don't abort the whole update if one entity happens to give us an exception. 387 // Don't abort the whole update if one entity happens to give us an exception.
398 try 388 try
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 6a10618..d4cef7d 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -1234,6 +1234,7 @@ namespace OpenSim.Region.Framework.Scenes
1234 { 1234 {
1235 lock (m_targets) 1235 lock (m_targets)
1236 m_targets.Clear(); 1236 m_targets.Clear();
1237 m_scene.RemoveGroupTarget(this);
1237 } 1238 }
1238 1239
1239 ScheduleGroupForFullUpdate(); 1240 ScheduleGroupForFullUpdate();
@@ -1864,12 +1865,6 @@ namespace OpenSim.Region.Framework.Scenes
1864 m_rootPart.UpdateFlag = 1; 1865 m_rootPart.UpdateFlag = 1;
1865 lastPhysGroupPos = AbsolutePosition; 1866 lastPhysGroupPos = AbsolutePosition;
1866 } 1867 }
1867 //foreach (SceneObjectPart part in m_parts.Values)
1868 //{
1869 //if (part.UpdateFlag == 0) part.UpdateFlag = 1;
1870 //}
1871
1872 checkAtTargets();
1873 1868
1874 if (UsePhysics && ((Math.Abs(lastPhysGroupRot.W - GroupRotation.W) > 0.1) 1869 if (UsePhysics && ((Math.Abs(lastPhysGroupRot.W - GroupRotation.W) > 0.1)
1875 || (Math.Abs(lastPhysGroupRot.X - GroupRotation.X) > 0.1) 1870 || (Math.Abs(lastPhysGroupRot.X - GroupRotation.X) > 0.1)
@@ -3114,6 +3109,7 @@ namespace OpenSim.Region.Framework.Scenes
3114 { 3109 {
3115 m_targets.Add(handle, waypoint); 3110 m_targets.Add(handle, waypoint);
3116 } 3111 }
3112 m_scene.AddGroupTarget(this);
3117 return (int)handle; 3113 return (int)handle;
3118 } 3114 }
3119 3115
@@ -3121,12 +3117,13 @@ namespace OpenSim.Region.Framework.Scenes
3121 { 3117 {
3122 lock (m_targets) 3118 lock (m_targets)
3123 { 3119 {
3124 if (m_targets.ContainsKey((uint)handle)) 3120 m_targets.Remove((uint)handle);
3125 m_targets.Remove((uint)handle); 3121 if (m_targets.Count == 0)
3122 m_scene.RemoveGroupTarget(this);
3126 } 3123 }
3127 } 3124 }
3128 3125
3129 private void checkAtTargets() 3126 public void checkAtTargets()
3130 { 3127 {
3131 if (m_scriptListens_atTarget || m_scriptListens_notAtTarget) 3128 if (m_scriptListens_atTarget || m_scriptListens_notAtTarget)
3132 { 3129 {
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneBaseTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneBaseTests.cs
index 5c9e66f..8230f32 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneBaseTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneBaseTests.cs
@@ -61,11 +61,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests
61 throw new NotImplementedException(); 61 throw new NotImplementedException();
62 } 62 }
63 63
64 public override void CloseAllAgents(uint circuitcode)
65 {
66 throw new NotImplementedException();
67 }
68
69 public override void OtherRegionUp(GridRegion otherRegion) 64 public override void OtherRegionUp(GridRegion otherRegion)
70 { 65 {
71 throw new NotImplementedException(); 66 throw new NotImplementedException();
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/IRCStackModule.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/IRCStackModule.cs
index 4b199ac..4c2a4b9 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/IRCStackModule.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/IRCStackModule.cs
@@ -64,7 +64,6 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView
64 void user_OnIRCReady(IRCClientView cv) 64 void user_OnIRCReady(IRCClientView cv)
65 { 65 {
66 m_log.Info("[IRCd] Adding user..."); 66 m_log.Info("[IRCd] Adding user...");
67 m_scene.ClientManager.Add(cv.CircuitCode, cv);
68 cv.Start(); 67 cv.Start();
69 m_log.Info("[IRCd] Added user to Scene"); 68 m_log.Info("[IRCd] Added user to Scene");
70 } 69 }
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index 4364627..a8acf0d 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -634,6 +634,12 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
634 { 634 {
635 get { return (uint)Util.RandomClass.Next(0,int.MaxValue); } 635 get { return (uint)Util.RandomClass.Next(0,int.MaxValue); }
636 } 636 }
637
638 public IPEndPoint RemoteEndPoint
639 {
640 get { return (IPEndPoint)m_client.Client.RemoteEndPoint; }
641 }
642
637#pragma warning disable 67 643#pragma warning disable 67
638 public event GenericMessage OnGenericMessage; 644 public event GenericMessage OnGenericMessage;
639 public event ImprovedInstantMessage OnInstantMessage; 645 public event ImprovedInstantMessage OnInstantMessage;
@@ -843,7 +849,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
843 849
844 } 850 }
845 851
846 public void Close(bool ShutdownCircuit) 852 public void Close()
847 { 853 {
848 Disconnect(); 854 Disconnect();
849 } 855 }
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs
index d6dacbc..b6513e2 100644
--- a/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs
+++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs
@@ -183,8 +183,9 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
183 public virtual void HideFromAll() 183 public virtual void HideFromAll()
184 { 184 {
185 foreach (SceneObjectPart part in m_Entity.Children.Values) 185 foreach (SceneObjectPart part in m_Entity.Children.Values)
186 m_Entity.Scene.ClientManager.ForEachClient(delegate(IClientAPI controller) 186 m_Entity.Scene.ClientManager.ForEach(
187 { controller.SendKillObject(m_Entity.RegionHandle, part.LocalId); } 187 delegate(IClientAPI controller)
188 { controller.SendKillObject(m_Entity.RegionHandle, part.LocalId); }
188 ); 189 );
189 } 190 }
190 191
@@ -201,8 +202,9 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
201 202
202 public void SendFullUpdateToAll() 203 public void SendFullUpdateToAll()
203 { 204 {
204 m_Entity.Scene.ClientManager.ForEachClient(delegate(IClientAPI controller) 205 m_Entity.Scene.ClientManager.ForEach(
205 { m_Entity.SendFullUpdateToClient(controller); } 206 delegate(IClientAPI controller)
207 { m_Entity.SendFullUpdateToClient(controller); }
206 ); 208 );
207 } 209 }
208 210
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
index ac8b98c..f7c63ac 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
@@ -825,7 +825,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
825 { 825 {
826 } 826 }
827 827
828 public void Close(bool ShutdownCircuit) 828 public void Close()
829 { 829 {
830 } 830 }
831 831
@@ -838,11 +838,21 @@ namespace OpenSim.Region.OptionalModules.World.NPC
838 } 838 }
839 839
840 private uint m_circuitCode; 840 private uint m_circuitCode;
841 private IPEndPoint m_remoteEndPoint;
841 842
842 public uint CircuitCode 843 public uint CircuitCode
843 { 844 {
844 get { return m_circuitCode; } 845 get { return m_circuitCode; }
845 set { m_circuitCode = value; } 846 set
847 {
848 m_circuitCode = value;
849 m_remoteEndPoint = new IPEndPoint(IPAddress.Loopback, (ushort)m_circuitCode);
850 }
851 }
852
853 public IPEndPoint RemoteEndPoint
854 {
855 get { return m_remoteEndPoint; }
846 } 856 }
847 857
848 public void SendBlueBoxMessage(UUID FromAvatarID, String FromAvatarName, String Message) 858 public void SendBlueBoxMessage(UUID FromAvatarID, String FromAvatarName, String Message)
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
index 30a2675..41a6255 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
@@ -155,7 +155,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC
155 NPCAvatar npcAvatar = new NPCAvatar(p_firstname, p_lastname, p_position, p_scene); 155 NPCAvatar npcAvatar = new NPCAvatar(p_firstname, p_lastname, p_position, p_scene);
156 npcAvatar.CircuitCode = (uint) Util.RandomClass.Next(0, int.MaxValue); 156 npcAvatar.CircuitCode = (uint) Util.RandomClass.Next(0, int.MaxValue);
157 157
158 p_scene.ClientManager.Add(npcAvatar.CircuitCode, npcAvatar);
159 p_scene.AddNewClient(npcAvatar); 158 p_scene.AddNewClient(npcAvatar);
160 159
161 ScenePresence sp; 160 ScenePresence sp;
diff --git a/OpenSim/Region/Physics/Meshing/PrimMesher.cs b/OpenSim/Region/Physics/Meshing/PrimMesher.cs
index a283840..47ce615 100644
--- a/OpenSim/Region/Physics/Meshing/PrimMesher.cs
+++ b/OpenSim/Region/Physics/Meshing/PrimMesher.cs
@@ -69,7 +69,7 @@ namespace PrimMesher
69 69
70 public Quat Identity() 70 public Quat Identity()
71 { 71 {
72 return new Quat(0.0f, 0.0f, 0.0f, 1.1f); 72 return new Quat(0.0f, 0.0f, 0.0f, 1.0f);
73 } 73 }
74 74
75 public float Length() 75 public float Length()
diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs
index 2b54890..5c838c5 100644
--- a/OpenSim/Tests/Common/Mock/TestClient.cs
+++ b/OpenSim/Tests/Common/Mock/TestClient.cs
@@ -393,6 +393,11 @@ namespace OpenSim.Tests.Common.Mock
393 set { m_circuitCode = value; } 393 set { m_circuitCode = value; }
394 } 394 }
395 395
396 public IPEndPoint RemoteEndPoint
397 {
398 get { return new IPEndPoint(IPAddress.Loopback, (ushort)m_circuitCode); }
399 }
400
396 /// <summary> 401 /// <summary>
397 /// Constructor 402 /// Constructor
398 /// </summary> 403 /// </summary>
@@ -865,7 +870,7 @@ namespace OpenSim.Tests.Common.Mock
865 { 870 {
866 } 871 }
867 872
868 public void Close(bool ShutdownCircuit) 873 public void Close()
869 { 874 {
870 m_scene.RemoveClient(AgentId); 875 m_scene.RemoveClient(AgentId);
871 } 876 }
diff --git a/ThirdPartyLicenses/BclExtras.txt b/ThirdPartyLicenses/BclExtras.txt
new file mode 100644
index 0000000..a8a0292
--- /dev/null
+++ b/ThirdPartyLicenses/BclExtras.txt
@@ -0,0 +1,60 @@
1MICROSOFT PUBLIC LICENSE (Ms-PL)
2
3This license governs use of the accompanying software. If you use the software,
4you accept this license. If you do not accept the license, do not use the
5software.
6
71. Definitions
8
9The terms "reproduce," "reproduction," "derivative works," and "distribution"
10have the same meaning here as under U.S. copyright law.
11
12A "contribution" is the original software, or any additions or changes to the
13software.
14
15A "contributor" is any person that distributes its contribution under this
16license.
17
18"Licensed patents" are a contributor's patent claims that read directly on its
19contribution.
20
212. Grant of Rights
22
23(A) Copyright Grant- Subject to the terms of this license, including the license
24conditions and limitations in section 3, each contributor grants you a
25non-exclusive, worldwide, royalty-free copyright license to reproduce its
26contribution, prepare derivative works of its contribution, and distribute its
27contribution or any derivative works that you create.
28
29(B) Patent Grant- Subject to the terms of this license, including the license
30conditions and limitations in section 3, each contributor grants you a
31non-exclusive, worldwide, royalty-free license under its licensed patents to
32make, have made, use, sell, offer for sale, import, and/or otherwise dispose of
33its contribution in the software or derivative works of the contribution in the
34software.
35
363. Conditions and Limitations
37
38(A) No Trademark License- This license does not grant you rights to use any
39contributors' name, logo, or trademarks.
40
41(B) If you bring a patent claim against any contributor over patents that you
42claim are infringed by the software, your patent license from such contributor
43to the software ends automatically.
44
45(C) If you distribute any portion of the software, you must retain all
46copyright, patent, trademark, and attribution notices that are present in the
47software.
48
49(D) If you distribute any portion of the software in source code form, you may
50do so only under this license by including a complete copy of this license with
51your distribution. If you distribute any portion of the software in compiled or
52object code form, you may only do so under a license that complies with this
53license.
54
55(E) The software is licensed "as-is." You bear the risk of using it. The
56contributors give no express warranties, guarantees or conditions. You may have
57additional consumer rights under your local laws which this license cannot
58change. To the extent permitted under your local laws, the contributors exclude
59the implied warranties of merchantability, fitness for a particular purpose and
60non-infringement.
diff --git a/ThirdPartyLicenses/CSJ2K.txt b/ThirdPartyLicenses/CSJ2K.txt
new file mode 100644
index 0000000..3032548
--- /dev/null
+++ b/ThirdPartyLicenses/CSJ2K.txt
@@ -0,0 +1,28 @@
1Copyright (c) 1999/2000 JJ2000 Partners.
2
3This software module was originally developed by Raphaël Grosbois and
4Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel
5Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David
6Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research
7Centre France S.A) in the course of development of the JPEG2000
8standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This
9software module is an implementation of a part of the JPEG 2000
10Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio
11Systems AB and Canon Research Centre France S.A (collectively JJ2000
12Partners) agree not to assert against ISO/IEC and users of the JPEG
132000 Standard (Users) any of their rights under the copyright, not
14including other intellectual property rights, for this software module
15with respect to the usage by ISO/IEC and Users of this software module
16or modifications thereof for use in hardware or software products
17claiming conformance to the JPEG 2000 Standard. Those intending to use
18this software module in hardware or software products are advised that
19their use may infringe existing patents. The original developers of
20this software module, JJ2000 Partners and ISO/IEC assume no liability
21for use of this software module or modifications thereof. No license
22or right to this software module is granted for non JPEG 2000 Standard
23conforming products. JJ2000 Partners have full right to use this
24software module for his/her own purpose, assign or donate this
25software module to any third party and to inhibit third parties from
26using this software module for non JPEG 2000 Standard conforming
27products. This copyright notice must be included in all copies or
28derivative works of this software module.
diff --git a/bin/BclExtras.dll b/bin/BclExtras.dll
new file mode 100644
index 0000000..505cf01
--- /dev/null
+++ b/bin/BclExtras.dll
Binary files differ
diff --git a/prebuild.xml b/prebuild.xml
index bba54f3..1a491a7 100644
--- a/prebuild.xml
+++ b/prebuild.xml
@@ -135,6 +135,7 @@
135 <Reference name="System.Xml"/> 135 <Reference name="System.Xml"/>
136 <Reference name="System.Data"/> 136 <Reference name="System.Data"/>
137 <Reference name="System.Drawing"/> 137 <Reference name="System.Drawing"/>
138 <Reference name="BclExtras.dll"/>
138 <Reference name="OpenMetaverseTypes.dll"/> 139 <Reference name="OpenMetaverseTypes.dll"/>
139 <Reference name="OpenMetaverse.dll"/> 140 <Reference name="OpenMetaverse.dll"/>
140 <Reference name="OpenMetaverse.StructuredData.dll"/> 141 <Reference name="OpenMetaverse.StructuredData.dll"/>
@@ -1767,6 +1768,7 @@
1767 <Reference name="OpenSim.Region.Communications.Local"/> 1768 <Reference name="OpenSim.Region.Communications.Local"/>
1768 <Reference name="OpenSim.Region.Physics.Manager"/> 1769 <Reference name="OpenSim.Region.Physics.Manager"/>
1769 <Reference name="OpenSim.Services.Interfaces"/> 1770 <Reference name="OpenSim.Services.Interfaces"/>
1771 <Reference name="BclExtras.dll"/>
1770 <Reference name="XMLRPC.dll"/> 1772 <Reference name="XMLRPC.dll"/>
1771 <Reference name="Nini.dll" /> 1773 <Reference name="Nini.dll" />
1772 <Reference name="log4net.dll"/> 1774 <Reference name="log4net.dll"/>
@@ -3495,7 +3497,6 @@
3495 <Reference name="OpenSim.Tests.Common"/> 3497 <Reference name="OpenSim.Tests.Common"/>
3496 <Reference name="OpenSim.Framework"/> 3498 <Reference name="OpenSim.Framework"/>
3497 <Reference name="OpenSim.Framework.Serialization"/> 3499 <Reference name="OpenSim.Framework.Serialization"/>
3498 <Reference name="OpenSim.Framework.Serialization.External"/>
3499 <Reference name="log4net.dll"/> 3500 <Reference name="log4net.dll"/>
3500 <Reference name="nunit.framework.dll" /> 3501 <Reference name="nunit.framework.dll" />
3501 3502