aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
Diffstat (limited to '')
-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.cs274
-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.cs13
-rw-r--r--OpenSim/Region/Application/OpenSim.cs24
-rw-r--r--OpenSim/Region/Application/OpenSimBackground.cs1
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs25
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs618
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs71
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs242
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs282
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs415
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs496
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs97
-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/Services/AssetService/AssetService.cs17
-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--bin/OpenSim.ini.example65
-rw-r--r--prebuild.xml3
45 files changed, 1475 insertions, 1705 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..61b59e7 100644
--- a/OpenSim/Framework/ClientManager.cs
+++ b/OpenSim/Framework/ClientManager.cs
@@ -28,193 +28,195 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using log4net; 31using System.Net;
32using OpenMetaverse; 32using OpenMetaverse;
33using OpenMetaverse.Packets; 33using OpenMetaverse.Packets;
34 34
35namespace OpenSim.Framework 35namespace OpenSim.Framework
36{ 36{
37 public delegate void ForEachClientDelegate(IClientAPI client); 37 /// <summary>
38 38 /// Maps from client AgentID and RemoteEndPoint values to IClientAPI
39 /// references for all of the connected clients
40 /// </summary>
39 public class ClientManager 41 public class ClientManager
40 { 42 {
41 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 43 /// <summary>A dictionary mapping from <seealso cref="UUID"/>
42 44 /// to <seealso cref="IClientAPI"/> references</summary>
43 private Dictionary<uint, IClientAPI> m_clients; 45 private Dictionary<UUID, IClientAPI> m_dict1;
46 /// <summary>A dictionary mapping from <seealso cref="IPEndPoint"/>
47 /// to <seealso cref="IClientAPI"/> references</summary>
48 private Dictionary<IPEndPoint, IClientAPI> m_dict2;
49 /// <summary>An immutable collection of <seealso cref="IClientAPI"/>
50 /// references</summary>
51 private IClientAPI[] m_array;
52 /// <summary>Synchronization object for writing to the collections</summary>
53 private object m_syncRoot = new object();
54
55 /// <summary>Number of clients in the collection</summary>
56 public int Count { get { return m_dict1.Count; } }
44 57
58 /// <summary>
59 /// Default constructor
60 /// </summary>
45 public ClientManager() 61 public ClientManager()
46 { 62 {
47 m_clients = new Dictionary<uint, IClientAPI>(); 63 m_dict1 = new Dictionary<UUID, IClientAPI>();
64 m_dict2 = new Dictionary<IPEndPoint, IClientAPI>();
65 m_array = new IClientAPI[0];
48 } 66 }
49 67
50 public void ForEachClient(ForEachClientDelegate whatToDo) 68 /// <summary>
69 /// Add a client reference to the collection if it does not already
70 /// exist
71 /// </summary>
72 /// <param name="value">Reference to the client object</param>
73 /// <returns>True if the client reference was successfully added,
74 /// otherwise false if the given key already existed in the collection</returns>
75 public bool Add(IClientAPI value)
51 { 76 {
52 IClientAPI[] LocalClients; 77 lock (m_syncRoot)
53 lock (m_clients)
54 { 78 {
55 LocalClients = new IClientAPI[m_clients.Count]; 79 if (m_dict1.ContainsKey(value.AgentId) || m_dict2.ContainsKey(value.RemoteEndPoint))
56 m_clients.Values.CopyTo(LocalClients, 0); 80 return false;
57 }
58 81
59 for (int i = 0; i < LocalClients.Length; i++) 82 m_dict1[value.AgentId] = value;
60 { 83 m_dict2[value.RemoteEndPoint] = value;
61 try
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 }
70 }
71 84
72 public void Remove(uint id) 85 IClientAPI[] oldArray = m_array;
73 { 86 int oldLength = oldArray.Length;
74 lock (m_clients)
75 {
76 m_clients.Remove(id);
77 }
78 }
79 87
80 public void Add(uint id, IClientAPI client) 88 IClientAPI[] newArray = new IClientAPI[oldLength + 1];
81 { 89 for (int i = 0; i < oldLength; i++)
82 lock (m_clients) 90 newArray[i] = oldArray[i];
83 { 91 newArray[oldLength] = value;
84 m_clients.Add(id, client); 92
93 m_array = newArray;
85 } 94 }
95
96 return true;
86 } 97 }
87 98
88 /// <summary> 99 /// <summary>
89 /// Pass incoming packet to client. 100 /// Remove a client from the collection
90 /// </summary> 101 /// </summary>
91 /// <param name="circuitCode">uint identifying the connection/client.</param> 102 /// <param name="key">UUID of the client to remove</param>
92 /// <param name="packet">object containing the packet.</param> 103 /// <returns>True if a client was removed, or false if the given UUID
93 public void InPacket(uint circuitCode, object packet) 104 /// was not present in the collection</returns>
94 { 105 public bool Remove(UUID key)
95 IClientAPI client;
96 bool tryGetRet = false;
97
98 lock (m_clients)
99 tryGetRet = m_clients.TryGetValue(circuitCode, out client);
100
101 if (tryGetRet)
102 {
103 client.InPacket(packet);
104 }
105 }
106
107 public void CloseAllAgents(uint circuitCode)
108 { 106 {
109 IClientAPI client; 107 lock (m_syncRoot)
110 bool tryGetRet = false;
111 lock (m_clients)
112 tryGetRet = m_clients.TryGetValue(circuitCode, out client);
113 if (tryGetRet)
114 { 108 {
115 CloseAllCircuits(client.AgentId); 109 IClientAPI value;
116 } 110 if (m_dict1.TryGetValue(key, out value))
117 } 111 {
112 m_dict1.Remove(key);
113 m_dict2.Remove(value.RemoteEndPoint);
118 114
119 public void CloseAllCircuits(UUID agentId) 115 IClientAPI[] oldArray = m_array;
120 { 116 int oldLength = oldArray.Length;
121 uint[] circuits = GetAllCircuits(agentId);
122 // We're using a for loop here so changes to the circuits don't cause it to completely fail.
123 117
124 for (int i = 0; i < circuits.Length; i++) 118 IClientAPI[] newArray = new IClientAPI[oldLength - 1];
125 { 119 int j = 0;
126 IClientAPI client; 120 for (int i = 0; i < oldLength; i++)
127 try
128 {
129 bool tryGetRet = false;
130 lock (m_clients)
131 tryGetRet = m_clients.TryGetValue(circuits[i], out client);
132 if (tryGetRet)
133 { 121 {
134 Remove(client.CircuitCode); 122 if (oldArray[i] != value)
135 client.Close(false); 123 newArray[j++] = oldArray[i];
136 } 124 }
137 } 125
138 catch (Exception e) 126 m_array = newArray;
139 { 127 return true;
140 m_log.Error(string.Format("[CLIENT]: Unable to shutdown circuit for: {0}\n Reason: {1}", agentId, e));
141 } 128 }
142 } 129 }
130
131 return false;
143 } 132 }
144 133
145 // [Obsolete("Using Obsolete to drive development is invalid. Obsolete presumes that something new has already been created to replace this.")] 134 /// <summary>
146 public uint[] GetAllCircuits(UUID agentId) 135 /// Resets the client collection
136 /// </summary>
137 public void Clear()
147 { 138 {
148 List<uint> circuits = new List<uint>(); 139 lock (m_syncRoot)
149 // Wasteful, I know
150 IClientAPI[] LocalClients = new IClientAPI[0];
151 lock (m_clients)
152 { 140 {
153 LocalClients = new IClientAPI[m_clients.Count]; 141 m_dict1.Clear();
154 m_clients.Values.CopyTo(LocalClients, 0); 142 m_dict2.Clear();
143 m_array = new IClientAPI[0];
155 } 144 }
156
157 for (int i = 0; i < LocalClients.Length; i++)
158 {
159 if (LocalClients[i].AgentId == agentId)
160 {
161 circuits.Add(LocalClients[i].CircuitCode);
162 }
163 }
164 return circuits.ToArray();
165 } 145 }
166 146
167 public List<uint> GetAllCircuitCodes() 147 /// <summary>
148 /// Checks if a UUID is in the collection
149 /// </summary>
150 /// <param name="key">UUID to check for</param>
151 /// <returns>True if the UUID was found in the collection, otherwise false</returns>
152 public bool ContainsKey(UUID key)
168 { 153 {
169 List<uint> circuits; 154 return m_dict1.ContainsKey(key);
170 155 }
171 lock (m_clients)
172 {
173 circuits = new List<uint>(m_clients.Keys);
174 }
175 156
176 return circuits; 157 /// <summary>
158 /// Checks if an endpoint is in the collection
159 /// </summary>
160 /// <param name="key">Endpoint to check for</param>
161 /// <returns>True if the endpoint was found in the collection, otherwise false</returns>
162 public bool ContainsKey(IPEndPoint key)
163 {
164 return m_dict2.ContainsKey(key);
177 } 165 }
178 166
179 public void ViewerEffectHandler(IClientAPI sender, List<ViewerEffectEventHandlerArg> args) 167 /// <summary>
168 /// Attempts to fetch a value out of the collection
169 /// </summary>
170 /// <param name="key">UUID of the client to retrieve</param>
171 /// <param name="value">Retrieved client, or null on lookup failure</param>
172 /// <returns>True if the lookup succeeded, otherwise false</returns>
173 public bool TryGetValue(UUID key, out IClientAPI value)
180 { 174 {
181 // TODO: don't create new blocks if recycling an old packet 175 try { return m_dict1.TryGetValue(key, out value); }
182 List<ViewerEffectPacket.EffectBlock> effectBlock = new List<ViewerEffectPacket.EffectBlock>(); 176 catch (Exception)
183 for (int i = 0; i < args.Count; i++)
184 { 177 {
185 ViewerEffectPacket.EffectBlock effect = new ViewerEffectPacket.EffectBlock(); 178 value = null;
186 effect.AgentID = args[i].AgentID; 179 return false;
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 } 180 }
194 ViewerEffectPacket.EffectBlock[] effectBlockArray = effectBlock.ToArray(); 181 }
195 182
196 IClientAPI[] LocalClients; 183 /// <summary>
197 lock (m_clients) 184 /// Attempts to fetch a value out of the collection
185 /// </summary>
186 /// <param name="key">Endpoint of the client to retrieve</param>
187 /// <param name="value">Retrieved client, or null on lookup failure</param>
188 /// <returns>True if the lookup succeeded, otherwise false</returns>
189 public bool TryGetValue(IPEndPoint key, out IClientAPI value)
190 {
191 try { return m_dict2.TryGetValue(key, out value); }
192 catch (Exception)
198 { 193 {
199 LocalClients = new IClientAPI[m_clients.Count]; 194 value = null;
200 m_clients.Values.CopyTo(LocalClients, 0); 195 return false;
201 } 196 }
197 }
202 198
203 for (int i = 0; i < LocalClients.Length; i++) 199 /// <summary>
204 { 200 /// Performs a given task in parallel for each of the elements in the
205 if (LocalClients[i].AgentId != sender.AgentId) 201 /// collection
206 { 202 /// </summary>
207 LocalClients[i].SendViewerEffect(effectBlockArray); 203 /// <param name="action">Action to perform on each element</param>
208 } 204 public void ForEach(Action<IClientAPI> action)
209 } 205 {
206 IClientAPI[] localArray = m_array;
207 Parallel.ForEach<IClientAPI>(localArray, action);
210 } 208 }
211 209
212 public bool TryGetClient(uint circuitId, out IClientAPI user) 210 /// <summary>
211 /// Performs a given task synchronously for each of the elements in
212 /// the collection
213 /// </summary>
214 /// <param name="action">Action to perform on each element</param>
215 public void ForEachSync(Action<IClientAPI> action)
213 { 216 {
214 lock (m_clients) 217 IClientAPI[] localArray = m_array;
215 { 218 for (int i = 0; i < localArray.Length; i++)
216 return m_clients.TryGetValue(circuitId, out user); 219 action(localArray[i]);
217 }
218 } 220 }
219 } 221 }
220} 222}
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..e21ff32 100644
--- a/OpenSim/Framework/ThrottleOutPacketType.cs
+++ b/OpenSim/Framework/ThrottleOutPacketType.cs
@@ -31,13 +31,24 @@ 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,
44 /// <summary>Any packets that do not fit into the other throttles</summary>
39 Task = 4, 45 Task = 4,
46 /// <summary>Texture assets</summary>
40 Texture = 5, 47 Texture = 5,
48 /// <summary>Non-texture assets</summary>
41 Asset = 6, 49 Asset = 6,
50 /// <summary>Avatar and primitive data</summary>
51 /// <remarks>This is a sub-category of Task</remarks>
52 State = 7,
42 } 53 }
43} 54}
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index 4d8409bb..ca6a2a3 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -239,6 +239,10 @@ namespace OpenSim
239 "show users [full]", 239 "show users [full]",
240 "Show user data", HandleShow); 240 "Show user data", HandleShow);
241 241
242 m_console.Commands.AddCommand("region", false, "show connections",
243 "show connections",
244 "Show connection data", HandleShow);
245
242 m_console.Commands.AddCommand("region", false, "show users full", 246 m_console.Commands.AddCommand("region", false, "show users full",
243 "show users full", 247 "show users full",
244 String.Empty, HandleShow); 248 String.Empty, HandleShow);
@@ -921,7 +925,25 @@ namespace OpenSim
921 regionName)); 925 regionName));
922 } 926 }
923 927
924 m_log.Info(""); 928 m_log.Info(String.Empty);
929 break;
930
931 case "connections":
932 System.Text.StringBuilder connections = new System.Text.StringBuilder("Connections:\n");
933 m_sceneManager.ForEachScene(
934 delegate(Scene scene)
935 {
936 scene.ClientManager.ForEachSync(
937 delegate(IClientAPI client)
938 {
939 connections.AppendFormat("{0}: {1} ({2}) from {3} on circuit {4}\n",
940 scene.RegionInfo.RegionName, client.Name, client.AgentId, client.RemoteEndPoint, client.CircuitCode);
941 }
942 );
943 }
944 );
945
946 m_log.Info(connections.ToString());
925 break; 947 break;
926 948
927 case "modules": 949 case "modules":
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/J2KImage.cs b/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs
index bb98f24..b53a2fb 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs
@@ -75,14 +75,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
75 m_imageManager = imageManager; 75 m_imageManager = imageManager;
76 } 76 }
77 77
78 public bool SendPackets(LLClientView client, int maxpack) 78 /// <summary>
79 /// Sends packets for this texture to a client until packetsToSend is
80 /// hit or the transfer completes
81 /// </summary>
82 /// <param name="client">Reference to the client that the packets are destined for</param>
83 /// <param name="packetsToSend">Maximum number of packets to send during this call</param>
84 /// <param name="packetsSent">Number of packets sent during this call</param>
85 /// <returns>True if the transfer completes at the current discard level, otherwise false</returns>
86 public bool SendPackets(LLClientView client, int packetsToSend, out int packetsSent)
79 { 87 {
80 if (client == null) 88 packetsSent = 0;
81 return false;
82 89
83 if (m_currentPacket <= m_stopPacket) 90 if (m_currentPacket <= m_stopPacket)
84 { 91 {
85 int count = 0;
86 bool sendMore = true; 92 bool sendMore = true;
87 93
88 if (!m_sentInfo || (m_currentPacket == 0)) 94 if (!m_sentInfo || (m_currentPacket == 0))
@@ -91,25 +97,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
91 97
92 m_sentInfo = true; 98 m_sentInfo = true;
93 ++m_currentPacket; 99 ++m_currentPacket;
94 ++count; 100 ++packetsSent;
95 } 101 }
96 if (m_currentPacket < 2) 102 if (m_currentPacket < 2)
97 { 103 {
98 m_currentPacket = 2; 104 m_currentPacket = 2;
99 } 105 }
100 106
101 while (sendMore && count < maxpack && m_currentPacket <= m_stopPacket) 107 while (sendMore && packetsSent < packetsToSend && m_currentPacket <= m_stopPacket)
102 { 108 {
103 sendMore = SendPacket(client); 109 sendMore = SendPacket(client);
104 ++m_currentPacket; 110 ++m_currentPacket;
105 ++count; 111 ++packetsSent;
106 } 112 }
107
108 if (m_currentPacket > m_stopPacket)
109 return true;
110 } 113 }
111 114
112 return false; 115 return (m_currentPacket > m_stopPacket);
113 } 116 }
114 117
115 public void RunUpdate() 118 public void RunUpdate()
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index d64f655..8487adc 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
@@ -111,17 +314,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
111 protected int m_primFullUpdatesPerPacket = 14; 314 protected int m_primFullUpdatesPerPacket = 14;
112 protected int m_primTerseUpdateRate = 10; 315 protected int m_primTerseUpdateRate = 10;
113 protected int m_primFullUpdateRate = 14; 316 protected int m_primFullUpdateRate = 14;
114 protected int m_textureSendLimit = 20;
115 protected int m_textureDataLimit = 10;
116 protected int m_avatarTerseUpdateRate = 50; 317 protected int m_avatarTerseUpdateRate = 50;
117 protected int m_avatarTerseUpdatesPerPacket = 5; 318 protected int m_avatarTerseUpdatesPerPacket = 5;
118 protected int m_packetMTU = 1400; 319 /// <summary>Number of texture packets to put on the queue each time the
320 /// OnQueueEmpty event is triggered for the texture category</summary>
321 protected int m_textureSendLimit = 20;
119 protected IAssetService m_assetService; 322 protected IAssetService m_assetService;
120 private IHyperAssetService m_hyperAssets; 323 private IHyperAssetService m_hyperAssets;
121 324
122 325
326 #endregion Class Members
327
123 #region Properties 328 #region Properties
124 329
330 public LLUDPClient UDPClient { get { return m_udpClient; } }
331 public IPEndPoint RemoteEndPoint { get { return m_udpClient.RemoteEndPoint; } }
125 public UUID SecureSessionId { get { return m_secureSessionId; } } 332 public UUID SecureSessionId { get { return m_secureSessionId; } }
126 public IScene Scene { get { return m_scene; } } 333 public IScene Scene { get { return m_scene; } }
127 public UUID SessionId { get { return m_sessionId; } } 334 public UUID SessionId { get { return m_sessionId; } }
@@ -202,51 +409,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
202 #region Client Methods 409 #region Client Methods
203 410
204 /// <summary> 411 /// <summary>
205 /// Close down the client view. This *must* be the last method called, since the last # 412 /// Shut down the client view
206 /// statement of CloseCleanup() aborts the thread.
207 /// </summary> 413 /// </summary>
208 /// <param name="shutdownCircuit"></param> 414 public void Close()
209 public void Close(bool shutdownCircuit)
210 { 415 {
211 m_log.DebugFormat( 416 m_log.DebugFormat(
212 "[CLIENT]: Close has been called with shutdownCircuit = {0} for {1} attached to scene {2}", 417 "[CLIENT]: Close has been called for {0} attached to scene {1}",
213 shutdownCircuit, Name, m_scene.RegionInfo.RegionName); 418 Name, m_scene.RegionInfo.RegionName);
214 419
420 // Send the STOP packet
421 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator);
422 OutPacket(disable, ThrottleOutPacketType.Unknown);
423
424 IsActive = false;
425
426 // Shutdown the image manager
215 if (m_imageManager != null) 427 if (m_imageManager != null)
216 m_imageManager.Close(); 428 m_imageManager.Close();
217 429
430 // Fire the callback for this connection closing
431 if (OnConnectionClosed != null)
432 OnConnectionClosed(this);
433
434 // Flush all of the packets out of the UDP server for this client
218 if (m_udpServer != null) 435 if (m_udpServer != null)
219 m_udpServer.Flush(); 436 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 437
237 private void CloseCleanup(bool shutdownCircuit) 438 // Remove ourselves from the scene
238 {
239 m_scene.RemoveClient(AgentId); 439 m_scene.RemoveClient(AgentId);
240 440
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 441 // Shut down timers. Thread Context of this method is murky. Lock all timers
251 if (m_avatarTerseUpdateTimer.Enabled) 442 if (m_avatarTerseUpdateTimer.Enabled)
252 lock (m_avatarTerseUpdateTimer) 443 lock (m_avatarTerseUpdateTimer)
@@ -258,43 +449,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
258 lock (m_primFullUpdateTimer) 449 lock (m_primFullUpdateTimer)
259 m_primFullUpdateTimer.Stop(); 450 m_primFullUpdateTimer.Stop();
260 451
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 452 // We can't reach into other scenes and close the connection
266 // We need to do this over grid communications 453 // We need to do this over grid communications
267 //m_scene.CloseAllAgents(CircuitCode); 454 //m_scene.CloseAllAgents(CircuitCode);
268 455
269 // If we're not shutting down the circuit, then this is the last time we'll go here. 456 m_avatarTerseUpdateTimer.Dispose();
270 // If we are shutting down the circuit, the UDP Server will come back here with 457 m_primTerseUpdateTimer.Dispose();
271 // ShutDownCircuit = false 458 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 459
290 //m_udpServer.OnPacketStats -= PopulateStats; 460 // Disable UDP handling for this client
291 m_udpClient.Shutdown(); 461 m_udpClient.Shutdown();
292 462
293 // wait for thread stoped 463 //m_log.InfoFormat("[CLIENTVIEW] Memory pre GC {0}", System.GC.GetTotalMemory(false));
294 // m_clientThread.Join(); 464 //GC.Collect();
295 465 //m_log.InfoFormat("[CLIENTVIEW] Memory post GC {0}", System.GC.GetTotalMemory(true));
296 // delete circuit code
297 //m_networkServer.CloseClient(this);
298 } 466 }
299 467
300 public void Kick(string message) 468 public void Kick(string message)
@@ -416,43 +584,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
416 return result; 584 return result;
417 } 585 }
418 586
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 587 #endregion Packet Handling
448 588
449 # region Setup 589 # region Setup
450 590
451 /// <summary> 591 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 { 592 {
457 m_avatarTerseUpdateTimer = new Timer(m_avatarTerseUpdateRate); 593 m_avatarTerseUpdateTimer = new Timer(m_avatarTerseUpdateRate);
458 m_avatarTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessAvatarTerseUpdates); 594 m_avatarTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessAvatarTerseUpdates);
@@ -471,262 +607,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
471 RefreshGroupMembership(); 607 RefreshGroupMembership();
472 } 608 }
473 609
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 610 # endregion
528 611
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) 612 public void ActivateGesture(UUID assetId, UUID gestureId)
731 { 613 {
732 } 614 }
@@ -1346,7 +1228,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1346 kill.ObjectData[0].ID = localID; 1228 kill.ObjectData[0].ID = localID;
1347 kill.Header.Reliable = true; 1229 kill.Header.Reliable = true;
1348 kill.Header.Zerocoded = true; 1230 kill.Header.Zerocoded = true;
1349 OutPacket(kill, ThrottleOutPacketType.Task); 1231 OutPacket(kill, ThrottleOutPacketType.State);
1350 } 1232 }
1351 1233
1352 /// <summary> 1234 /// <summary>
@@ -1940,7 +1822,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1940 sendXfer.XferID.ID = xferID; 1822 sendXfer.XferID.ID = xferID;
1941 sendXfer.XferID.Packet = packet; 1823 sendXfer.XferID.Packet = packet;
1942 sendXfer.DataPacket.Data = data; 1824 sendXfer.DataPacket.Data = data;
1943 OutPacket(sendXfer, ThrottleOutPacketType.Task); 1825 OutPacket(sendXfer, ThrottleOutPacketType.Asset);
1944 } 1826 }
1945 1827
1946 public void SendEconomyData(float EnergyEfficiency, int ObjectCapacity, int ObjectCount, int PriceEnergyUnit, 1828 public void SendEconomyData(float EnergyEfficiency, int ObjectCapacity, int ObjectCount, int PriceEnergyUnit,
@@ -2222,7 +2104,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2222 packet.AgentData.SessionID = SessionId; 2104 packet.AgentData.SessionID = SessionId;
2223 packet.Header.Reliable = false; 2105 packet.Header.Reliable = false;
2224 packet.Header.Zerocoded = true; 2106 packet.Header.Zerocoded = true;
2225 OutPacket(packet, ThrottleOutPacketType.Task); 2107 OutPacket(packet, ThrottleOutPacketType.State);
2226 } 2108 }
2227 2109
2228 public void SendAvatarProperties(UUID avatarID, string aboutText, string bornOn, Byte[] charterMember, 2110 public void SendAvatarProperties(UUID avatarID, string aboutText, string bornOn, Byte[] charterMember,
@@ -3245,7 +3127,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3245 3127
3246 avp.Sender.IsTrial = false; 3128 avp.Sender.IsTrial = false;
3247 avp.Sender.ID = agentID; 3129 avp.Sender.ID = agentID;
3248 OutPacket(avp, ThrottleOutPacketType.Task); 3130 OutPacket(avp, ThrottleOutPacketType.State);
3249 } 3131 }
3250 3132
3251 public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs) 3133 public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs)
@@ -3370,7 +3252,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3370 int length = 0; 3252 int length = 0;
3371 m_avatarTerseUpdates[count].ToBytes(blockbuffer, ref length); 3253 m_avatarTerseUpdates[count].ToBytes(blockbuffer, ref length);
3372 length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); 3254 length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer);
3373 if (size + length > m_packetMTU) 3255 if (size + length > Packet.MTU)
3374 break; 3256 break;
3375 size += length; 3257 size += length;
3376 } 3258 }
@@ -3385,6 +3267,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3385 3267
3386 terse.Header.Reliable = false; 3268 terse.Header.Reliable = false;
3387 terse.Header.Zerocoded = true; 3269 terse.Header.Zerocoded = true;
3270 // FIXME: Move this to ThrottleOutPacketType.State when the real prioritization code is committed
3388 OutPacket(terse, ThrottleOutPacketType.Task); 3271 OutPacket(terse, ThrottleOutPacketType.Task);
3389 3272
3390 if (m_avatarTerseUpdates.Count == 0) 3273 if (m_avatarTerseUpdates.Count == 0)
@@ -3575,7 +3458,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3575 void ProcessTextureRequests() 3458 void ProcessTextureRequests()
3576 { 3459 {
3577 if (m_imageManager != null) 3460 if (m_imageManager != null)
3578 m_imageManager.ProcessImageQueue(m_textureSendLimit, m_textureDataLimit); 3461 m_imageManager.ProcessImageQueue(m_textureSendLimit);
3579 } 3462 }
3580 3463
3581 void ProcessPrimFullUpdates(object sender, ElapsedEventArgs e) 3464 void ProcessPrimFullUpdates(object sender, ElapsedEventArgs e)
@@ -3614,7 +3497,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3614 int length = 0; 3497 int length = 0;
3615 m_primFullUpdates[count].ToBytes(blockbuffer, ref length); 3498 m_primFullUpdates[count].ToBytes(blockbuffer, ref length);
3616 length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); 3499 length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer);
3617 if (size + length > m_packetMTU) 3500 if (size + length > Packet.MTU)
3618 break; 3501 break;
3619 size += length; 3502 size += length;
3620 } 3503 }
@@ -3629,7 +3512,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3629 } 3512 }
3630 3513
3631 outPacket.Header.Zerocoded = true; 3514 outPacket.Header.Zerocoded = true;
3632 OutPacket(outPacket, ThrottleOutPacketType.Task); 3515 OutPacket(outPacket, ThrottleOutPacketType.State);
3633 3516
3634 if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled) 3517 if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled)
3635 lock (m_primFullUpdateTimer) 3518 lock (m_primFullUpdateTimer)
@@ -3702,7 +3585,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3702 int length = 0; 3585 int length = 0;
3703 m_primTerseUpdates[count].ToBytes(blockbuffer, ref length); 3586 m_primTerseUpdates[count].ToBytes(blockbuffer, ref length);
3704 length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); 3587 length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer);
3705 if (size + length > m_packetMTU) 3588 if (size + length > Packet.MTU)
3706 break; 3589 break;
3707 size += length; 3590 size += length;
3708 } 3591 }
@@ -3719,7 +3602,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3719 3602
3720 outPacket.Header.Reliable = false; 3603 outPacket.Header.Reliable = false;
3721 outPacket.Header.Zerocoded = true; 3604 outPacket.Header.Zerocoded = true;
3722 OutPacket(outPacket, ThrottleOutPacketType.Task); 3605 OutPacket(outPacket, ThrottleOutPacketType.State);
3723 3606
3724 if (m_primTerseUpdates.Count == 0) 3607 if (m_primTerseUpdates.Count == 0)
3725 lock (m_primTerseUpdateTimer) 3608 lock (m_primTerseUpdateTimer)
@@ -4805,7 +4688,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4805 4688
4806 public bool HandleObjectGroupRequest(IClientAPI sender, Packet Pack) 4689 public bool HandleObjectGroupRequest(IClientAPI sender, Packet Pack)
4807 { 4690 {
4808
4809 ObjectGroupPacket ogpack = (ObjectGroupPacket)Pack; 4691 ObjectGroupPacket ogpack = (ObjectGroupPacket)Pack;
4810 if (ogpack.AgentData.SessionID != SessionId) return false; 4692 if (ogpack.AgentData.SessionID != SessionId) return false;
4811 4693
@@ -10252,7 +10134,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10252 10134
10253 public void KillEndDone() 10135 public void KillEndDone()
10254 { 10136 {
10255 m_udpClient.Shutdown();
10256 } 10137 }
10257 10138
10258 #region IClientCore 10139 #region IClientCore
@@ -10295,15 +10176,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10295 { 10176 {
10296 Kick(reason); 10177 Kick(reason);
10297 Thread.Sleep(1000); 10178 Thread.Sleep(1000);
10298 Close(true); 10179 Close();
10299 } 10180 }
10300 10181
10301 public void Disconnect() 10182 public void Disconnect()
10302 { 10183 {
10303 Close(true); 10184 Close();
10304 } 10185 }
10305 10186
10306
10307 #endregion 10187 #endregion
10308 10188
10309 public void RefreshGroupMembership() 10189 public void RefreshGroupMembership()
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs b/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs
index 56d34e6..d25bf95 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs
@@ -167,47 +167,48 @@ namespace OpenSim.Region.ClientStack.LindenUDP
167 } 167 }
168 } 168 }
169 169
170 public bool ProcessImageQueue(int count, int maxpack) 170 public bool ProcessImageQueue(int packetsToSend)
171 { 171 {
172 J2KImage imagereq; 172 m_lastloopprocessed = DateTime.Now.Ticks;
173 int numCollected = 0; 173 int packetsSent = 0;
174 174
175 //lock (m_syncRoot) 175 while (packetsSent < packetsToSend)
176 //{ 176 {
177 m_lastloopprocessed = DateTime.Now.Ticks; 177 J2KImage image = GetHighestPriorityImage();
178 178
179 // This can happen during Close() 179 // If null was returned, the texture priority queue is currently empty
180 if (m_client == null) 180 if (image == null)
181 return false; 181 return false;
182
183 while ((imagereq = GetHighestPriorityImage()) != null)
184 {
185 if (imagereq.IsDecoded == true)
186 {
187 ++numCollected;
188 182
189 if (imagereq.SendPackets(m_client, maxpack)) 183 if (image.IsDecoded)
190 { 184 {
191 // Send complete. Destroy any knowledge of this transfer 185 int sent;
192 RemoveImageFromQueue(imagereq); 186 bool imageDone = image.SendPackets(m_client, packetsToSend - packetsSent, out sent);
193 } 187 packetsSent += sent;
194 }
195 188
196 if (numCollected == count) 189 // If the send is complete, destroy any knowledge of this transfer
197 break; 190 if (imageDone)
191 RemoveImageFromQueue(image);
198 } 192 }
199 //} 193 else
194 {
195 // TODO: This is a limitation of how LLImageManager is currently
196 // written. Undecoded textures should not be going into the priority
197 // queue, because a high priority undecoded texture will clog up the
198 // pipeline for a client
199 return true;
200 }
201 }
200 202
201 return m_priorityQueue.Count > 0; 203 return m_priorityQueue.Count > 0;
202 } 204 }
203 205
204 //Faux destructor 206 /// <summary>
207 /// Faux destructor
208 /// </summary>
205 public void Close() 209 public void Close()
206 { 210 {
207 m_shuttingdown = true; 211 m_shuttingdown = true;
208 m_j2kDecodeModule = null;
209 m_assetCache = null;
210 m_client = null;
211 } 212 }
212 213
213 #region Priority Queue Helpers 214 #region Priority Queue Helpers
@@ -218,13 +219,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
218 219
219 lock (m_syncRoot) 220 lock (m_syncRoot)
220 { 221 {
221
222 if (m_priorityQueue.Count > 0) 222 if (m_priorityQueue.Count > 0)
223 { 223 {
224 try 224 try { image = m_priorityQueue.FindMax(); }
225 {
226 image = m_priorityQueue.FindMax();
227 }
228 catch (Exception) { } 225 catch (Exception) { }
229 } 226 }
230 } 227 }
@@ -236,20 +233,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
236 image.PriorityQueueHandle = null; 233 image.PriorityQueueHandle = null;
237 234
238 lock (m_syncRoot) 235 lock (m_syncRoot)
239 try 236 try { m_priorityQueue.Add(ref image.PriorityQueueHandle, image); }
240 {
241 m_priorityQueue.Add(ref image.PriorityQueueHandle, image);
242 }
243 catch (Exception) { } 237 catch (Exception) { }
244 } 238 }
245 239
246 void RemoveImageFromQueue(J2KImage image) 240 void RemoveImageFromQueue(J2KImage image)
247 { 241 {
248 lock (m_syncRoot) 242 lock (m_syncRoot)
249 try 243 try { m_priorityQueue.Delete(image.PriorityQueueHandle); }
250 {
251 m_priorityQueue.Delete(image.PriorityQueueHandle);
252 }
253 catch (Exception) { } 244 catch (Exception) { }
254 } 245 }
255 246
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index 871e8e8..4eee6b6 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
@@ -28,8 +28,10 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Net; 30using System.Net;
31using log4net;
31using OpenSim.Framework; 32using OpenSim.Framework;
32using OpenMetaverse; 33using OpenMetaverse;
34using OpenMetaverse.Packets;
33 35
34namespace OpenSim.Region.ClientStack.LindenUDP 36namespace OpenSim.Region.ClientStack.LindenUDP
35{ 37{
@@ -59,9 +61,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
59 /// </summary> 61 /// </summary>
60 public sealed class LLUDPClient 62 public sealed class LLUDPClient
61 { 63 {
64 // TODO: Make this a config setting
65 /// <summary>Percentage of the task throttle category that is allocated to avatar and prim
66 /// state updates</summary>
67 const float STATE_TASK_PERCENTAGE = 0.8f;
68
69 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
70
62 /// <summary>The number of packet categories to throttle on. If a throttle category is added 71 /// <summary>The number of packet categories to throttle on. If a throttle category is added
63 /// or removed, this number must also change</summary> 72 /// or removed, this number must also change</summary>
64 const int THROTTLE_CATEGORY_COUNT = 7; 73 const int THROTTLE_CATEGORY_COUNT = 8;
65 74
66 /// <summary>Fired when updated networking stats are produced for this client</summary> 75 /// <summary>Fired when updated networking stats are produced for this client</summary>
67 public event PacketStats OnPacketStats; 76 public event PacketStats OnPacketStats;
@@ -80,10 +89,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
80 /// <summary>Packets we have sent that need to be ACKed by the client</summary> 89 /// <summary>Packets we have sent that need to be ACKed by the client</summary>
81 public readonly UnackedPacketCollection NeedAcks = new UnackedPacketCollection(); 90 public readonly UnackedPacketCollection NeedAcks = new UnackedPacketCollection();
82 /// <summary>ACKs that are queued up, waiting to be sent to the client</summary> 91 /// <summary>ACKs that are queued up, waiting to be sent to the client</summary>
83 public readonly LocklessQueue<uint> PendingAcks = new LocklessQueue<uint>(); 92 public readonly OpenSim.Framework.LocklessQueue<uint> PendingAcks = new OpenSim.Framework.LocklessQueue<uint>();
84 93
85 /// <summary>Reference to the IClientAPI for this client</summary>
86 public LLClientView ClientAPI;
87 /// <summary>Current packet sequence number</summary> 94 /// <summary>Current packet sequence number</summary>
88 public int CurrentSequence; 95 public int CurrentSequence;
89 /// <summary>Current ping sequence number</summary> 96 /// <summary>Current ping sequence number</summary>
@@ -123,21 +130,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
123 private int m_packetsSentReported; 130 private int m_packetsSentReported;
124 131
125 /// <summary>Throttle bucket for this agent's connection</summary> 132 /// <summary>Throttle bucket for this agent's connection</summary>
126 private readonly TokenBucket throttle; 133 private readonly TokenBucket m_throttle;
127 /// <summary>Throttle buckets for each packet category</summary> 134 /// <summary>Throttle buckets for each packet category</summary>
128 private readonly TokenBucket[] throttleCategories; 135 private readonly TokenBucket[] m_throttleCategories;
129 /// <summary>Throttle rate defaults and limits</summary> 136 /// <summary>Throttle rate defaults and limits</summary>
130 private readonly ThrottleRates defaultThrottleRates; 137 private readonly ThrottleRates m_defaultThrottleRates;
131 /// <summary>Outgoing queues for throttled packets</summary> 138 /// <summary>Outgoing queues for throttled packets</summary>
132 private readonly LocklessQueue<OutgoingPacket>[] packetOutboxes = new LocklessQueue<OutgoingPacket>[THROTTLE_CATEGORY_COUNT]; 139 private readonly OpenSim.Framework.LocklessQueue<OutgoingPacket>[] m_packetOutboxes = new OpenSim.Framework.LocklessQueue<OutgoingPacket>[THROTTLE_CATEGORY_COUNT];
133 /// <summary>A container that can hold one packet for each outbox, used to store 140 /// <summary>A container that can hold one packet for each outbox, used to store
134 /// dequeued packets that are being held for throttling</summary> 141 /// dequeued packets that are being held for throttling</summary>
135 private readonly OutgoingPacket[] nextPackets = new OutgoingPacket[THROTTLE_CATEGORY_COUNT]; 142 private readonly OutgoingPacket[] m_nextPackets = new OutgoingPacket[THROTTLE_CATEGORY_COUNT];
136 /// <summary>An optimization to store the length of dequeued packets being held 143 /// <summary>Flags to prevent queue empty callbacks from stacking up on
137 /// for throttling. This avoids expensive calls to Packet.Length</summary> 144 /// top of each other</summary>
138 private readonly int[] nextPacketLengths = new int[THROTTLE_CATEGORY_COUNT]; 145 private readonly bool[] m_onQueueEmptyRunning = new bool[THROTTLE_CATEGORY_COUNT];
139 /// <summary>A reference to the LLUDPServer that is managing this client</summary> 146 /// <summary>A reference to the LLUDPServer that is managing this client</summary>
140 private readonly LLUDPServer udpServer; 147 private readonly LLUDPServer m_udpServer;
141 148
142 /// <summary> 149 /// <summary>
143 /// Default constructor 150 /// Default constructor
@@ -151,24 +158,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
151 /// <param name="remoteEndPoint">Remote endpoint for this connection</param> 158 /// <param name="remoteEndPoint">Remote endpoint for this connection</param>
152 public LLUDPClient(LLUDPServer server, ThrottleRates rates, TokenBucket parentThrottle, uint circuitCode, UUID agentID, IPEndPoint remoteEndPoint) 159 public LLUDPClient(LLUDPServer server, ThrottleRates rates, TokenBucket parentThrottle, uint circuitCode, UUID agentID, IPEndPoint remoteEndPoint)
153 { 160 {
154 udpServer = server;
155 AgentID = agentID; 161 AgentID = agentID;
156 RemoteEndPoint = remoteEndPoint; 162 RemoteEndPoint = remoteEndPoint;
157 CircuitCode = circuitCode; 163 CircuitCode = circuitCode;
158 defaultThrottleRates = rates; 164 m_udpServer = server;
165 m_defaultThrottleRates = rates;
166 m_throttle = new TokenBucket(parentThrottle, rates.TotalLimit, rates.Total);
167 m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT];
159 168
160 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) 169 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
161 packetOutboxes[i] = new LocklessQueue<OutgoingPacket>(); 170 {
162 171 ThrottleOutPacketType type = (ThrottleOutPacketType)i;
163 throttle = new TokenBucket(parentThrottle, 0, 0); 172
164 throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; 173 m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>();
165 throttleCategories[(int)ThrottleOutPacketType.Resend] = new TokenBucket(throttle, rates.ResendLimit, rates.Resend); 174 m_throttleCategories[i] = new TokenBucket(m_throttle, rates.GetLimit(type), rates.GetRate(type));
166 throttleCategories[(int)ThrottleOutPacketType.Land] = new TokenBucket(throttle, rates.LandLimit, rates.Land); 175 }
167 throttleCategories[(int)ThrottleOutPacketType.Wind] = new TokenBucket(throttle, rates.WindLimit, rates.Wind);
168 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);
171 throttleCategories[(int)ThrottleOutPacketType.Asset] = new TokenBucket(throttle, rates.AssetLimit, rates.Asset);
172 176
173 // Set the granularity variable used for retransmission calculations to 177 // Set the granularity variable used for retransmission calculations to
174 // the measured resolution of Environment.TickCount 178 // the measured resolution of Environment.TickCount
@@ -176,6 +180,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
176 180
177 // Default the retransmission timeout to three seconds 181 // Default the retransmission timeout to three seconds
178 RTO = 3000; 182 RTO = 3000;
183
184 // Initialize this to a sane value to prevent early disconnects
185 TickLastPacketReceived = Environment.TickCount;
179 } 186 }
180 187
181 /// <summary> 188 /// <summary>
@@ -183,8 +190,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
183 /// </summary> 190 /// </summary>
184 public void Shutdown() 191 public void Shutdown()
185 { 192 {
186 // TODO: Do we need to invalidate the circuit?
187 IsConnected = false; 193 IsConnected = false;
194 NeedAcks.Clear();
195 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
196 {
197 m_packetOutboxes[i].Clear();
198 m_nextPackets[i] = null;
199 }
200 OnPacketStats = null;
201 OnQueueEmpty = null;
188 } 202 }
189 203
190 /// <summary> 204 /// <summary>
@@ -200,13 +214,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
200 info.pendingAcks = new Dictionary<uint, uint>(); 214 info.pendingAcks = new Dictionary<uint, uint>();
201 info.needAck = new Dictionary<uint, byte[]>(); 215 info.needAck = new Dictionary<uint, byte[]>();
202 216
203 info.resendThrottle = throttleCategories[(int)ThrottleOutPacketType.Resend].DripRate; 217 info.resendThrottle = m_throttleCategories[(int)ThrottleOutPacketType.Resend].DripRate;
204 info.landThrottle = throttleCategories[(int)ThrottleOutPacketType.Land].DripRate; 218 info.landThrottle = m_throttleCategories[(int)ThrottleOutPacketType.Land].DripRate;
205 info.windThrottle = throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate; 219 info.windThrottle = m_throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate;
206 info.cloudThrottle = throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate; 220 info.cloudThrottle = m_throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate;
207 info.taskThrottle = throttleCategories[(int)ThrottleOutPacketType.Task].DripRate; 221 info.taskThrottle = m_throttleCategories[(int)ThrottleOutPacketType.State].DripRate + m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate;
208 info.assetThrottle = throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate; 222 info.assetThrottle = m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate;
209 info.textureThrottle = throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate; 223 info.textureThrottle = m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate;
210 info.totalThrottle = info.resendThrottle + info.landThrottle + info.windThrottle + info.cloudThrottle + 224 info.totalThrottle = info.resendThrottle + info.landThrottle + info.windThrottle + info.cloudThrottle +
211 info.taskThrottle + info.assetThrottle + info.textureThrottle; 225 info.taskThrottle + info.assetThrottle + info.textureThrottle;
212 226
@@ -267,6 +281,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
267 adjData = throttleData; 281 adjData = throttleData;
268 } 282 }
269 283
284 // 0.125f converts from bits to bytes
270 int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; 285 int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
271 int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; 286 int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
272 int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; 287 int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
@@ -274,22 +289,40 @@ namespace OpenSim.Region.ClientStack.LindenUDP
274 int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; 289 int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
275 int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; 290 int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
276 int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); 291 int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
292 // State is a subcategory of task that we allocate a percentage to
293 int state = (int)((float)task * STATE_TASK_PERCENTAGE);
294 task -= state;
295
296 int ceiling = Int32.MaxValue;
297 if (m_defaultThrottleRates.Total != 0)
298 {
299 ceiling = m_defaultThrottleRates.Total;
300 if (ceiling < Packet.MTU) ceiling = Packet.MTU;
301 }
277 302
278 resend = (resend <= defaultThrottleRates.ResendLimit) ? resend : defaultThrottleRates.ResendLimit; 303 resend = Utils.Clamp(resend, Packet.MTU, ceiling);
279 land = (land <= defaultThrottleRates.LandLimit) ? land : defaultThrottleRates.LandLimit; 304 land = Utils.Clamp(land, Packet.MTU, ceiling);
280 wind = (wind <= defaultThrottleRates.WindLimit) ? wind : defaultThrottleRates.WindLimit; 305 wind = Utils.Clamp(wind, Packet.MTU, ceiling);
281 cloud = (cloud <= defaultThrottleRates.CloudLimit) ? cloud : defaultThrottleRates.CloudLimit; 306 cloud = Utils.Clamp(cloud, Packet.MTU, ceiling);
282 task = (task <= defaultThrottleRates.TaskLimit) ? task : defaultThrottleRates.TaskLimit; 307 task = Utils.Clamp(task, Packet.MTU, ceiling);
283 texture = (texture <= defaultThrottleRates.TextureLimit) ? texture : defaultThrottleRates.TextureLimit; 308 texture = Utils.Clamp(texture, Packet.MTU, ceiling);
284 asset = (asset <= defaultThrottleRates.AssetLimit) ? asset : defaultThrottleRates.AssetLimit; 309 asset = Utils.Clamp(asset, Packet.MTU, ceiling);
285 310 state = Utils.Clamp(state, Packet.MTU, ceiling);
286 SetThrottle(ThrottleOutPacketType.Resend, resend); 311
287 SetThrottle(ThrottleOutPacketType.Land, land); 312 int total = resend + land + wind + cloud + task + texture + asset + state;
288 SetThrottle(ThrottleOutPacketType.Wind, wind); 313 int taskTotal = task + state;
289 SetThrottle(ThrottleOutPacketType.Cloud, cloud); 314
290 SetThrottle(ThrottleOutPacketType.Task, task); 315 m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, State={8}, Total={9}",
291 SetThrottle(ThrottleOutPacketType.Texture, texture); 316 AgentID, resend, land, wind, cloud, task, texture, asset, state, total);
292 SetThrottle(ThrottleOutPacketType.Asset, asset); 317
318 SetThrottle(ThrottleOutPacketType.Resend, resend, resend);
319 SetThrottle(ThrottleOutPacketType.Land, land, land);
320 SetThrottle(ThrottleOutPacketType.Wind, wind, wind);
321 SetThrottle(ThrottleOutPacketType.Cloud, cloud, cloud);
322 SetThrottle(ThrottleOutPacketType.Task, task, taskTotal);
323 SetThrottle(ThrottleOutPacketType.Texture, texture, texture);
324 SetThrottle(ThrottleOutPacketType.Asset, asset, asset);
325 SetThrottle(ThrottleOutPacketType.State, state, taskTotal);
293 } 326 }
294 327
295 public byte[] GetThrottlesPacked() 328 public byte[] GetThrottlesPacked()
@@ -297,25 +330,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
297 byte[] data = new byte[7 * 4]; 330 byte[] data = new byte[7 * 4];
298 int i = 0; 331 int i = 0;
299 332
300 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Resend].DripRate), 0, data, i, 4); i += 4; 333 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Resend].DripRate), 0, data, i, 4); i += 4;
301 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Land].DripRate), 0, data, i, 4); i += 4; 334 Buffer.BlockCopy(Utils.FloatToBytes((float)m_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; 335 Buffer.BlockCopy(Utils.FloatToBytes((float)m_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; 336 Buffer.BlockCopy(Utils.FloatToBytes((float)m_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; 337 Buffer.BlockCopy(Utils.FloatToBytes((float)(m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate) +
305 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate), 0, data, i, 4); i += 4; 338 m_throttleCategories[(int)ThrottleOutPacketType.State].DripRate), 0, data, i, 4); i += 4;
306 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate), 0, data, i, 4); i += 4; 339 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate), 0, data, i, 4); i += 4;
340 Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate), 0, data, i, 4); i += 4;
307 341
308 return data; 342 return data;
309 } 343 }
310 344
311 public void SetThrottle(ThrottleOutPacketType category, int rate) 345 public void SetThrottle(ThrottleOutPacketType category, int rate, int maxBurst)
312 { 346 {
313 int i = (int)category; 347 int i = (int)category;
314 if (i >= 0 && i < throttleCategories.Length) 348 if (i >= 0 && i < m_throttleCategories.Length)
315 { 349 {
316 TokenBucket bucket = throttleCategories[(int)category]; 350 TokenBucket bucket = m_throttleCategories[(int)category];
317 bucket.MaxBurst = rate;
318 bucket.DripRate = rate; 351 bucket.DripRate = rate;
352 bucket.MaxBurst = maxBurst;
319 } 353 }
320 } 354 }
321 355
@@ -323,12 +357,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
323 { 357 {
324 int category = (int)packet.Category; 358 int category = (int)packet.Category;
325 359
326 if (category >= 0 && category < packetOutboxes.Length) 360 if (category >= 0 && category < m_packetOutboxes.Length)
327 { 361 {
328 LocklessQueue<OutgoingPacket> queue = packetOutboxes[category]; 362 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category];
329 TokenBucket bucket = throttleCategories[category]; 363 TokenBucket bucket = m_throttleCategories[category];
330 364
331 if (throttleCategories[category].RemoveTokens(packet.Buffer.DataLength)) 365 if (m_throttleCategories[category].RemoveTokens(packet.Buffer.DataLength))
332 { 366 {
333 // Enough tokens were removed from the bucket, the packet will not be queued 367 // Enough tokens were removed from the bucket, the packet will not be queued
334 return false; 368 return false;
@@ -357,24 +391,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
357 public bool DequeueOutgoing() 391 public bool DequeueOutgoing()
358 { 392 {
359 OutgoingPacket packet; 393 OutgoingPacket packet;
360 LocklessQueue<OutgoingPacket> queue; 394 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue;
361 TokenBucket bucket; 395 TokenBucket bucket;
362 bool packetSent = false; 396 bool packetSent = false;
363 397
364 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) 398 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
365 { 399 {
366 bucket = throttleCategories[i]; 400 bucket = m_throttleCategories[i];
367 401
368 if (nextPackets[i] != null) 402 if (m_nextPackets[i] != null)
369 { 403 {
370 // This bucket was empty the last time we tried to send a packet, 404 // This bucket was empty the last time we tried to send a packet,
371 // leaving a dequeued packet still waiting to be sent out. Try to 405 // leaving a dequeued packet still waiting to be sent out. Try to
372 // send it again 406 // send it again
373 if (bucket.RemoveTokens(nextPacketLengths[i])) 407 OutgoingPacket nextPacket = m_nextPackets[i];
408 if (bucket.RemoveTokens(nextPacket.Buffer.DataLength))
374 { 409 {
375 // Send the packet 410 // Send the packet
376 udpServer.SendPacketFinal(nextPackets[i]); 411 m_udpServer.SendPacketFinal(nextPacket);
377 nextPackets[i] = null; 412 m_nextPackets[i] = null;
378 packetSent = true; 413 packetSent = true;
379 } 414 }
380 } 415 }
@@ -382,7 +417,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
382 { 417 {
383 // No dequeued packet waiting to be sent, try to pull one off 418 // No dequeued packet waiting to be sent, try to pull one off
384 // this queue 419 // this queue
385 queue = packetOutboxes[i]; 420 queue = m_packetOutboxes[i];
386 if (queue.Dequeue(out packet)) 421 if (queue.Dequeue(out packet))
387 { 422 {
388 // A packet was pulled off the queue. See if we have 423 // A packet was pulled off the queue. See if we have
@@ -390,23 +425,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
390 if (bucket.RemoveTokens(packet.Buffer.DataLength)) 425 if (bucket.RemoveTokens(packet.Buffer.DataLength))
391 { 426 {
392 // Send the packet 427 // Send the packet
393 udpServer.SendPacketFinal(packet); 428 m_udpServer.SendPacketFinal(packet);
394 packetSent = true; 429 packetSent = true;
395 } 430 }
396 else 431 else
397 { 432 {
398 // Save the dequeued packet and the length calculation for 433 // Save the dequeued packet for the next iteration
399 // the next iteration 434 m_nextPackets[i] = packet;
400 nextPackets[i] = packet;
401 nextPacketLengths[i] = packet.Buffer.DataLength;
402 } 435 }
436
437 // If the queue is empty after this dequeue, fire the queue
438 // empty callback now so it has a chance to fill before we
439 // get back here
440 if (queue.Count == 0)
441 BeginFireQueueEmpty(i);
403 } 442 }
404 else 443 else
405 { 444 {
406 // No packets in this queue. Fire the queue empty callback 445 // No packets in this queue. Fire the queue empty callback
407 QueueEmpty callback = OnQueueEmpty; 446 // if it has not been called recently
408 if (callback != null) 447 BeginFireQueueEmpty(i);
409 callback((ThrottleOutPacketType)i);
410 } 448 }
411 } 449 }
412 } 450 }
@@ -414,6 +452,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
414 return packetSent; 452 return packetSent;
415 } 453 }
416 454
455 /// <summary>
456 /// Called when an ACK packet is received and a round-trip time for a
457 /// packet is calculated. This is used to calculate the smoothed
458 /// round-trip time, round trip time variance, and finally the
459 /// retransmission timeout
460 /// </summary>
461 /// <param name="r">Round-trip time of a single packet and its
462 /// acknowledgement</param>
417 public void UpdateRoundTrip(float r) 463 public void UpdateRoundTrip(float r)
418 { 464 {
419 const float ALPHA = 0.125f; 465 const float ALPHA = 0.125f;
@@ -435,8 +481,44 @@ namespace OpenSim.Region.ClientStack.LindenUDP
435 481
436 // Always round retransmission timeout up to two seconds 482 // Always round retransmission timeout up to two seconds
437 RTO = Math.Max(2000, (int)(SRTT + Math.Max(G, K * RTTVAR))); 483 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 " + 484 //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"); 485 // RTTVAR + " based on new RTT of " + r + "ms");
440 } 486 }
487
488 /// <summary>
489 /// Does an early check to see if this queue empty callback is already
490 /// running, then asynchronously firing the event
491 /// </summary>
492 /// <param name="throttleIndex">Throttle category to fire the callback
493 /// for</param>
494 private void BeginFireQueueEmpty(int throttleIndex)
495 {
496 if (!m_onQueueEmptyRunning[throttleIndex])
497 Util.FireAndForget(FireQueueEmpty, throttleIndex);
498 }
499
500 /// <summary>
501 /// Checks to see if this queue empty callback is already running,
502 /// then firing the event
503 /// </summary>
504 /// <param name="o">Throttle category to fire the callback for, stored
505 /// as an object to match the WaitCallback delegate signature</param>
506 private void FireQueueEmpty(object o)
507 {
508 int i = (int)o;
509 ThrottleOutPacketType type = (ThrottleOutPacketType)i;
510 QueueEmpty callback = OnQueueEmpty;
511
512 if (callback != null)
513 {
514 if (!m_onQueueEmptyRunning[i])
515 {
516 m_onQueueEmptyRunning[i] = true;
517 try { callback(type); }
518 catch (Exception e) { m_log.Error("[LLUDPCLIENT]: OnQueueEmpty(" + type + ") threw an exception: " + e.Message, e); }
519 m_onQueueEmptyRunning[i] = false;
520 }
521 }
522 }
441 } 523 }
442} 524}
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..890f701 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>
@@ -109,13 +109,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
109 private Location m_location; 109 private Location m_location;
110 /// <summary>The measured resolution of Environment.TickCount</summary> 110 /// <summary>The measured resolution of Environment.TickCount</summary>
111 private float m_tickCountResolution; 111 private float m_tickCountResolution;
112 /// <summary>The size of the receive buffer for the UDP socket. This value
113 /// is passed up to the operating system and used in the system networking
114 /// stack. Use zero to leave this value as the default</summary>
115 private int m_recvBufferSize;
112 116
113 /// <summary>The measured resolution of Environment.TickCount</summary> 117 /// <summary>The measured resolution of Environment.TickCount</summary>
114 public float TickCountResolution { get { return m_tickCountResolution; } } 118 public float TickCountResolution { get { return m_tickCountResolution; } }
115 public Socket Server { get { return null; } } 119 public Socket Server { get { return null; } }
116 120
117 public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager) 121 public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager)
118 : base((int)port) 122 : base(listenIP, (int)port)
119 { 123 {
120 #region Environment.TickCount Measurement 124 #region Environment.TickCount Measurement
121 125
@@ -134,18 +138,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
134 #endregion Environment.TickCount Measurement 138 #endregion Environment.TickCount Measurement
135 139
136 m_circuitManager = circuitManager; 140 m_circuitManager = circuitManager;
141 int sceneThrottleBps = 0;
137 142
138 // TODO: Config support for throttling the entire connection 143 IConfig config = configSource.Configs["ClientStack.LindenUDP"];
139 m_throttle = new TokenBucket(null, 0, 0); 144 if (config != null)
145 {
146 m_recvBufferSize = config.GetInt("client_socket_rcvbuf_size", 0);
147 sceneThrottleBps = config.GetInt("scene_throttle_max_bps", 0);
148 }
149
150 m_throttle = new TokenBucket(null, sceneThrottleBps, sceneThrottleBps);
140 m_throttleRates = new ThrottleRates(configSource); 151 m_throttleRates = new ThrottleRates(configSource);
141 } 152 }
142 153
143 public new void Start() 154 public void Start()
144 { 155 {
145 if (m_scene == null) 156 if (m_scene == null)
146 throw new InvalidOperationException("Cannot LLUDPServer.Start() without an IScene reference"); 157 throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference");
147 158
148 base.Start(); 159 base.Start(m_recvBufferSize);
149 160
150 // Start the incoming packet processing thread 161 // Start the incoming packet processing thread
151 Thread incomingThread = new Thread(IncomingPacketHandler); 162 Thread incomingThread = new Thread(IncomingPacketHandler);
@@ -181,24 +192,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
181 return x == m_location; 192 return x == m_location;
182 } 193 }
183 194
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) 195 public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents, bool allowSplitting)
203 { 196 {
204 // CoarseLocationUpdate packets cannot be split in an automated way 197 // CoarseLocationUpdate packets cannot be split in an automated way
@@ -216,30 +209,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP
216 for (int i = 0; i < packetCount; i++) 209 for (int i = 0; i < packetCount; i++)
217 { 210 {
218 byte[] data = datas[i]; 211 byte[] data = datas[i];
219 clients.ForEach( 212 m_scene.ClientManager.ForEach(
220 delegate(LLUDPClient client) 213 delegate(IClientAPI client)
221 { SendPacketData(client, data, data.Length, packet.Type, packet.Header.Zerocoded, category); }); 214 {
215 if (client is LLClientView)
216 SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category);
217 }
218 );
222 } 219 }
223 } 220 }
224 else 221 else
225 { 222 {
226 byte[] data = packet.ToBytes(); 223 byte[] data = packet.ToBytes();
227 clients.ForEach( 224 m_scene.ClientManager.ForEach(
228 delegate(LLUDPClient client) 225 delegate(IClientAPI client)
229 { SendPacketData(client, data, data.Length, packet.Type, packet.Header.Zerocoded, category); }); 226 {
227 if (client is LLClientView)
228 SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category);
229 }
230 );
230 } 231 }
231 } 232 }
232 233
233 public void SendPacket(UUID agentID, Packet packet, ThrottleOutPacketType category, bool allowSplitting) 234 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 { 235 {
244 // CoarseLocationUpdate packets cannot be split in an automated way 236 // CoarseLocationUpdate packets cannot be split in an automated way
245 if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting) 237 if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting)
@@ -256,25 +248,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP
256 for (int i = 0; i < packetCount; i++) 248 for (int i = 0; i < packetCount; i++)
257 { 249 {
258 byte[] data = datas[i]; 250 byte[] data = datas[i];
259 SendPacketData(client, data, data.Length, packet.Type, packet.Header.Zerocoded, category); 251 SendPacketData(udpClient, data, packet.Type, category);
260 } 252 }
261 } 253 }
262 else 254 else
263 { 255 {
264 byte[] data = packet.ToBytes(); 256 byte[] data = packet.ToBytes();
265 SendPacketData(client, data, data.Length, packet.Type, packet.Header.Zerocoded, category); 257 SendPacketData(udpClient, data, packet.Type, category);
266 } 258 }
267 } 259 }
268 260
269 public void SendPacketData(LLUDPClient client, byte[] data, int dataLength, PacketType type, bool doZerocode, ThrottleOutPacketType category) 261 public void SendPacketData(LLUDPClient udpClient, byte[] data, PacketType type, ThrottleOutPacketType category)
270 { 262 {
263 int dataLength = data.Length;
264 bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0;
265
271 // Frequency analysis of outgoing packet sizes shows a large clump of packets at each end of the spectrum. 266 // 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 267 // 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 268 // 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 269 // to accomodate for both common scenarios and provide ample room for ACK appending in both
275 int bufferSize = (dataLength > 180) ? Packet.MTU : 200; 270 int bufferSize = (dataLength > 180) ? Packet.MTU : 200;
276 271
277 UDPPacketBuffer buffer = new UDPPacketBuffer(client.RemoteEndPoint, bufferSize); 272 UDPPacketBuffer buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize);
278 273
279 // Zerocode if needed 274 // Zerocode if needed
280 if (doZerocode) 275 if (doZerocode)
@@ -285,17 +280,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
285 // The packet grew larger than the bufferSize while zerocoding. 280 // The packet grew larger than the bufferSize while zerocoding.
286 // Remove the MSG_ZEROCODED flag and send the unencoded data 281 // Remove the MSG_ZEROCODED flag and send the unencoded data
287 // instead 282 // instead
288 m_log.Info("[LLUDPSERVER]: Packet exceeded buffer size during zerocoding. Removing MSG_ZEROCODED flag"); 283 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); 284 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); 285 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
294 } 286 }
295 } 287 }
296 else 288 else
297 { 289 {
298 // ??? will it fit?
299 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength); 290 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
300 } 291 }
301 buffer.DataLength = dataLength; 292 buffer.DataLength = dataLength;
@@ -303,7 +294,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
303 #region Queue or Send 294 #region Queue or Send
304 295
305 // Look up the UDPClient this is going to 296 // Look up the UDPClient this is going to
306 OutgoingPacket outgoingPacket = new OutgoingPacket(client, buffer, category); 297 OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category);
307 298
308 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket)) 299 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket))
309 SendPacketFinal(outgoingPacket); 300 SendPacketFinal(outgoingPacket);
@@ -311,18 +302,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
311 #endregion Queue or Send 302 #endregion Queue or Send
312 } 303 }
313 304
314 public void SendAcks(LLUDPClient client) 305 public void SendAcks(LLUDPClient udpClient)
315 { 306 {
316 uint ack; 307 uint ack;
317 308
318 if (client.PendingAcks.Dequeue(out ack)) 309 if (udpClient.PendingAcks.Dequeue(out ack))
319 { 310 {
320 List<PacketAckPacket.PacketsBlock> blocks = new List<PacketAckPacket.PacketsBlock>(); 311 List<PacketAckPacket.PacketsBlock> blocks = new List<PacketAckPacket.PacketsBlock>();
321 PacketAckPacket.PacketsBlock block = new PacketAckPacket.PacketsBlock(); 312 PacketAckPacket.PacketsBlock block = new PacketAckPacket.PacketsBlock();
322 block.ID = ack; 313 block.ID = ack;
323 blocks.Add(block); 314 blocks.Add(block);
324 315
325 while (client.PendingAcks.Dequeue(out ack)) 316 while (udpClient.PendingAcks.Dequeue(out ack))
326 { 317 {
327 block = new PacketAckPacket.PacketsBlock(); 318 block = new PacketAckPacket.PacketsBlock();
328 block.ID = ack; 319 block.ID = ack;
@@ -333,22 +324,39 @@ namespace OpenSim.Region.ClientStack.LindenUDP
333 packet.Header.Reliable = false; 324 packet.Header.Reliable = false;
334 packet.Packets = blocks.ToArray(); 325 packet.Packets = blocks.ToArray();
335 326
336 SendPacket(client, packet, ThrottleOutPacketType.Unknown, true); 327 SendPacket(udpClient, packet, ThrottleOutPacketType.Unknown, true);
337 } 328 }
338 } 329 }
339 330
340 public void SendPing(LLUDPClient client) 331 public void SendPing(LLUDPClient udpClient)
341 { 332 {
342 IClientAPI api = client.ClientAPI; 333 StartPingCheckPacket pc = (StartPingCheckPacket)PacketPool.Instance.GetPacket(PacketType.StartPingCheck);
343 if (api != null) 334 pc.Header.Reliable = false;
344 api.SendStartPingCheck(client.CurrentPingSequence++); 335
336 OutgoingPacket oldestPacket = udpClient.NeedAcks.GetOldest();
337
338 pc.PingID.PingID = (byte)udpClient.CurrentPingSequence++;
339 pc.PingID.OldestUnacked = (oldestPacket != null) ? oldestPacket.SequenceNumber : 0;
340
341 SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false);
345 } 342 }
346 343
347 public void ResendUnacked(LLUDPClient client) 344 public void ResendUnacked(LLUDPClient udpClient)
348 { 345 {
349 if (client.NeedAcks.Count > 0) 346 if (udpClient.IsConnected && udpClient.NeedAcks.Count > 0)
350 { 347 {
351 List<OutgoingPacket> expiredPackets = client.NeedAcks.GetExpiredPackets(client.RTO); 348 // Disconnect an agent if no packets are received for some time
349 //FIXME: Make 60 an .ini setting
350 if (Environment.TickCount - udpClient.TickLastPacketReceived > 1000 * 60)
351 {
352 m_log.Warn("[LLUDPSERVER]: Ack timeout, disconnecting " + udpClient.AgentID);
353
354 RemoveClient(udpClient);
355 return;
356 }
357
358 // Get a list of all of the packets that have been sitting unacked longer than udpClient.RTO
359 List<OutgoingPacket> expiredPackets = udpClient.NeedAcks.GetExpiredPackets(udpClient.RTO);
352 360
353 if (expiredPackets != null) 361 if (expiredPackets != null)
354 { 362 {
@@ -357,54 +365,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
357 { 365 {
358 OutgoingPacket outgoingPacket = expiredPackets[i]; 366 OutgoingPacket outgoingPacket = expiredPackets[i];
359 367
360 // FIXME: Make this an .ini setting 368 //m_log.DebugFormat("[LLUDPSERVER]: Resending packet #{0} (attempt {1}), {2}ms have passed",
361 if (outgoingPacket.ResendCount < 3) 369 // 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
370 // The TickCount will be set to the current time when the packet 371 // Set the resent flag
371 // is actually sent out again 372 outgoingPacket.Buffer.Data[0] = (byte)(outgoingPacket.Buffer.Data[0] | Helpers.MSG_RESENT);
372 outgoingPacket.TickCount = 0; 373 outgoingPacket.Category = ThrottleOutPacketType.Resend;
373 374
374 // Bump up the resend count on this packet 375 // The TickCount will be set to the current time when the packet
375 Interlocked.Increment(ref outgoingPacket.ResendCount); 376 // is actually sent out again
376 //Interlocked.Increment(ref Stats.ResentPackets); 377 outgoingPacket.TickCount = 0;
377 378
378 // Queue or (re)send the packet 379 // Bump up the resend count on this packet
379 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket)) 380 Interlocked.Increment(ref outgoingPacket.ResendCount);
380 SendPacketFinal(outgoingPacket); 381 //Interlocked.Increment(ref Stats.ResentPackets);
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 382
387 lock (client.NeedAcks.SyncRoot) 383 // Requeue or resend the packet
388 client.NeedAcks.RemoveUnsafe(outgoingPacket.SequenceNumber); 384 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket))
389 385 SendPacketFinal(outgoingPacket);
390 //Interlocked.Increment(ref Stats.DroppedPackets);
391
392 // Disconnect an agent if no packets are received for some time
393 //FIXME: Make 60 an .ini setting
394 if (Environment.TickCount - client.TickLastPacketReceived > 1000 * 60)
395 {
396 m_log.Warn("[LLUDPSERVER]: Ack timeout, disconnecting " + client.ClientAPI.Name);
397
398 RemoveClient(client.ClientAPI);
399 return;
400 }
401 }
402 } 386 }
403 } 387 }
404 } 388 }
405 } 389 }
406 390
407 public void Flush() 391 public void Flush(LLUDPClient udpClient)
408 { 392 {
409 // FIXME: Implement? 393 // FIXME: Implement?
410 } 394 }
@@ -415,7 +399,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
415 byte flags = buffer.Data[0]; 399 byte flags = buffer.Data[0];
416 bool isResend = (flags & Helpers.MSG_RESENT) != 0; 400 bool isResend = (flags & Helpers.MSG_RESENT) != 0;
417 bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0; 401 bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0;
418 LLUDPClient client = outgoingPacket.Client; 402 LLUDPClient udpClient = outgoingPacket.Client;
403
404 if (!udpClient.IsConnected)
405 return;
419 406
420 // Keep track of when this packet was sent out (right now) 407 // Keep track of when this packet was sent out (right now)
421 outgoingPacket.TickCount = Environment.TickCount; 408 outgoingPacket.TickCount = Environment.TickCount;
@@ -424,11 +411,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
424 411
425 int dataLength = buffer.DataLength; 412 int dataLength = buffer.DataLength;
426 413
427 // Keep appending ACKs until there is no room left in the packet or there are 414 // Keep appending ACKs until there is no room left in the buffer or there are
428 // no more ACKs to append 415 // no more ACKs to append
429 uint ackCount = 0; 416 uint ackCount = 0;
430 uint ack; 417 uint ack;
431 while (dataLength + 5 < buffer.Data.Length && client.PendingAcks.Dequeue(out ack)) 418 while (dataLength + 5 < buffer.Data.Length && udpClient.PendingAcks.Dequeue(out ack))
432 { 419 {
433 Utils.UIntToBytesBig(ack, buffer.Data, dataLength); 420 Utils.UIntToBytesBig(ack, buffer.Data, dataLength);
434 dataLength += 4; 421 dataLength += 4;
@@ -447,24 +434,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP
447 434
448 #endregion ACK Appending 435 #endregion ACK Appending
449 436
437 #region Sequence Number Assignment
438
450 if (!isResend) 439 if (!isResend)
451 { 440 {
452 // Not a resend, assign a new sequence number 441 // Not a resend, assign a new sequence number
453 uint sequenceNumber = (uint)Interlocked.Increment(ref client.CurrentSequence); 442 uint sequenceNumber = (uint)Interlocked.Increment(ref udpClient.CurrentSequence);
454 Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1); 443 Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1);
455 outgoingPacket.SequenceNumber = sequenceNumber; 444 outgoingPacket.SequenceNumber = sequenceNumber;
456 445
457 if (isReliable) 446 if (isReliable)
458 { 447 {
459 // Add this packet to the list of ACK responses we are waiting on from the server 448 // Add this packet to the list of ACK responses we are waiting on from the server
460 client.NeedAcks.Add(outgoingPacket); 449 udpClient.NeedAcks.Add(outgoingPacket);
461 } 450 }
462 } 451 }
463 452
453 #endregion Sequence Number Assignment
454
464 // Stats tracking 455 // Stats tracking
465 Interlocked.Increment(ref client.PacketsSent); 456 Interlocked.Increment(ref udpClient.PacketsSent);
466 if (isReliable) 457 if (isReliable)
467 Interlocked.Add(ref client.UnackedBytes, outgoingPacket.Buffer.DataLength); 458 Interlocked.Add(ref udpClient.UnackedBytes, outgoingPacket.Buffer.DataLength);
468 459
469 // Put the UDP payload on the wire 460 // Put the UDP payload on the wire
470 AsyncBeginSend(buffer); 461 AsyncBeginSend(buffer);
@@ -473,10 +464,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
473 protected override void PacketReceived(UDPPacketBuffer buffer) 464 protected override void PacketReceived(UDPPacketBuffer buffer)
474 { 465 {
475 // Debugging/Profiling 466 // Debugging/Profiling
476 //try { Thread.CurrentThread.Name = "PacketReceived (" + scene.RegionName + ")"; } 467 //try { Thread.CurrentThread.Name = "PacketReceived (" + m_scene.RegionInfo.RegionName + ")"; }
477 //catch (Exception) { } 468 //catch (Exception) { }
478 469
479 LLUDPClient client = null; 470 LLUDPClient udpClient = null;
480 Packet packet = null; 471 Packet packet = null;
481 int packetEnd = buffer.DataLength - 1; 472 int packetEnd = buffer.DataLength - 1;
482 IPEndPoint address = (IPEndPoint)buffer.RemoteEndPoint; 473 IPEndPoint address = (IPEndPoint)buffer.RemoteEndPoint;
@@ -491,61 +482,59 @@ namespace OpenSim.Region.ClientStack.LindenUDP
491 } 482 }
492 catch (MalformedDataException) 483 catch (MalformedDataException)
493 { 484 {
494 m_log.ErrorFormat("[LLUDPSERVER]: Malformed data, cannot parse packet:\n{0}", 485 m_log.ErrorFormat("[LLUDPSERVER]: Malformed data, cannot parse packet from {0}:\n{1}",
495 Utils.BytesToHexString(buffer.Data, buffer.DataLength, null)); 486 buffer.RemoteEndPoint, Utils.BytesToHexString(buffer.Data, buffer.DataLength, null));
496 } 487 }
497 488
498 // Fail-safe check 489 // Fail-safe check
499 if (packet == null) 490 if (packet == null)
500 { 491 {
501 m_log.Warn("[LLUDPSERVER]: Couldn't build a message from the incoming data"); 492 m_log.Warn("[LLUDPSERVER]: Couldn't build a message from incoming data " + buffer.DataLength +
493 " bytes long from " + buffer.RemoteEndPoint);
502 return; 494 return;
503 } 495 }
504 496
505 //Stats.RecvBytes += (ulong)buffer.DataLength;
506 //++Stats.RecvPackets;
507
508 #endregion Decoding 497 #endregion Decoding
509 498
510 #region UseCircuitCode Handling 499 #region Packet to Client Mapping
511 500
501 // UseCircuitCode handling
512 if (packet.Type == PacketType.UseCircuitCode) 502 if (packet.Type == PacketType.UseCircuitCode)
513 { 503 {
514 UseCircuitCodePacket useCircuitCode = (UseCircuitCodePacket)packet; 504 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 } 505 }
524 506
525 // Determine which agent this packet came from 507 // Determine which agent this packet came from
526 if (!clients.TryGetValue(address, out client)) 508 IClientAPI client;
509 if (!m_scene.ClientManager.TryGetValue(address, out client) || !(client is LLClientView))
527 { 510 {
528 m_log.Warn("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); 511 m_log.Warn("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address +
512 " in " + m_scene.RegionInfo.RegionName + ", currently tracking " + m_scene.ClientManager.Count + " clients");
529 return; 513 return;
530 } 514 }
531 515
532 #endregion UseCircuitCode Handling 516 udpClient = ((LLClientView)client).UDPClient;
517
518 if (!udpClient.IsConnected)
519 return;
520
521 #endregion Packet to Client Mapping
533 522
534 // Stats tracking 523 // Stats tracking
535 Interlocked.Increment(ref client.PacketsReceived); 524 Interlocked.Increment(ref udpClient.PacketsReceived);
536 525
537 #region ACK Receiving 526 #region ACK Receiving
538 527
539 int now = Environment.TickCount; 528 int now = Environment.TickCount;
540 client.TickLastPacketReceived = now; 529 udpClient.TickLastPacketReceived = now;
541 530
542 // Handle appended ACKs 531 // Handle appended ACKs
543 if (packet.Header.AppendedAcks && packet.Header.AckList != null) 532 if (packet.Header.AppendedAcks && packet.Header.AckList != null)
544 { 533 {
545 lock (client.NeedAcks.SyncRoot) 534 lock (udpClient.NeedAcks.SyncRoot)
546 { 535 {
547 for (int i = 0; i < packet.Header.AckList.Length; i++) 536 for (int i = 0; i < packet.Header.AckList.Length; i++)
548 AcknowledgePacket(client, packet.Header.AckList[i], now, packet.Header.Resent); 537 AcknowledgePacket(udpClient, packet.Header.AckList[i], now, packet.Header.Resent);
549 } 538 }
550 } 539 }
551 540
@@ -554,10 +543,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
554 { 543 {
555 PacketAckPacket ackPacket = (PacketAckPacket)packet; 544 PacketAckPacket ackPacket = (PacketAckPacket)packet;
556 545
557 lock (client.NeedAcks.SyncRoot) 546 lock (udpClient.NeedAcks.SyncRoot)
558 { 547 {
559 for (int i = 0; i < ackPacket.Packets.Length; i++) 548 for (int i = 0; i < ackPacket.Packets.Length; i++)
560 AcknowledgePacket(client, ackPacket.Packets[i].ID, now, packet.Header.Resent); 549 AcknowledgePacket(udpClient, ackPacket.Packets[i].ID, now, packet.Header.Resent);
561 } 550 }
562 } 551 }
563 552
@@ -566,27 +555,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP
566 #region ACK Sending 555 #region ACK Sending
567 556
568 if (packet.Header.Reliable) 557 if (packet.Header.Reliable)
569 client.PendingAcks.Enqueue((uint)packet.Header.Sequence); 558 udpClient.PendingAcks.Enqueue(packet.Header.Sequence);
570 559
571 // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out, 560 // 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 561 // 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 562 // 2*MTU bytes from the value and send ACKs, and finally add the local value back to
574 // client.BytesSinceLastACK. Lockless thread safety 563 // client.BytesSinceLastACK. Lockless thread safety
575 int bytesSinceLastACK = Interlocked.Exchange(ref client.BytesSinceLastACK, 0); 564 int bytesSinceLastACK = Interlocked.Exchange(ref udpClient.BytesSinceLastACK, 0);
576 bytesSinceLastACK += buffer.DataLength; 565 bytesSinceLastACK += buffer.DataLength;
577 if (bytesSinceLastACK > Packet.MTU * 2) 566 if (bytesSinceLastACK > Packet.MTU * 2)
578 { 567 {
579 bytesSinceLastACK -= Packet.MTU * 2; 568 bytesSinceLastACK -= Packet.MTU * 2;
580 SendAcks(client); 569 SendAcks(udpClient);
581 } 570 }
582 Interlocked.Add(ref client.BytesSinceLastACK, bytesSinceLastACK); 571 Interlocked.Add(ref udpClient.BytesSinceLastACK, bytesSinceLastACK);
583 572
584 #endregion ACK Sending 573 #endregion ACK Sending
585 574
586 #region Incoming Packet Accounting 575 #region Incoming Packet Accounting
587 576
588 // Check the archive of received reliable packet IDs to see whether we already received this packet 577 // 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)) 578 if (packet.Header.Reliable && !udpClient.PacketArchive.TryEnqueue(packet.Header.Sequence))
590 { 579 {
591 if (packet.Header.Resent) 580 if (packet.Header.Resent)
592 m_log.Debug("[LLUDPSERVER]: Received a resend of already processed packet #" + packet.Header.Sequence + ", type: " + packet.Type); 581 m_log.Debug("[LLUDPSERVER]: Received a resend of already processed packet #" + packet.Header.Sequence + ", type: " + packet.Type);
@@ -603,7 +592,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
603 if (packet.Type != PacketType.PacketAck) 592 if (packet.Type != PacketType.PacketAck)
604 { 593 {
605 // Inbox insertion 594 // Inbox insertion
606 packetInbox.Enqueue(new IncomingPacket(client, packet)); 595 packetInbox.Enqueue(new IncomingPacket(udpClient, packet));
607 } 596 }
608 } 597 }
609 598
@@ -623,53 +612,59 @@ namespace OpenSim.Region.ClientStack.LindenUDP
623 612
624 private void AddNewClient(UseCircuitCodePacket useCircuitCode, IPEndPoint remoteEndPoint) 613 private void AddNewClient(UseCircuitCodePacket useCircuitCode, IPEndPoint remoteEndPoint)
625 { 614 {
626 //Slave regions don't accept new clients 615 UUID agentID = useCircuitCode.CircuitCode.ID;
616 UUID sessionID = useCircuitCode.CircuitCode.SessionID;
617 uint circuitCode = useCircuitCode.CircuitCode.Code;
618
627 if (m_scene.RegionStatus != RegionStatus.SlaveScene) 619 if (m_scene.RegionStatus != RegionStatus.SlaveScene)
628 { 620 {
629 AuthenticateResponse sessionInfo; 621 AuthenticateResponse sessionInfo;
630 bool isNewCircuit = !clients.ContainsKey(remoteEndPoint); 622 if (IsClientAuthorized(useCircuitCode, out sessionInfo))
631
632 if (!IsClientAuthorized(useCircuitCode, out sessionInfo))
633 { 623 {
634 m_log.WarnFormat( 624 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 } 625 }
639 626 else
640 if (isNewCircuit)
641 { 627 {
642 UUID agentID = useCircuitCode.CircuitCode.ID; 628 // Don't create circuits for unauthorized clients
643 UUID sessionID = useCircuitCode.CircuitCode.SessionID; 629 m_log.WarnFormat(
644 uint circuitCode = useCircuitCode.CircuitCode.Code; 630 "[LLUDPSERVER]: Connection request for client {0} connecting with unnotified circuit code {1} from {2}",
645 631 useCircuitCode.CircuitCode.ID, useCircuitCode.CircuitCode.Code, remoteEndPoint);
646 AddClient(circuitCode, agentID, sessionID, remoteEndPoint, sessionInfo);
647 } 632 }
648 } 633 }
634 else
635 {
636 // Slave regions don't accept new clients
637 m_log.Debug("[LLUDPSERVER]: Slave region " + m_scene.RegionInfo.RegionName + " ignoring UseCircuitCode packet");
638 }
649 } 639 }
650 640
651 private void AddClient(uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo) 641 private void AddClient(uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo)
652 { 642 {
653 // Create the LLUDPClient 643 // Create the LLUDPClient
654 LLUDPClient client = new LLUDPClient(this, m_throttleRates, m_throttle, circuitCode, agentID, remoteEndPoint); 644 LLUDPClient udpClient = new LLUDPClient(this, m_throttleRates, m_throttle, circuitCode, agentID, remoteEndPoint);
655
656 // Create the LLClientView
657 LLClientView clientApi = new LLClientView(remoteEndPoint, m_scene, this, client, sessionInfo, agentID, sessionID, circuitCode);
658 clientApi.OnViewerEffect += m_scene.ClientManager.ViewerEffectHandler;
659 clientApi.OnLogout += LogoutHandler;
660 clientApi.OnConnectionClosed += RemoveClient;
661
662 // Start the IClientAPI
663 m_scene.ClientManager.Add(circuitCode, clientApi);
664 clientApi.Start();
665 645
666 // Give LLUDPClient a reference to IClientAPI 646 if (!m_scene.ClientManager.ContainsKey(agentID))
667 client.ClientAPI = clientApi; 647 {
648 // Create the LLClientView
649 LLClientView client = new LLClientView(remoteEndPoint, m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
650 client.OnLogout += LogoutHandler;
668 651
669 // Add the new client to our list of tracked clients 652 // Start the IClientAPI
670 clients.Add(agentID, client.RemoteEndPoint, client); 653 client.Start();
654 }
655 else
656 {
657 m_log.WarnFormat("[LLUDPSERVER]: Ignoring a repeated UseCircuitCode from {0} at {1} for circuit {2}",
658 udpClient.AgentID, remoteEndPoint, circuitCode);
659 }
660 }
671 661
672 m_log.DebugFormat("[LLUDPSERVER]: Added new client {0} to region {1}", agentID, m_scene.RegionInfo.RegionName); 662 private void RemoveClient(LLUDPClient udpClient)
663 {
664 // Remove this client from the scene
665 IClientAPI client;
666 if (m_scene.ClientManager.TryGetValue(udpClient.AgentID, out client))
667 client.Close();
673 } 668 }
674 669
675 private void AcknowledgePacket(LLUDPClient client, uint ack, int currentTime, bool fromResend) 670 private void AcknowledgePacket(LLUDPClient client, uint ack, int currentTime, bool fromResend)
@@ -747,20 +742,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP
747 elapsed500MS = 0; 742 elapsed500MS = 0;
748 } 743 }
749 744
750 clients.ForEach( 745 m_scene.ClientManager.ForEach(
751 delegate(LLUDPClient client) 746 delegate(IClientAPI client)
752 { 747 {
753 if (client.DequeueOutgoing()) 748 if (client is LLClientView)
754 packetSent = true;
755 if (resendUnacked)
756 ResendUnacked(client);
757 if (sendAcks)
758 { 749 {
759 SendAcks(client); 750 LLUDPClient udpClient = ((LLClientView)client).UDPClient;
760 client.SendPacketStats(); 751
752 if (udpClient.IsConnected)
753 {
754 if (udpClient.DequeueOutgoing())
755 packetSent = true;
756 if (resendUnacked)
757 ResendUnacked(udpClient);
758 if (sendAcks)
759 {
760 SendAcks(udpClient);
761 udpClient.SendPacketStats();
762 }
763 if (sendPings)
764 SendPing(udpClient);
765 }
761 } 766 }
762 if (sendPings)
763 SendPing(client);
764 } 767 }
765 ); 768 );
766 769
@@ -773,38 +776,48 @@ namespace OpenSim.Region.ClientStack.LindenUDP
773 { 776 {
774 IncomingPacket incomingPacket = (IncomingPacket)state; 777 IncomingPacket incomingPacket = (IncomingPacket)state;
775 Packet packet = incomingPacket.Packet; 778 Packet packet = incomingPacket.Packet;
776 LLUDPClient client = incomingPacket.Client; 779 LLUDPClient udpClient = incomingPacket.Client;
780 IClientAPI client;
777 781
778 // Sanity check 782 // Sanity check
779 if (packet == null || client == null || client.ClientAPI == null) 783 if (packet == null || udpClient == null)
780 { 784 {
781 m_log.WarnFormat("[LLUDPSERVER]: Processing a packet with incomplete state. Packet=\"{0}\", Client=\"{1}\", Client.ClientAPI=\"{2}\"", 785 m_log.WarnFormat("[LLUDPSERVER]: Processing a packet with incomplete state. Packet=\"{0}\", UDPClient=\"{1}\"",
782 packet, client, (client != null) ? client.ClientAPI : null); 786 packet, udpClient);
783 } 787 }
784 788
785 try 789 // Make sure this client is still alive
786 { 790 if (m_scene.ClientManager.TryGetValue(udpClient.AgentID, out client))
787 // Process this packet
788 client.ClientAPI.ProcessInPacket(packet);
789 }
790 catch (ThreadAbortException)
791 { 791 {
792 // If something is trying to abort the packet processing thread, take that as a hint that it's time to shut down 792 try
793 m_log.Info("[LLUDPSERVER]: Caught a thread abort, shutting down the LLUDP server"); 793 {
794 Stop(); 794 // Process this packet
795 client.ProcessInPacket(packet);
796 }
797 catch (ThreadAbortException)
798 {
799 // If something is trying to abort the packet processing thread, take that as a hint that it's time to shut down
800 m_log.Info("[LLUDPSERVER]: Caught a thread abort, shutting down the LLUDP server");
801 Stop();
802 }
803 catch (Exception e)
804 {
805 // Don't let a failure in an individual client thread crash the whole sim.
806 m_log.ErrorFormat("[LLUDPSERVER]: Client packet handler for {0} for packet {1} threw an exception", udpClient.AgentID, packet.Type);
807 m_log.Error(e.Message, e);
808 }
795 } 809 }
796 catch (Exception e) 810 else
797 { 811 {
798 // Don't let a failure in an individual client thread crash the whole sim. 812 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 } 813 }
802 } 814 }
803 815
804 private void LogoutHandler(IClientAPI client) 816 private void LogoutHandler(IClientAPI client)
805 { 817 {
806 client.SendLogoutPacket(); 818 client.SendLogoutPacket();
807 RemoveClient(client); 819 if (client.IsActive)
820 RemoveClient(((LLClientView)client).UDPClient);
808 } 821 }
809 } 822 }
810} 823}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs
index 43a68ec..44a6ed6 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs
@@ -1,419 +1,129 @@
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 ///
77 public OpenSimUDPBase(IPAddress bindAddress, int port)
384 { 78 {
385 remoteEndPoint = endPoint; 79 m_localBindAddress = bindAddress;
386 udpPort = 0; 80 m_udpPort = port;
387 } 81 }
388 82
389 /// <summary> 83 /// <summary>
390 /// 84 /// Start the UDP server
391 /// </summary> 85 /// </summary>
392 public void Start() 86 /// <param name="recvBufferSize">The size of the receive buffer for
87 /// the UDP socket. This value is passed up to the operating system
88 /// and used in the system networking stack. Use zero to leave this
89 /// value as the default</param>
90 /// <remarks>This method will attempt to set the SIO_UDP_CONNRESET flag
91 /// on the socket to get newer versions of Windows to behave in a sane
92 /// manner (not throwing an exception when the remote side resets the
93 /// connection). This call is ignored on Mono where the flag is not
94 /// necessary</remarks>
95 public void Start(int recvBufferSize)
393 { 96 {
394 if (shutdownFlag) 97 if (m_shutdownFlag)
395 { 98 {
396 const int SIO_UDP_CONNRESET = -1744830452; 99 const int SIO_UDP_CONNRESET = -1744830452;
397 100
398 IPEndPoint ipep = new IPEndPoint(Settings.BIND_ADDR, udpPort); 101 IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort);
399 udpSocket = new Socket( 102
103 m_udpSocket = new Socket(
400 AddressFamily.InterNetwork, 104 AddressFamily.InterNetwork,
401 SocketType.Dgram, 105 SocketType.Dgram,
402 ProtocolType.Udp); 106 ProtocolType.Udp);
107
403 try 108 try
404 { 109 {
405 // this udp socket flag is not supported under mono, 110 // This udp socket flag is not supported under mono,
406 // so we'll catch the exception and continue 111 // so we'll catch the exception and continue
407 udpSocket.IOControl(SIO_UDP_CONNRESET, new byte[] { 0 }, null); 112 m_udpSocket.IOControl(SIO_UDP_CONNRESET, new byte[] { 0 }, null);
113 m_log.Debug("[UDPBASE]: SIO_UDP_CONNRESET flag set");
408 } 114 }
409 catch (SocketException) 115 catch (SocketException)
410 { 116 {
411 Logger.DebugLog("UDP SIO_UDP_CONNRESET flag not supported on this platform"); 117 m_log.Debug("[UDPBASE]: SIO_UDP_CONNRESET flag not supported on this platform, ignoring");
412 } 118 }
413 udpSocket.Bind(ipep); 119
120 if (recvBufferSize != 0)
121 m_udpSocket.ReceiveBufferSize = recvBufferSize;
122
123 m_udpSocket.Bind(ipep);
414 124
415 // we're not shutting down, we're starting up 125 // we're not shutting down, we're starting up
416 shutdownFlag = false; 126 m_shutdownFlag = false;
417 127
418 // kick off an async receive. The Start() method will return, the 128 // kick off an async receive. The Start() method will return, the
419 // actual receives will occur asynchronously and will be caught in 129 // actual receives will occur asynchronously and will be caught in
@@ -423,41 +133,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP
423 } 133 }
424 134
425 /// <summary> 135 /// <summary>
426 /// 136 /// Stops the UDP server
427 /// </summary> 137 /// </summary>
428 public void Stop() 138 public void Stop()
429 { 139 {
430 if (!shutdownFlag) 140 if (!m_shutdownFlag)
431 { 141 {
432 // wait indefinitely for a writer lock. Once this is called, the .NET runtime 142 // 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 143 // 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 144 // threads. Once we have the lock, we set shutdownFlag to inform the other
435 // threads that the socket is closed. 145 // threads that the socket is closed.
436 shutdownFlag = true; 146 m_shutdownFlag = true;
437 udpSocket.Close(); 147 m_udpSocket.Close();
438 } 148 }
439 } 149 }
440 150
441 /// <summary>
442 ///
443 /// </summary>
444 public bool IsRunning
445 {
446 get { return !shutdownFlag; }
447 }
448
449 private void AsyncBeginReceive() 151 private void AsyncBeginReceive()
450 { 152 {
451 // allocate a packet buffer 153 // allocate a packet buffer
452 //WrappedObject<UDPPacketBuffer> wrappedBuffer = Pool.CheckOut(); 154 //WrappedObject<UDPPacketBuffer> wrappedBuffer = Pool.CheckOut();
453 UDPPacketBuffer buf = new UDPPacketBuffer(); 155 UDPPacketBuffer buf = new UDPPacketBuffer();
454 156
455 if (!shutdownFlag) 157 if (!m_shutdownFlag)
456 { 158 {
457 try 159 try
458 { 160 {
459 // kick off an async read 161 // kick off an async read
460 udpSocket.BeginReceiveFrom( 162 m_udpSocket.BeginReceiveFrom(
461 //wrappedBuffer.Instance.Data, 163 //wrappedBuffer.Instance.Data,
462 buf.Data, 164 buf.Data,
463 0, 165 0,
@@ -472,13 +174,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
472 { 174 {
473 if (e.SocketErrorCode == SocketError.ConnectionReset) 175 if (e.SocketErrorCode == SocketError.ConnectionReset)
474 { 176 {
475 Logger.Log("SIO_UDP_CONNRESET was ignored, attempting to salvage the UDP listener on port " + udpPort, Helpers.LogLevel.Error); 177 m_log.Warn("[UDPBASE]: SIO_UDP_CONNRESET was ignored, attempting to salvage the UDP listener on port " + m_udpPort);
476 bool salvaged = false; 178 bool salvaged = false;
477 while (!salvaged) 179 while (!salvaged)
478 { 180 {
479 try 181 try
480 { 182 {
481 udpSocket.BeginReceiveFrom( 183 m_udpSocket.BeginReceiveFrom(
482 //wrappedBuffer.Instance.Data, 184 //wrappedBuffer.Instance.Data,
483 buf.Data, 185 buf.Data,
484 0, 186 0,
@@ -494,7 +196,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
494 catch (ObjectDisposedException) { return; } 196 catch (ObjectDisposedException) { return; }
495 } 197 }
496 198
497 Logger.Log("Salvaged the UDP listener on port " + udpPort, Helpers.LogLevel.Info); 199 m_log.Warn("[UDPBASE]: Salvaged the UDP listener on port " + m_udpPort);
498 } 200 }
499 } 201 }
500 catch (ObjectDisposedException) { } 202 catch (ObjectDisposedException) { }
@@ -505,7 +207,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
505 { 207 {
506 // Asynchronous receive operations will complete here through the call 208 // Asynchronous receive operations will complete here through the call
507 // to AsyncBeginReceive 209 // to AsyncBeginReceive
508 if (!shutdownFlag) 210 if (!m_shutdownFlag)
509 { 211 {
510 // start another receive - this keeps the server going! 212 // start another receive - this keeps the server going!
511 AsyncBeginReceive(); 213 AsyncBeginReceive();
@@ -520,7 +222,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
520 { 222 {
521 // get the length of data actually read from the socket, store it with the 223 // get the length of data actually read from the socket, store it with the
522 // buffer 224 // buffer
523 buffer.DataLength = udpSocket.EndReceiveFrom(iar, ref buffer.RemoteEndPoint); 225 buffer.DataLength = m_udpSocket.EndReceiveFrom(iar, ref buffer.RemoteEndPoint);
524 226
525 // call the abstract method PacketReceived(), passing the buffer that 227 // call the abstract method PacketReceived(), passing the buffer that
526 // has just been filled from the socket read. 228 // has just been filled from the socket read.
@@ -529,16 +231,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
529 catch (SocketException) { } 231 catch (SocketException) { }
530 catch (ObjectDisposedException) { } 232 catch (ObjectDisposedException) { }
531 //finally { wrappedBuffer.Dispose(); } 233 //finally { wrappedBuffer.Dispose(); }
234
532 } 235 }
533 } 236 }
534 237
535 public void AsyncBeginSend(UDPPacketBuffer buf) 238 public void AsyncBeginSend(UDPPacketBuffer buf)
536 { 239 {
537 if (!shutdownFlag) 240 if (!m_shutdownFlag)
538 { 241 {
539 try 242 try
540 { 243 {
541 udpSocket.BeginSendTo( 244 m_udpSocket.BeginSendTo(
542 buf.Data, 245 buf.Data,
543 0, 246 0,
544 buf.DataLength, 247 buf.DataLength,
@@ -557,7 +260,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
557 try 260 try
558 { 261 {
559 UDPPacketBuffer buf = (UDPPacketBuffer)result.AsyncState; 262 UDPPacketBuffer buf = (UDPPacketBuffer)result.AsyncState;
560 int bytesSent = udpSocket.EndSendTo(result); 263 int bytesSent = m_udpSocket.EndSendTo(result);
561 264
562 PacketSent(buf, bytesSent); 265 PacketSent(buf, bytesSent);
563 } 266 }
@@ -566,4 +269,3 @@ namespace OpenSim.Region.ClientStack.LindenUDP
566 } 269 }
567 } 270 }
568} 271}
569
diff --git a/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs b/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs
index 858a03c..008d827 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using OpenSim.Framework;
29using Nini.Config; 30using Nini.Config;
30 31
31namespace OpenSim.Region.ClientStack.LindenUDP 32namespace OpenSim.Region.ClientStack.LindenUDP
@@ -45,12 +46,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
45 public int Wind; 46 public int Wind;
46 /// <summary>Drip rate for cloud packets</summary> 47 /// <summary>Drip rate for cloud packets</summary>
47 public int Cloud; 48 public int Cloud;
48 /// <summary>Drip rate for task (state and transaction) packets</summary> 49 /// <summary>Drip rate for task packets</summary>
49 public int Task; 50 public int Task;
50 /// <summary>Drip rate for texture packets</summary> 51 /// <summary>Drip rate for texture packets</summary>
51 public int Texture; 52 public int Texture;
52 /// <summary>Drip rate for asset packets</summary> 53 /// <summary>Drip rate for asset packets</summary>
53 public int Asset; 54 public int Asset;
55 /// <summary>Drip rate for state packets</summary>
56 public int State;
57 /// <summary>Drip rate for the parent token bucket</summary>
58 public int Total;
54 59
55 /// <summary>Maximum burst rate for resent packets</summary> 60 /// <summary>Maximum burst rate for resent packets</summary>
56 public int ResendLimit; 61 public int ResendLimit;
@@ -66,6 +71,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
66 public int TextureLimit; 71 public int TextureLimit;
67 /// <summary>Maximum burst rate for asset packets</summary> 72 /// <summary>Maximum burst rate for asset packets</summary>
68 public int AssetLimit; 73 public int AssetLimit;
74 /// <summary>Maximum burst rate for state packets</summary>
75 public int StateLimit;
76 /// <summary>Burst rate for the parent token bucket</summary>
77 public int TotalLimit;
69 78
70 /// <summary> 79 /// <summary>
71 /// Default constructor 80 /// Default constructor
@@ -77,23 +86,81 @@ namespace OpenSim.Region.ClientStack.LindenUDP
77 { 86 {
78 IConfig throttleConfig = config.Configs["ClientStack.LindenUDP"]; 87 IConfig throttleConfig = config.Configs["ClientStack.LindenUDP"];
79 88
80 Resend = throttleConfig.GetInt("ResendDefault", 12500); 89 Resend = throttleConfig.GetInt("resend_default", 12500);
81 Land = throttleConfig.GetInt("LandDefault", 500); 90 Land = throttleConfig.GetInt("land_default", 500);
82 Wind = throttleConfig.GetInt("WindDefault", 500); 91 Wind = throttleConfig.GetInt("wind_default", 500);
83 Cloud = throttleConfig.GetInt("CloudDefault", 500); 92 Cloud = throttleConfig.GetInt("cloud_default", 500);
84 Task = throttleConfig.GetInt("TaskDefault", 500); 93 Task = throttleConfig.GetInt("task_default", 500);
85 Texture = throttleConfig.GetInt("TextureDefault", 500); 94 Texture = throttleConfig.GetInt("texture_default", 500);
86 Asset = throttleConfig.GetInt("AssetDefault", 500); 95 Asset = throttleConfig.GetInt("asset_default", 500);
96 State = throttleConfig.GetInt("state_default", 500);
87 97
88 ResendLimit = throttleConfig.GetInt("ResendLimit", 18750); 98 Total = throttleConfig.GetInt("client_throttle_max_bps", 0);
89 LandLimit = throttleConfig.GetInt("LandLimit", 29750); 99
90 WindLimit = throttleConfig.GetInt("WindLimit", 18750); 100 ResendLimit = throttleConfig.GetInt("resend_limit", 18750);
91 CloudLimit = throttleConfig.GetInt("CloudLimit", 18750); 101 LandLimit = throttleConfig.GetInt("land_limit", 29750);
92 TaskLimit = throttleConfig.GetInt("TaskLimit", 55750); 102 WindLimit = throttleConfig.GetInt("wind_limit", 18750);
93 TextureLimit = throttleConfig.GetInt("TextureLimit", 55750); 103 CloudLimit = throttleConfig.GetInt("cloud_limit", 18750);
94 AssetLimit = throttleConfig.GetInt("AssetLimit", 27500); 104 TaskLimit = throttleConfig.GetInt("task_limit", 18750);
105 TextureLimit = throttleConfig.GetInt("texture_limit", 55750);
106 AssetLimit = throttleConfig.GetInt("asset_limit", 27500);
107 State = throttleConfig.GetInt("state_limit", 37000);
108
109 TotalLimit = throttleConfig.GetInt("client_throttle_max_bps", 0);
95 } 110 }
96 catch (Exception) { } 111 catch (Exception) { }
97 } 112 }
113
114 public int GetRate(ThrottleOutPacketType type)
115 {
116 switch (type)
117 {
118 case ThrottleOutPacketType.Resend:
119 return Resend;
120 case ThrottleOutPacketType.Land:
121 return Land;
122 case ThrottleOutPacketType.Wind:
123 return Wind;
124 case ThrottleOutPacketType.Cloud:
125 return Cloud;
126 case ThrottleOutPacketType.Task:
127 return Task;
128 case ThrottleOutPacketType.Texture:
129 return Texture;
130 case ThrottleOutPacketType.Asset:
131 return Asset;
132 case ThrottleOutPacketType.State:
133 return State;
134 case ThrottleOutPacketType.Unknown:
135 default:
136 return 0;
137 }
138 }
139
140 public int GetLimit(ThrottleOutPacketType type)
141 {
142 switch (type)
143 {
144 case ThrottleOutPacketType.Resend:
145 return ResendLimit;
146 case ThrottleOutPacketType.Land:
147 return LandLimit;
148 case ThrottleOutPacketType.Wind:
149 return WindLimit;
150 case ThrottleOutPacketType.Cloud:
151 return CloudLimit;
152 case ThrottleOutPacketType.Task:
153 return TaskLimit;
154 case ThrottleOutPacketType.Texture:
155 return TextureLimit;
156 case ThrottleOutPacketType.Asset:
157 return AssetLimit;
158 case ThrottleOutPacketType.State:
159 return StateLimit;
160 case ThrottleOutPacketType.Unknown:
161 default:
162 return 0;
163 }
164 }
98 } 165 }
99} 166}
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 04eb93f..14e4534 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
@@ -2436,6 +2428,8 @@ namespace OpenSim.Region.Framework.Scenes
2436 /// <param name="client"></param> 2428 /// <param name="client"></param>
2437 public override void AddNewClient(IClientAPI client) 2429 public override void AddNewClient(IClientAPI client)
2438 { 2430 {
2431 ClientManager.Add(client);
2432
2439 CheckHeartbeat(); 2433 CheckHeartbeat();
2440 SubscribeToClientEvents(client); 2434 SubscribeToClientEvents(client);
2441 ScenePresence presence; 2435 ScenePresence presence;
@@ -2645,6 +2639,7 @@ namespace OpenSim.Region.Framework.Scenes
2645 public virtual void SubscribeToClientNetworkEvents(IClientAPI client) 2639 public virtual void SubscribeToClientNetworkEvents(IClientAPI client)
2646 { 2640 {
2647 client.OnNetworkStatsUpdate += StatsReporter.AddPacketsStats; 2641 client.OnNetworkStatsUpdate += StatsReporter.AddPacketsStats;
2642 client.OnViewerEffect += ProcessViewerEffect;
2648 } 2643 }
2649 2644
2650 protected virtual void UnsubscribeToClientEvents(IClientAPI client) 2645 protected virtual void UnsubscribeToClientEvents(IClientAPI client)
@@ -2799,11 +2794,9 @@ namespace OpenSim.Region.Framework.Scenes
2799 public virtual void UnSubscribeToClientNetworkEvents(IClientAPI client) 2794 public virtual void UnSubscribeToClientNetworkEvents(IClientAPI client)
2800 { 2795 {
2801 client.OnNetworkStatsUpdate -= StatsReporter.AddPacketsStats; 2796 client.OnNetworkStatsUpdate -= StatsReporter.AddPacketsStats;
2797 client.OnViewerEffect -= ProcessViewerEffect;
2802 } 2798 }
2803 2799
2804
2805
2806
2807 /// <summary> 2800 /// <summary>
2808 /// Teleport an avatar to their home region 2801 /// Teleport an avatar to their home region
2809 /// </summary> 2802 /// </summary>
@@ -3076,7 +3069,9 @@ namespace OpenSim.Region.Framework.Scenes
3076 agentTransactions.RemoveAgentAssetTransactions(agentID); 3069 agentTransactions.RemoveAgentAssetTransactions(agentID);
3077 } 3070 }
3078 3071
3072 // Remove the avatar from the scene
3079 m_sceneGraph.RemoveScenePresence(agentID); 3073 m_sceneGraph.RemoveScenePresence(agentID);
3074 ClientManager.Remove(agentID);
3080 3075
3081 try 3076 try
3082 { 3077 {
@@ -3126,16 +3121,6 @@ namespace OpenSim.Region.Framework.Scenes
3126 } 3121 }
3127 3122
3128 /// <summary> 3123 /// <summary>
3129 /// Closes all endpoints with the circuitcode provided.
3130 /// </summary>
3131 /// <param name="circuitcode">Circuit Code of the endpoint to close</param>
3132 public override void CloseAllAgents(uint circuitcode)
3133 {
3134 // Called by ClientView to kill all circuit codes
3135 ClientManager.CloseAllAgents(circuitcode);
3136 }
3137
3138 /// <summary>
3139 /// Inform all other ScenePresences on this Scene that someone else has changed position on the minimap. 3124 /// Inform all other ScenePresences on this Scene that someone else has changed position on the minimap.
3140 /// </summary> 3125 /// </summary>
3141 public void NotifyMyCoarseLocationChange() 3126 public void NotifyMyCoarseLocationChange()
@@ -3456,7 +3441,7 @@ namespace OpenSim.Region.Framework.Scenes
3456 loggingOffUser.ControllingClient.Kick(message); 3441 loggingOffUser.ControllingClient.Kick(message);
3457 // Give them a second to receive the message! 3442 // Give them a second to receive the message!
3458 Thread.Sleep(1000); 3443 Thread.Sleep(1000);
3459 loggingOffUser.ControllingClient.Close(true); 3444 loggingOffUser.ControllingClient.Close();
3460 } 3445 }
3461 else 3446 else
3462 { 3447 {
@@ -3627,7 +3612,7 @@ namespace OpenSim.Region.Framework.Scenes
3627 presence.ControllingClient.SendShutdownConnectionNotice(); 3612 presence.ControllingClient.SendShutdownConnectionNotice();
3628 } 3613 }
3629 3614
3630 presence.ControllingClient.Close(true); 3615 presence.ControllingClient.Close();
3631 return true; 3616 return true;
3632 } 3617 }
3633 3618
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/Services/AssetService/AssetService.cs b/OpenSim/Services/AssetService/AssetService.cs
index ebfd47a..df33db2 100644
--- a/OpenSim/Services/AssetService/AssetService.cs
+++ b/OpenSim/Services/AssetService/AssetService.cs
@@ -64,12 +64,17 @@ namespace OpenSim.Services.AssetService
64 string loaderArgs = assetConfig.GetString("AssetLoaderArgs", 64 string loaderArgs = assetConfig.GetString("AssetLoaderArgs",
65 String.Empty); 65 String.Empty);
66 66
67 m_log.InfoFormat("[ASSET]: Loading default asset set from {0}", loaderArgs); 67 bool assetLoaderEnabled = assetConfig.GetBoolean("AssetLoaderEnabled", true);
68 m_AssetLoader.ForEachDefaultXmlAsset(loaderArgs, 68
69 delegate(AssetBase a) 69 if (assetLoaderEnabled)
70 { 70 {
71 Store(a); 71 m_log.InfoFormat("[ASSET]: Loading default asset set from {0}", loaderArgs);
72 }); 72 m_AssetLoader.ForEachDefaultXmlAsset(loaderArgs,
73 delegate(AssetBase a)
74 {
75 Store(a);
76 });
77 }
73 78
74 m_log.Info("[ASSET CONNECTOR]: Local asset service enabled"); 79 m_log.Info("[ASSET CONNECTOR]: Local asset service enabled");
75 } 80 }
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/bin/OpenSim.ini.example b/bin/OpenSim.ini.example
index 5cb51b2..983a7e5 100644
--- a/bin/OpenSim.ini.example
+++ b/bin/OpenSim.ini.example
@@ -341,25 +341,6 @@
341 341
342 342
343[ClientStack.LindenUDP] 343[ClientStack.LindenUDP]
344 ; This is the multiplier applied to all client throttles for outgoing UDP network data
345 ; If it is set to 1, then we obey the throttle settings as given to us by the client. If it is set to 3, for example, then we
346 ; multiply that setting by 3 (e.g. if the client gives us a setting of 250 kilobits per second then we
347 ; will actually push down data at a maximum rate of 750 kilobits per second).
348 ;
349 ; In principle, setting a multiplier greater than 1 will allow data to be pushed down to a client much faster
350 ; than its UI allows the setting to go. This may be okay in some situations, such as standalone OpenSim
351 ; applications on a LAN. However, the greater the multipler, the higher the risk of packet drop, resulting
352 ; in symptoms such as missing terrain or objects. A much better solution is to change the client UI to allow
353 ; higher network bandwidth settings directly, though this isn't always possible.
354 ;
355 ; Currently this setting is 2 by default because we currently send much more texture data than is strictly
356 ; necessary. A setting of 1 could result in slow texture transfer. This will be fixed when the transfer
357 ; of textures at different levels of quality is improved.
358 ;
359 ; Pre r7113, this setting was not exposed but was effectively 8. You may want to try this if you encounter
360 ; unexpected difficulties
361 client_throttle_multiplier = 2;
362
363 ; the client socket receive buffer size determines how many 344 ; the client socket receive buffer size determines how many
364 ; incoming requests we can process; the default on .NET is 8192 345 ; incoming requests we can process; the default on .NET is 8192
365 ; which is about 2 4k-sized UDP datagrams. On mono this is 346 ; which is about 2 4k-sized UDP datagrams. On mono this is
@@ -374,12 +355,42 @@
374 ; by the system's settings for the maximum client receive buffer 355 ; by the system's settings for the maximum client receive buffer
375 ; size (on linux systems you can set that with "sysctl -w 356 ; size (on linux systems you can set that with "sysctl -w
376 ; net.core.rmem_max=X") 357 ; net.core.rmem_max=X")
377 ; 358 ;client_socket_rcvbuf_size = 8388608
378 ; client_socket_rcvbuf_size = 8388608 359
379 360 ; Maximum outbound bytes per second for a single scene. This can be used to
380 ; Maximum bits per second to send to any single client. This will override the user's viewer preference settings. 361 ; throttle total outbound UDP traffic for a simulator. The default value is
381 362 ; 0, meaning no throttling at the scene level. The example given here is
382 ; client_throttle_max_bps = 1500000 363 ; 20 megabits
364 ;scene_throttle_max_bps = 2621440
365
366 ; Maximum bits per second to send to any single client. This will override
367 ; the user's viewer preference settings. The default value is 0, meaning no
368 ; aggregate throttling on clients (only per-category throttling). The
369 ; example given here is 1.5 megabits
370 ;client_throttle_max_bps = 196608
371
372 ; Per-client bytes per second rates for the various throttle categories.
373 ; These are default values that will be overriden by clients
374 ;resend_default = 12500
375 ;land_default = 500
376 ;wind_default = 500
377 ;cloud_default = 50
378 ;task_default = 500
379 ;texture_default = 500
380 ;asset_default = 500
381 ;state_default = 500
382
383 ; Per-client maximum burst rates in bytes per second for the various
384 ; throttle categories. These are default values that will be overriden by
385 ; clients
386 ;resend_limit = 18750
387 ;land_limit = 29750
388 ;wind_limit = 18750
389 ;cloud_limit = 18750
390 ;task_limit = 18750
391 ;texture_limit = 55750
392 ;asset_limit = 27500
393 ;state_limit = 37000
383 394
384[Chat] 395[Chat]
385 ; Controls whether the chat module is enabled. Default is true. 396 ; Controls whether the chat module is enabled. Default is true.
@@ -1381,6 +1392,10 @@
1381[AssetService] 1392[AssetService]
1382 DefaultAssetLoader = "OpenSim.Framework.AssetLoader.Filesystem.dll" 1393 DefaultAssetLoader = "OpenSim.Framework.AssetLoader.Filesystem.dll"
1383 AssetLoaderArgs = "assets/AssetSets.xml" 1394 AssetLoaderArgs = "assets/AssetSets.xml"
1395
1396 ; Disable this to prevent the default asset set from being inserted into the
1397 ; asset store each time the region starts
1398 AssetLoaderEnabled = true
1384 1399
1385[GridService] 1400[GridService]
1386 ;; default standalone, overridable in StandaloneCommon.ini 1401 ;; default standalone, overridable in StandaloneCommon.ini
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